次の方法で共有


Java Spring Boot アプリによるユーザーのサインインと Microsoft Graph へのアクセスを有効にする

この記事では Spring Boot Web アプリについて、ユーザーのサインインと、Microsoft Graph を呼び出すために必要なアクセス トークンの取得機能を紹介します。 Java 用 Microsoft Entra ID Spring Boot Starter クライアント ライブラリを使用して、認証、承認、トークン取得を行います。 Graph からのデータの取得には、Microsoft Graph SDK for Java を使用します。

次の図は、アプリのトポロジを示しています。

アプリのトポロジを示す図。

このアプリは Java 用 Microsoft Entra ID Spring Boot Starter クライアント ライブラリを使用して、Microsoft Entra ID から Microsoft Graphアクセス トークンを取得します。 アクセス トークンにより、ユーザーはスコープで定義されているとおり、Microsoft Graph API エンドポイントにアクセスする権限を持つことが証明されます。

前提条件

推奨事項

  • Spring Framework に関するある程度の知識。
  • Linux/OSX ターミナルに関するある程度の知識。
  • トークンの検査に必要な jwt.ms
  • ネットワークの活動監視とトラブルシューティングに必要な Fiddler
  • 開発に関する最新の情報について、Microsoft Entra ID ブログを確認してください。

サンプルのセットアップ

次のセクションでは、サンプル アプリケーションを設定する方法を示します。

サンプル リポジトリを複製またはダウンロードする

サンプルを複製するには、Bash ウィンドウを開き、次のコマンドを使用します。

git clone https://github.com/Azure-Samples/ms-identity-msal-java-samples.git
cd 4-spring-web-app/2-Authorization-I/call-graph

または、ms-identity-msal-java-samples リポジトリに移動し、.zip ファイルでダウンロードして、ハード ドライブに展開します。

重要

Windows でファイル パスの長さが制限を超える場合は、ハード ドライブのルート近くのディレクトリにリポジトリを複製または展開してください。

Microsoft Entra ID テナントにサンプル アプリケーションを登録する

このサンプルには、プロジェクトが 1 つ存在します。 以下の各セクションでは、Azure portal を使用してアプリを登録する方法を説明します。

アプリケーションを作成する Microsoft Entra ID テナントを選択する

テナントを選択するには、次の手順に従います。

  1. Azure portal にサインインします。

  2. ご利用のアカウントが複数の Microsoft Entra ID テナントに存在する場合は、Azure portal の隅にあるプロファイルを選択し、ディレクトリの切り替えを選択して、セッションを目的の Microsoft Entra ID テナントに変更します。

アプリを登録する (java-servlet-webapp-call-graph)

アプリを登録するには、次の手順に従います。

  1. Azure portal に移動し、Microsoft Entra ID を選択します。

  2. ナビゲーション ペインでアプリの登録を選択し、新しい登録を選択します。

  3. 表示される アプリケーションの登録ページで、アプリケーションの登録情報を入力します。

    • 名前セクションに、アプリのユーザーに表示されるわかりやすいアプリケーション名を入力します (例: java-spring-webapp-call-graph)。
    • [サポートされているアカウントの種類] で、 [この組織のディレクトリ内のアカウントのみ] を選択します。
    • [リダイレクト URI (省略可能)] セクションで、コンボボックスの [Web] を選択し、リダイレクト URI 「http://localhost:8080/login/oauth2/code/」を入力します。
  4. [登録] を選択して、アプリケーションを作成します。

  5. アプリの登録ページで、アプリケーション (クライアント) ID の値を見つけてメモします。 この値は、後ほどアプリの構成ファイルで使用します。

  6. アプリの登録ページで、ナビゲーション ペインにある 証明書とシークレットを選択してページを開き、シークレットの生成と証明書のアップロードを行います。

  7. [クライアント シークレット] セクションで、 [新しいクライアント シークレット] を選択します。

  8. キーの説明 (例: アプリのシークレット) を入力します。

  9. 1 年2 年無期限のいずれかの期間を選びます。

  10. [追加] を選択します。 生成された値が表示されます。

  11. 生成した値をコピーしてから保存します。 この値は後ほど、コードの構成ファイルに使用します。 この値は二度と表示されず、他の方法でも取得はできません。 そのため、必ず Azure portal から保存した後に、他の画面やペインに移動してください。

  12. アプリの登録ページで、ナビゲーション ペインから API のアクセス許可を選択してページを開き、アプリケーションで必要となる API にアクセスします。

  13. アクセス許可の追加を選択し、Microsoft API タブが選択されていることを確認します。

  14. [よく使用される Microsoft API] セクションで、 [Microsoft Graph] を選択します。

  15. [委任されたアクセス許可] セクションで、一覧から [User.Read] を選択します。 必要に応じて検索ボックスを使用します。

  16. [アクセス許可の追加] を選択します.


アプリの登録を使用するためにアプリ (java-spring-webapp-call-graph) を構成する

アプリを構成するには、次の手順に従います。

Note

以降の手順では、ClientIDApplication ID または AppId と同じです。

  1. IDE でプロジェクトを開きます。

  2. src\main\resources\application.yml ファイルを開きます。

  3. プレースフォルダー Enter_Your_Tenant_ID_Here を見つけて、既存の値を Microsoft Entra テナント ID に置き換えます。

  4. Enter_Your_Client_ID_Here のプレースフォルダーを見つけて、既存の値をアプリケーション ID または Azure portal からコピーした java-spring-webapp-call-graph アプリの clientId に変更します。

  5. Enter_Your_Client_Secret_Here のプレースフォルダーを見つけて、既存の値を Azure portal からコピーした、java-spring-webapp-call-graph の作成時に保存した値に置き換えます。

サンプルを実行する

以降のセクションでは、サンプルを Azure Container Apps にデプロイする方法を紹介します。

前提条件

  • Azure アカウント。 アカウントがない場合は、 無料アカウントを作成してください。 続行するには、Azure サブスクリプションの "共同作成者" または "所有者" のアクセス許可が必要です。 詳細については、Azure portal を使用して Azure ロールを割り当てる方法に関するページを参照してください。
  • Azure CLI
  • Azure Container Apps CLI 拡張機能バージョン 0.3.47 以上。 最新バージョンをインストールするには、az extension add --name containerapp --upgrade --allow-preview コマンドを使用します。
  • Java Development Kit バージョン 17 以上。
  • Maven

Spring プロジェクトを準備する

次の手順を実行して、プロジェクトを準備します。

  1. 次の Maven コマンドを使用して、プロジェクトをビルドします。

    mvn clean verify
    
  2. 次のコマンドを使用して、サンプル プロジェクトをローカルで実行します。

    mvn spring-boot:run
    

セットアップ

CLI から Azure にサインインするには、次のコマンドを実行し、プロンプトに従って認証プロセスを完了します。

az login

最新バージョンの CLI を実行していることを確認するには、upgrade コマンドを実行します。

az upgrade

次に、CLI 用の Azure Container Apps 拡張機能をインストールまたは更新します。

Azure CLI で az containerapp コマンドを実行するときにパラメーターが見つからないというエラーが表示された場合には、最新バージョンの Azure Container Apps 拡張機能がインストールされていることを確認してください。

az extension add --name containerapp --upgrade

Note

2024 年 5 月以降、Azure CLI 拡張機能では、既定でプレビュー機能が有効になりません。 Container Apps のプレビュー機能にアクセスするには、--allow-preview true を使用して Container Apps 拡張機能をインストールします。

az extension add --name containerapp --upgrade --allow-preview true

最新の拡張機能またはモジュールがインストールされたので、Microsoft.App および Microsoft.OperationalInsights 名前空間を登録します。

Note

Azure Container Apps リソースは、Microsoft.Web 名前空間から Microsoft.App 名前空間に移行されました。 詳細については、「2022 年 3 月に Microsoft.Web から Microsoft.App に名前空間を移行する」を参照してください。

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

Azure Container Apps 環境を作成する

Azure CLI のセットアップが完了したところで、この記事全体で使用される環境変数を定義できます。

bash シェルで次の変数を定義します。

export RESOURCE_GROUP="ms-identity-containerapps"
export LOCATION="canadacentral"
export ENVIRONMENT="env-ms-identity-containerapps"
export API_NAME="ms-identity-api"
export JAR_FILE_PATH_AND_NAME="./target/ms-identity-spring-boot-webapp-0.0.1-SNAPSHOT.jar"

リソース グループを作成する。

az group create  \
    --name $RESOURCE_GROUP \
    --location $LOCATION \

自動生成されたログ分析ワークスペースを使用して環境を作成します。

az containerapp env create \
    --name $ENVIRONMENT \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION

コンテナー アプリ環境の既定のドメインを表示します。 このドメインは、後のセクションで使用するためにメモしておきます。

az containerapp env show \
    --name $ENVIRONMENT \
    --resource-group $RESOURCE_GROUP \
    --query properties.defaultDomain

アプリのデプロイを準備する

アプリケーションを Azure Container Apps にデプロイすると、リダイレクト URL は、Azure Container Apps にデプロイされたアプリ インスタンスのリダイレクト URL に変更されます。 application.yml ファイルでこれらの設定を変更するには、次の手順に従います。

  1. アプリの src\main\resources\application.yml ファイルに移動し、post-logout-redirect-uri の値をデプロイされたアプリのドメイン名に変更します (次の例を参照)。 <API_NAME><default-domain-of-container-app-environment> は実際の値に置き換えてください。 たとえば、前の手順の Azure Container Apps 環境の既定のドメインを使用し、アプリ名に ms-identity-api を使用する場合、post-logout-redirect-uri 値には https://ms-identity-api.<default-domain> を使用します。

    post-logout-redirect-uri: https://<API_NAME>.<default-domain-of-container-app-environment>
    
  2. このファイルを保存した後、次のコマンドを使用してアプリをリビルドします。

    mvn clean package
    

重要

アプリケーションの application.yml ファイルには、クライアント シークレットの値が client-secret パラメーターに格納されています。 この値をこのファイルに保持しないでください。 また、ファイルを Git リポジトリにコミットすると、リスクが生じる可能性があります。 推奨される方法については、「Azure Container Apps でシークレットを管理する」を参照してください。

Microsoft Entra IDアプリの登録を更新する

リダイレクト URI は Azure Container Apps にデプロイされたアプリに変更されるため、Microsoft Entra ID アプリの登録でも、リダイレクト URI を変更する必要があります。 次の手順に従って、この変更を行います。

  1. 開発者用の Microsoft ID プラットフォームの [アプリの登録] ページに移動します。

  2. 検索ボックスを使用してアプリの登録を検索します (例: java-servlet-webapp-authentication)。

  3. 名前を選択して、アプリの登録を開きます。

  4. コマンドメニューから 認証 を選択します。

  5. Web - リダイレクト URI セクションで、URI の追加を選択します。

  6. アプリの URI を、/login/oauth2/code/ を追加して入力します。たとえば https://<containerapp-name>.<default domain of container app environment>/login/oauth2/code/ のようになります。

  7. [保存] を選択します。

アプリケーションのデプロイ

JAR パッケージを Azure Container Apps にデプロイします。

Note

必要に応じて、Java ビルド環境変数で JDK のバージョンを指定できます。 詳細については、Azure Container Apps の Java 用ビルド環境変数に関する記事を参照してください。

これで、az containerapp up CLI コマンドを使って WAR ファイルをデプロイできるようになります。

az containerapp up \
    --name $API_NAME \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION \
    --environment $ENVIRONMENT \
    --artifact <JAR_FILE_PATH_AND_NAME> \
    --ingress external \
    --target-port 8080 \
    --query properties.configuration.ingress.fqdn

Note

既定の JDK バージョンは 17 です。 アプリケーションとの互換性のために JDK のバージョンを変更する必要がある場合は、--build-env-vars BP_JVM_VERSION=<YOUR_JDK_VERSION> 引数を使ってバージョン番号を調整できます。

ビルド環境変数の詳細については、Azure Container Apps の Java 用ビルド環境変数に関する記事を参照してください。

アプリを検証する

この例では、containerapp up コマンドに --query properties.configuration.ingress.fqdn 引数が含まれており、完全修飾ドメイン名 (FQDN) (アプリの URL とも呼ばれます) を返します。 次の手順を使用して、アプリのログをチェックし、デプロイの問題があれば調査します。

  1. デプロイメント セクションの出力ページから出力アプリケーションの URL にアクセスします。

  2. Azure Container Apps インスタンスの[概要] ページのナビゲーション ウィンドウで、[ログ] を選択してアプリのログを確認します。

サンプルの確認

次の手順に従ってサンプルを操作します。

  1. サインインまたはサインアウトの状態が、画面の中央に表示されます。
  2. 画面の隅にある状況依存ボタンを選択します。 このボタンは、アプリを最初に実行するときにサインインと表示します。 または、トークンの詳細Graph を呼び出すを選択します。 このページは保護されており、認証が必要であるため、サインイン ページに自動でリダイレクトされます。
  3. 次のページに記載された指示に従い、Microsoft Entra ID テナントのアカウントでサインインします。
  4. 同意画面に、必要となるスコープが表示されます。
  5. サインイン フローが正常に完了するとホーム ページにリダイレクトされ、どのボタンでサインイン フローをトリガーした化に応じて、サインインの状態ページまたは他のいずれかのページが表示されます。
  6. 状況依存ボタンの表示がサインアウトに変わり、ユーザー名が表示されます。
  7. ホーム ページを表示している場合は、IDトークンの詳細を選択して、IDトークンのデコードされた要求の一部を表示します。
  8. Graph を呼び出すを選択して Microsoft Graph の /me エンドポイント を呼び出し、取得したユーザーの詳細の選択を確認します。
  9. 隅にあるボタンを使用してサインアウトします。新しい状態が状態ページに反映されます。

コードについて

このサンプルでは、Java 用 Microsoft Entra ID Spring Boot Starter クライアント ライブラリを使用して、Microsoft Entra ID テナントへのユーザーのサインインを行い、Microsoft Graph を呼び出すためにアクセス トークンを取得する方法を示します。 このサンプルでは、Spring Oauth2 クライアントと Spring Web ブート スターターも使用します。

Contents

次の表に、サンプル プロジェクト フォルダーの内容を示します。

ファイル/フォルダー 説明
pom.xml アプリケーションの依存関係。
src/main/resources/templates/ UI 用の Thymeleaf テンプレート。
src/main/resources/application.yml アプリケーションと Microsoft Entra ID Boot Starter ライブラリの構成。
src/main/java/com/microsoft/azuresamples/msal4j/msidentityspringbootwebapp/ このディレクトリには、メイン アプリケーションのエントリ ポイント、コントローラー、および構成のクラスが含まれています。
.../MsIdentitySpringBootWebappApplication.java Main クラス。
.../SampleController.java エンドポイントをマッピングするコントローラー。
.../SecurityConfig.java セキュリティ構成 - たとえば、認証が必要なルートを構成します。
.../Utilities.java ユーティリティ クラス - たとえば、ID トークン要求をフィルター処理します。
CHANGELOG.md サンプルに対する変更の一覧。
CONTRIBUTING.md サンプルに貢献するためのガイドライン。
ライセンス サンプルのライセンス。

ID トークン要求

アプリはトークンの詳細を抽出するために、要求マッピングで Spring Security の AuthenticationPrincipalOidcUser のオブジェクトを使用します (次の例を参照)。 このアプリで ID トークン要求を使用する方法については、サンプル コントローラーを参照してください。

import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
//...
@GetMapping(path = "/some_path")
public String tokenDetails(@AuthenticationPrincipal OidcUser principal) {
    Map<String, Object> claims = principal.getIdToken().getClaims();
}

アプリはサインインを行う際に、Java 用 Microsoft Entra ID Spring Boot Starter クライアント ライブラリで自動的に構成された Microsoft Entra ID サインイン エンドポイントに対して要求を行います (次の例を参照)。

<a class="btn btn-success" href="/oauth2/authorization/azure">Sign In</a>

アプリはサインアウトを行う際に、logout エンドポイントへの POST 要求を行います (次の例を参照)。

<form action="#" th:action="@{/logout}" method="post">
  <input class="btn btn-warning" type="submit" value="Sign Out" />
</form>

認証に依存する UI 要素

アプリの UI テンプレート ページに、ユーザーが認証済みかどうかに応じて表示するコンテンツを決定するためのシンプルなロジックがあります (Spring Security Thymeleaf タグを使用した次の例を参照)。

<div sec:authorize="isAuthenticated()">
  this content only shows to authenticated users
</div>
<div sec:authorize="isAnonymous()">
  this content only shows to not-authenticated users
</div>

AADWebSecurityConfigurerAdapter を使用してルートを保護する

既定では、アプリは ID トークンの詳細ページと Graph の呼び出しページを保護するため、サインインしているユーザーのみがそれらのページにアクセスできます。 アプリは、application.yml ファイルにある app.protect.authenticated プロパティで、これらのルートを構成します。 アプリの特定の要件を構成するには、いずれのクラスで AADWebSecurityConfigurationAdapter を拡張します。 例については、このアプリの SecurityConfig クラスを参照してください (次の例を参照)。

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends AADWebSecurityConfigurerAdapter{
  @Value( "${app.protect.authenticated}" )
  private String[] protectedRoutes;

    @Override
    public void configure(HttpSecurity http) throws Exception {
    // use required configuration form AADWebSecurityAdapter.configure:
    super.configure(http);
    // add custom configuration:
    http.authorizeRequests()
      .antMatchers(protectedRoutes).authenticated()     // limit these pages to authenticated users (default: /token_details, /call_graph)
      .antMatchers("/**").permitAll();                  // allow all other routes.
    }
}

グラフの呼び出し

ユーザーが /call_graph に移動すると、アプリケーションは Microsoft Entra ID ブート スターターが準備した Oauth2AuthorizedClient または graphAuthorizedClient を使用して GraphServiceClient を作成します。 アプリは /me エンドポイントの呼び出しを GraphServiceClient に要求し、現在サインインしているユーザーの詳細を表示します。 GraphServiceClient は、Microsoft Graph SDK for Java v3 にあります。

Oauth2AuthorizedClientを正しいスコープで準備する必要があります。 application.yml ファイルと次のスコープセクションを参照してください。 Oauth2AuthorizedClient はアクセス トークンを表示し、それを GraphServiceClient 要求の Authorization ヘッダーに入力するために使用されます (次の例を参照)。

//see SampleController.java
@GetMapping(path = "/call_graph")
public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graphAuthorizedClient) {
  // See the Utilities.graphUserProperties() method for the full example of the following operation:
  GraphServiceClient graphServiceClient = Utilities.getGraphServiceClient(graphAuthorizedClient);
  User user = graphServiceClient.me().buildRequest().get();
  return user.displayName;
}

application.yml ファイルにある次の例は、要求されたスコープを示しています。

# see application.yml file
authorization-clients:
  graph:
    # Specifies the Microsoft Graph scopes that your app needs access to:
    scopes: https://graph.microsoft.com/User.Read

スコープ

スコープはアプリケーションが要求するアクセス レベルを Microsoft Entra ID に通知します。 このアプリケーションが要求する Microsoft Graph のスコープについては、application.yml を参照してください。

既定では、アプリケーションはスコープの値を https://graph.microsoft.com/User.Read に設定します。 User.Read のスコープは、現在サインインしているユーザーの情報に /me endpoint からアクセスするためのものです。 /me エンドポイントへの要求には、User.Read スコープを含める必要があります。

ユーザーがサインインすると、Microsoft Entra ID は、アプリケーションで要求されたスコープに基づいて、ユーザーに同意ダイアログを表示します。 ユーザーが 1 つ以上のスコープに同意してトークンを取得すると、その同意先スコープが結果のアクセス トークンにエンコードされます。

このアプリでは、graphAuthorizedClient によってアクセス トークンが表示され、ユーザーが同意したスコープが提示されます。 アプリはこのトークンを使用して、Graph 要求を処理する GraphServiceClient のインスタンスを作成します。

GraphServiceClient.me().buildRequest().get() を使用すると要求がビルドされ、https://graph.microsoft.com/v1.0/me に作成されます。 アクセス トークンは、要求の Authorization ヘッダーに配置されます。

詳細

このシナリオおよびその他のシナリオでの OAuth 2.0 プロトコルの動作の詳細については、「Microsoft Entra ID の認証シナリオ」を参照してください。