XSUAAでOAuth2.0認証のREST APIを作成します。内部的にはSAP Cloud SDK for Javaを使っています。
OAuth2.0の リソースオーナー・パスワード・クレデンシャルズフローを使っています。
Client Credentials Flowを使った
記事「OAuth2.0認証のREST API作成(SAP Cloud SDK for Java使用) Client Credentials Flow」も書きました。
記事「CFでApp Router, XSUAAとJava Application開発(SAP Cloud SDK使用)」のApp Routerがなく、APIでのアクセスをしている形です。
別記事「Create REST APIs secured with XSUAA in Cloud Foundry environment and call REST APIs in ABAP envi...を参考にしました。
開発環境
以下の環境で実行しています。
- OS: Windows10 64-bit
- openJDK: 1.8.0_252
- Chocolatey: 0.10.15
- maven: 3.6.3
- IDE: IntelliJ IDEA Community Edition 2019.3.3
- CF cli: 6.51.0+2acd15650.2020-04-07
- SAP Cloud SDK for Java: 3.20.0
手順
1. Java プロジェクト作成
まずは、コマンドプロンプトからmavenでプロジェクト作成。
mvn archetype:generate "-DarchetypeGroupId=com.sap.cloud.sdk.archetypes" "-DarchetypeArtifactId=scp-cf-tomee" "-DarchetypeVersion=RELEASE"
途中のプロンプトでは以下を入力。”artifactId”に入力した”rest-oauth”がApplication名です。
- groupId: com.sap.cloud.sdk
- artifactId: rest-oauth
- version: 1.0-SNAPSHOT
- package: com.sap.cloud.sdk
2. XSUAAサービス作成
まずは準備です。
プロジェクトルート直下にファイル".cfignore"を作成。定義したファイル/フォルダがCFへデプロイするときに無視されます(.gitignore感覚)。
# exclude xsuaa folder
/xsuaa
で、プロジェクトルート直下にディレクトリ"xsuaa"を作成し、そこにファイル"xs-security.json"を作成。
{
"xsappname": "rest-oauth",
"tenant-mode": "dedicated",
"scopes": [
{
"name": "$XSAPPNAME.Display",
"description": "display"
}
],
"role-templates": [
{
"name": "Viewer",
"description": "Required to view things in our solution",
"scope-references" : [
"$XSAPPNAME.Display"
]
}
]
}
カレントディレクトリを"xsuaa"にしてcf cliでxsuaaサービスを作成。
cf create-service xsuaa application my-xsuaa -c xs-security.json
3. Java開発
"application/src/main/webapp/WEB-INF/web.xml"を変更します。コメントアウトされている以下の認証認可の部分を有効化します。
<login-config>
<auth-method>XSUAA</auth-method>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Baseline Security</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>Display</role-name>
</security-role>
Cloud SDKで初期作成されているHelloWorldServletを変更。以下のコードをクラス宣言前に追加し、関連するクラスをインポートします。
@ServletSecurity(@HttpConstraint(rolesAllowed = { "Display" }))
ソース全体です。
package com.sap.cloud.sdk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/hello")
@ServletSecurity(@HttpConstraint(rolesAllowed = { "Display" }))
public class HelloWorldServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(HelloWorldServlet.class);
@Override
protected void doGet( final HttpServletRequest request, final HttpServletResponse response )
throws IOException
{
logger.info("I am running!");
response.getWriter().write("Hello World!");
}
}
プロジェクト全体をビルドします。
# from project root directory
mvn clean install
4. CFへデプロイ
manifest.ymlを変更します。サービスにXSUAAを紐付けしています。
---
applications:
- name: rest-oauth
memory: 1024M
timeout: 300
random-route: true
path: application/target/rest-oauth-application.war
buildpacks:
- sap_java_buildpack
env:
TARGET_RUNTIME: tomee7
SET_LOGGING_LEVEL: '{ROOT: INFO, com.sap.cloud.sdk: INFO}'
JBP_CONFIG_SAPJVM_MEMORY_SIZES: 'metaspace:128m..'
services:
# - my-application-logs
- my-xsuaa
# - my-destination
# - my-connectivity
cliでデプロイします。
cf push
5. Role系設定
SAP Cloud CockpitからRole系の設定をします。内容は
記事「CFでApp Router, XSUAAとJava Application開発(SAP Cloud SDK使用)」の「4. Role定義」の4.1以外と同じなので割愛します。
結果とAPIアクセス
これでブラウザからJavaアプリケーションにアクセスしようとしても401(Unauthorized)となります。
POSTMANからTokenを取得して、APIにアクセスしてみます。
XSUAA情報取得
まずはSAP Cloud CockpitからXSUAAの情報を取得します。
作成したXSUAAのReferencing Appsを開きます。以降で使うのはclientid, clientsecretとurlです。
※cf cliでも"cf env <app name>"で取得できるようです(bindされていれば)。

Token取得
まずは認証サーバからTokenを取得します。Bodyの値のタイプがx-www-form-urlencodedであることに注意します。
項目 |
設定値 |
エンドポイント |
XSUAAの"url"の値 + /oauth/token |
HTTP メソッド |
POST |
BodyのKey Value(grant_type) |
固定値"password" |
BodyのKey Value(username) |
ロール定義で割り当てたアカウントのメールアドレス |
BodyのKey Value(password) |
ロール定義で割り当てたアカウントのパスワード |
BodyのKey Value(client_id) |
XSUAAの"clientid"の値 |
BodyのKey Value(client_secret) |
XSUAAの"clientsecret"の値 |
BodyのKey Value(response_type) |
固定値"token" |

API呼出
取得したTokenを使ってAPIを呼び出します。呼出先はJavaのアプリケーションのエンドポイントにパスとして"/hello"をつけています(今回のエンドポイントはrandomで振られています)。
HTTP HeaderのKeyを"Authorization"にしてValueに"Bearer"と取得したToken(responseの"access_token"の値)を半角スペース区切りで結合してセットします。
"Hello World!"が返ってきて成功です。