Microsoft Entra ID を使用して Java Spring Boot アプリをセキュリティで保護する
[アーティクル] 2024/10/14
4 人の共同作成者
フィードバック
この記事の内容
前提条件
推奨事項
サンプルのセットアップ
サンプルを実行する
セットアップ
Azure Container Apps 環境を作成する
サンプルの確認
コードについて
詳細
さらに 5 個を表示
この記事では、Java 用 Microsoft Entra ID Spring Boot Starterクライアント ライブラリ を使用して Microsoft Entra ID テナントのユーザーのサインインを行う Java Spring Boot Web アプリについて説明します。 OpenID Connect プロトコルを使用します。
次の図は、アプリのトポロジを示しています。
クライアント アプリは、Java 用 Microsoft Entra ID Spring Boot Starter クライアント ライブラリを使用してユーザーのサインインを行い、Microsoft Entra ID から ID トークンを取得します。 ID トークンにより、ユーザーが Microsoft Entra ID で認証され、保護されたルートにアクセスできることが証明されます。
次のセクションでは、サンプル アプリケーションを設定する方法を示します。
サンプルを複製するには、Bash ウィンドウを開き、次のコマンドを使用します。
git clone https://github.com/Azure-Samples/ms-identity-msal-java-samples.git
cd 4-spring-web-app/1-Authentication/sign-in
または、ms-identity-msal-java-samples リポジトリに移動し、.zip ファイルでダウンロードして、ハード ドライブに展開します。
重要
Windows のパスの長さ制限によって発生するエラーを回避するために、ドライブのルート近くのディレクトリにクローンを作成することをお勧めします。
Microsoft Entra ID テナントにサンプル アプリケーションを登録する
このサンプルには、プロジェクトが 1 つ存在します。 以下の各セクションでは、Azure portal を使用してアプリを登録する方法を説明します。
アプリケーションを作成する Microsoft Entra ID テナントを選択する
テナントを選択するには、次の手順に従います。
Azure portal にサインインします。
ご利用のアカウントが複数の Microsoft Entra ID テナントに存在する場合は、Azure portal の隅にあるプロファイルを選択し、ディレクトリの切り替え を選択して、セッションを目的の Microsoft Entra ID テナントに変更します。
アプリを登録する (java-spring-webapp-auth)
アプリを登録するには、次の手順に従います。
Azure portal に移動し、Microsoft Entra ID を選択します。
ナビゲーション ペインでアプリの登録 を選択し、新しい登録 を選択します。
表示される アプリケーションの登録ページ で、アプリケーションの登録情報を入力します。
名前 セクションに、アプリのユーザーに表示されるわかりやすいアプリケーション名を入力します (例: java-spring-webapp-auth
)。
[サポートされているアカウントの種類] で、 [この組織のディレクトリ内のアカウントのみ] を選択します。
[リダイレクト URI (省略可能)] セクションで、コンボボックスの [Web] を選択し、リダイレクト URI 「http://localhost:8080/login/oauth2/code/
」を入力します。
[登録] を選択して、アプリケーションを作成します。
アプリの登録ページで、アプリケーション (クライアント) ID の値を見つけてメモします。 この値は、後ほどアプリの構成ファイルで使用します。
アプリの登録ページで、ナビゲーション ペインにある 証明書とシークレット を選択してページを開き、シークレットの生成と証明書のアップロードを行います。
[クライアント シークレット] セクションで、 [新しいクライアント シークレット] を選択します。
キーの説明 (例: アプリのシークレット ) を入力します。
1 年 、2 年 、無期限 のいずれかの期間を選びます。
[追加] を選択します。 生成された値が表示されます。
生成した値をコピーしてから保存します。 この値は後ほど、コードの構成ファイルに使用します。 この値は二度と表示されず、他の方法でも取得はできません。 そのため、必ず Azure portal から保存した後に、他の画面やペインに移動してください。
アプリを構成するには、次の手順に従います。
注意
以降の手順では、ClientID
は Application ID
または AppId
と同じです。
IDE でプロジェクトを開きます。
src\main\resources\application.yml ファイルを開きます。
プレースフォルダー Enter_Your_Tenant_ID_Here
を見つけて、既存の値を Microsoft Entra テナント ID に置き換えます。
Enter_Your_Client_ID_Here
のプレースフォルダーを見つけて、既存の値をアプリケーション ID または Azure portal からコピーした clientId
アプリの java-spring-webapp-auth
に変更します。
Enter_Your_Client_Secret_Here
のプレースフォルダーを見つけて、既存の値を Azure portal からコピーした、java-spring-webapp-auth
の作成時に保存した値に置き換えます。
以降のセクションでは、サンプルを Azure Container Apps にデプロイする方法を紹介します。
次の手順を実行して、プロジェクトを準備します。
次の Maven コマンドを使用して、プロジェクトをビルドします。
mvn clean verify
次のコマンドを使用して、サンプル プロジェクトをローカルで実行します。
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
注意
2024 年 5 月以降、Azure CLI 拡張機能では、既定でプレビュー機能が有効になりません。 Container Apps のプレビュー機能 にアクセスするには、--allow-preview true
を使用して Container Apps 拡張機能をインストールします。
az extension add --name containerapp --upgrade --allow-preview true
最新の拡張機能またはモジュールがインストールされたので、Microsoft.App
および Microsoft.OperationalInsights
名前空間を登録します。
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 ファイルでこれらの設定を変更するには、次の手順に従います。
アプリの src\main\resources\application.yml ファイルに移動し、post-logout-redirect-uri
の値をデプロイされたアプリのドメイン名に変更します (次の例を参照)。 <API_NAME>
と <default-domain-of-container-app-environment>
は実際の値に置き換えてください。 たとえば、前の手順の Azure Container Apps 環境の既定のドメインを使用し、アプリ名に ms-identity-api
を使用する場合、https://ms-identity-api.<default-domain>
値には post-logout-redirect-uri
を使用します。
post-logout-redirect-uri: https://<API_NAME>.<default-domain-of-container-app-environment>
このファイルを保存した後、次のコマンドを使用してアプリをリビルドします。
mvn clean package
重要
アプリケーションの application.yml ファイルには、クライアント シークレットの値が client-secret
パラメーターに格納されています。 この値をこのファイルに保持しないでください。 また、ファイルを Git リポジトリにコミットすると、リスクが生じる可能性があります。 推奨される方法については、「Azure Container Apps でシークレットを管理する 」を参照してください。
Microsoft Entra IDアプリの登録を更新する
リダイレクト URI は Azure Container Apps にデプロイされたアプリに変更されるため、Microsoft Entra ID アプリの登録でも、リダイレクト URI を変更する必要があります。 次の手順に従って、この変更を行います。
開発者用の Microsoft ID プラットフォームの [アプリの登録] ページに移動します。
検索ボックスを使用してアプリの登録を検索します (例: java-servlet-webapp-authentication
)。
名前を選択して、アプリの登録を開きます。
コマンドメニューから 認証 を選択します。
Web - リダイレクト URI セクションで、URI の追加 を選択します。
アプリの URI を、/login/oauth2/code/
を追加して入力します。たとえば https://<containerapp-name>.<default domain of container app environment>/login/oauth2/code/
のようになります。
[保存] を選択します。
JAR パッケージを Azure Container Apps にデプロイします。
これで、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
注意
既定の 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 とも呼ばれます) を返します。 次の手順を使用して、アプリのログをチェックし、デプロイの問題があれば調査します。
デプロイメント セクションの出力 ページから出力アプリケーションの URL にアクセスします。
Azure Container Apps インスタンスの[概要] ページのナビゲーション ウィンドウで、[ログ] を選択してアプリのログを確認します。
サンプルを実行するには、次の手順に従います。
Bash ウィンドウまたは統合された Visual Studio Code ターミナルを開きます。
アプリ プロジェクトのルート ディレクトリから次のコマンドを実行します。
mvn clean compile spring-boot:run
ブラウザーを開き、http://localhost:8080
に移動します。 You're signed in! Click here to get your ID Token Details
というテキストが書かれた画面が表示されます。
次の手順に従ってサンプルを操作します。
サインインまたはサインアウトの状態が、画面の中央に表示されます。
画面の隅にある状況依存ボタンを選択します。 このボタンは、アプリを最初に実行するときにサインイン と表示します。 または、トークンの詳細 を選択します。 このページは保護されており、認証が必要であるため、サインイン ページに自動でリダイレクトされます。
次のページに記載された指示に従い、Microsoft Entra ID テナントのアカウントでサインインします。
同意画面に、必要となるスコープが表示されます。
サインイン フローが正常に完了するとホーム ページにリダイレクトされ、どのボタンでサインイン フローをトリガーした化に応じて、サインインの状態 ページまたはトークンの詳細 ページが表示されます。
状況依存ボタンの表示がサインアウト に変わり、ユーザー名が表示されます。
ホーム ページを表示している場合は、IDトークンの詳細 を選択して、IDトークンのデコードされた要求の一部を表示します。
隅にあるボタンを使用してサインアウトします。新しい状態が状態ページに反映されます。
このサンプルでは、Java 用 Microsoft Entra ID Spring Boot Starter クライアント ライブラリ を使用して Microsoft Entra ID テナントへのユーザーのサインインを行う方法を説明します。 このサンプルでは、Spring Oauth2 クライアントと Spring Web ブート スターターも使用します。 このサンプルは Microsoft Entra ID から取得した ID トークンにある要求を使用して、サインインしているユーザーの詳細を表示します。
次の表に、サンプル プロジェクト フォルダーの内容を示します。
テーブルを展開する
ファイル/フォルダー
説明
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
サンプルに貢献するためのガイドライン。
ライセンス
サンプルのライセンス。
アプリはトークンの詳細を抽出するために、要求マッピングで Spring Security の AuthenticationPrincipal
と OidcUser
のオブジェクトを使用します (次の例を参照)。 このアプリで 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 テンプレート ページに、ユーザーが認証済みかどうかに応じて表示するコンテンツを決定するためのシンプルなロジックがあります (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>
既定では、ID トークンの詳細 ページを保護するために、サインインしているユーザーのみにアクセスを許可します。 アプリは、app.protect.authenticated
ファイルにある プロパティを使用して、これらのルートを構成します。 アプリの特定の要件を構成するには、AadWebApplicationHttpSecurityConfigurer#aadWebApplication
インスタンスに HttpSecurity
メソッドを適用します。 例については、このアプリの SecurityConfig クラスを参照してください (次の例を参照)。
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Value("${app.protect.authenticated}")
private String[] allowedOrigins;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
.and()
.authorizeHttpRequests(auth -> auth
.requestMatchers(allowedOrigins).authenticated()
.anyRequest().permitAll()
);
// @formatter:on
return http.build();
}
@Bean
@RequestScope
public ServletUriComponentsBuilder urlBuilder() {
return ServletUriComponentsBuilder.fromCurrentRequest();
}
}
このシナリオおよびその他のシナリオでの OAuth 2.0 プロトコルの動作の詳細については、「Microsoft Entra ID の認証シナリオ 」を参照してください。