Azure Active Directory B2C を使用したサインインを Spring Web アプリに追加する
この記事では、Microsoft Entra ID 用 Spring Boot Starter 搭載の Spring Initializr を使用して、サインイン機能を備えた Java アプリを作成する方法について説明します。
このチュートリアルでは、次の作業を行う方法について説明します。
- Spring Initializr を使用して Java アプリケーションを作成する
- Azure Active Directory B2C を構成する
- Spring Boot クラスと注釈を使用してアプリケーションをセキュリティで保護する
- Java アプリケーションをビルドしてテストする
Microsoft Entra ID は、Microsoft のクラウドスケールのエンタープライズ ID ソリューションです。 Azure Active Directory B2C は、Microsoft Entra ID の機能セットを補完することにより、御社がその企業-消費者間 (B2C) アプリケーションを管理して、顧客や消費者、市民にアクセスを提供できるようにします。
前提条件
- Azure サブスクリプション。 まだお持ちでない場合は、開始する前に無料アカウントを作成してください。
- サポートされている Java Development Kit (JDK)。 Azure での開発時に使用可能な JDK の詳細については、「Java の Azure および Azure Stack に関するサポート」 を参照してください。
- Apache Maven、バージョン 3.0 以降。
重要
この記事の手順を完了するには、Spring Boot 2.5 以降のバージョンが必要です。
Spring Initializr を使用したアプリの作成
https://start.spring.io/ にアクセスします。
このガイダンスに従って、値を入力します。 ラベルとレイアウトは、ここに示されている画像とは異なる場合があります。
- [プロジェクト] で、[Maven プロジェクト] を選択します。
- [言語] で、[Java] を選択します。
- [Spring Boot] で、[2.7.11] を選択します。
- [グループ]、[アーティファクト] および [名前] で、短い説明の文字列を使用して同じ値を入力します。 入力するにつれ、一部が UI に自動的に入力される場合があります。
- [依存関係] ペインで、[依存関係の追加] を選択します。 UI を使用して Spring Web と、Spring Security に対する依存関係を追加します。
Note
Spring Security 5.5.1、5.4.7、5.3.10、5.2.11 が、CVE レポート 「CVE-2021-22119: Denial-of-Service attack with spring-security-oauth2-client」に対応するためにリリースされています。 これより古いバージョンを使用している場合は、アップグレードしてください。
[プロジェクトの生成] を選択してから、ローカル コンピューター上のパスにプロジェクトをダウンロードします。 ダウンロードしたファイルを、プロジェクトに基づいて名前が付けられたディレクトリに移動し、そのファイルを解凍します。 ファイルのレイアウトは以下のようになるはずです。
yourProject
の代わりに、[グループ] に入力した値が示されます。. ├── HELP.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main │ ├── java │ │ └── yourProject │ │ └── yourProject │ │ └── YourProjectApplication.java │ └── resources │ ├── application.properties │ ├── static │ └── templates └── test └── java └── yourProject └── yourProject └── YourProjectApplicationTests.java
Microsoft Entra インスタンスの作成と初期化
Active Directory インスタンスを作成する
https://portal.azure.com にログインします。
[リソースの作成] を選択します。 Azure Active Directory B2C を検索します。
[作成] を選択します
[Create a new Azure AD B2C Tenant](新しい Azure AD B2C テナントの作成) を選択します。
[組織名] と [初期ドメイン名] では、適切な値を指定してから [作成] を選択します。
Active Directory の作成が完了したら、右上隅にある自分のアカウントを選択し、[ディレクトリの切り替え] を選択してから、作成したディレクトリを選択します。 新しいテナント ホーム ページにリダイレクトされます。 次に
b2c
を検索して [Azure AD B2C] を選択します。
Spring Boot アプリのアプリケーション登録を追加する
[管理] ペインで、[アプリの登録] を選択し、次に [新しい登録] を選択します。
[名前] フィールドに、アプリの名前を入力して、[登録] を選択します。
[管理] ペインに戻り、[アプリの登録] を選択し、作成したアプリケーション名を選択します。
[認証]、[プラットフォームの追加]、[Web] の順に選択します。 [リダイレクト URI] を
http://localhost:8080/login/oauth2/code/
に設定し、[構成] を選択します。
アプリのアプリ シークレットを追加する
[証明書とシークレット] を選択し、[新しいクライアント シークレット] を選択します。 シークレットの説明を入力し、[追加] を選択します。 シークレットを作成した後、シークレット値の横にあるコピー アイコンを選択して値をコピーして、この記事で後半で使用します。
Note
[認定資格証&シークレット] セクションから移動して再び戻ると、シークレットの値を表示できなくなります。 その場合は、別のシークレットを作成し、今後の使用のためにコピーする必要があります。 場合によっては、生成されたシークレット値に、application.yml ファイルに含める場合に問題となる文字 (円記号やバッククォートなど) が含まれていることがあります。 その場合は、そのシークレットを破棄し、別のものを生成します。
ユーザー フローの追加
お使いのテナント メイン ページに移動します。 左ペインの [ポリシー] セクションで、[ユーザー フロー]、[新しいユーザー フロー] の順に選択します。
このチュートリアルから離れて、別のチュートリアルを実行し、完了したらこのチュートリアルに戻ります。 他のチュートリアルに移動するときに注意すべきいくつかの点を以下に示します。
- [新しいユーザー フロー] を選択するよう求める手順から開始します。
- このチュートリアルで
webapp1
が示された場合は、代わりに [グループ] に入力した値を使用します。 - フローから返される要求を選択する場合は、確実に [表示名] が選択されるようにしてください。 この要求がないと、このチュートリアルでビルドされるアプリは機能しません。
- ユーザー フローを実行するように求められた場合は、以前に指定したリダイレクト URL がまだアクティブになっていません。 フローは引き続き実行できますが、リダイレクトは正常に完了しません。 これは予期されることです。
- 「次のステップ」に到達したら、このチュートリアルに戻ります。
チュートリアル: Azure Active Directory B2C でユーザー フローを作成する のすべての手順を実行して、「サインアップとサインイン」、「プロファイルの編集」、「パスワードのリセット」のユーザー フローを作成します。
Azure AD B2C は、ローカル アカウントとソーシャル ID プロバイダーをサポートしています。 GitHub ID プロバイダーを作成する例については、「Azure Active Directory B2C を使用して GitHub アカウントでのサインアップおよびサインインを設定する」を参照してください。
アプリの構成およびコンパイル
Azure AD B2C インスタンスといくつかのユーザー フローを作成したので、Spring アプリを Azure AD B2C インスタンスに接続します。
コマンド ラインで、Spring Initializr からダウンロードした .zip ファイルを解凍したディレクトリに移動します。
プロジェクトの親フォルダーに移動し、テキスト エディターで pom.xml Maven プロジェクト ファイルを開きます。
Spring OAuth2 セキュリティの依存関係を pom.xml に追加します。
<dependency> <groupId>com.azure.spring</groupId> <artifactId>spring-cloud-azure-starter-active-directory-b2c</artifactId> <version>See Below</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>See Below</version> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>See Below</version> </dependency>
spring-cloud-azure-starter-active-directory-b2c
には、使用可能な最新バージョンを使用します。 mvnrepository.com を使用して、これを確認できる場合があります。spring-boot-starter-thymeleaf
には、先ほど選択した Spring Boot のバージョン (2.3.4.RELEASE
など) に対応するバージョンを使用します。thymeleaf-extras-springsecurity5
には、使用可能な最新バージョンを使用します。 mvnrepository.com を使用して、これを確認できる場合があります。 このドキュメントの執筆時点では、最新バージョンは3.0.4.RELEASE
です。pom.xml ファイルを保存して閉じます。
mvn -DskipTests clean install
を実行して、依存関係が正しいことを確認します。 そうでない場合は、「BUILD SUCCESS
」を参照して、問題をトラブルシューティングし、解決してから続行してください。
プロジェクトの src/main/resources フォルダーに移動し、テキスト エディターで application.yml ファイルを作成します。
前に作成した値を使用して、アプリ登録の設定を指定します。たとえば、以下のとおりです。
spring: cloud: azure: active-directory: b2c: enabled: true base-uri: https://<your-tenant-initial-domain-name>.b2clogin.com/<your-tenant-initial-domain-name>.onmicrosoft.com/ credential: client-id: <your-application-ID> client-secret: '<secret-value>' login-flow: sign-up-or-sign-in logout-success-url: <your-logout-success-URL> user-flows: sign-up-or-sign-in: <your-sign-up-or-sign-in-user-flow-name> profile-edit: <your-profile-edit-user-flow-name> password-reset: <your-password-reset-user-flow-name> user-name-attribute-name: <your-user-name-attribute-name>
client-secret
値が単一引用符で囲まれていることに注目してください。 これが必要なのは、<secret-value>
の値には、YAML に存在する場合に単一引用符で囲む必要があるいくつかの文字がほぼ確実に含まれるためです。Note
このドキュメントの執筆時点で、application.yml で使用できる Active Directory B2C Spring の統合の値の完全な一覧を以下に示します。
spring: cloud: azure: active-directory: b2c: enabled: true base-uri: credential: client-id: client-secret: login-flow: logout-success-url: user-flows: sign-up-or-sign-in: profile-edit: # optional password-reset: # optional user-name-attribute-name:
application.yml ファイルは、GitHub 上の spring-cloud-azure-starter-active-directory-b2c サンプル: aad-b2c-web-application で入手できます。
application.yml ファイルを保存して閉じます。
src/main/java/<yourGroupId>/<yourGroupId> に controller という名前のフォルダーを作成し、
<yourGroupId>
を、[グループ] で入力した値に置き換えます。controller フォルダーに "java" という名前の新しい Java ファイルを作成し、テキスト エディターで開きます。
次のコードを入力し、適宜、
yourGroupId
を変更してから、ファイルを保存して閉じます。package yourGroupId.yourGroupId.controller; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller public class WebController { private void initializeModel(Model model, OAuth2AuthenticationToken token) { if (token != null) { final OAuth2User user = token.getPrincipal(); model.addAttribute("grant_type", user.getAuthorities()); model.addAllAttributes(user.getAttributes()); } } @GetMapping(value = "/") public String index(Model model, OAuth2AuthenticationToken token) { initializeModel(model, token); return "home"; } @GetMapping(value = "/greeting") public String greeting(Model model, OAuth2AuthenticationToken token) { initializeModel(model, token); return "greeting"; } @GetMapping(value = "/home") public String home(Model model, OAuth2AuthenticationToken token) { initializeModel(model, token); return "home"; } }
コントローラー内のすべてのメソッドで
initializeModel()
が呼び出され、そのメソッドでmodel.addAllAttributes(user.getAttributes());
が呼び出されるため、src/main/resources/templates 内の任意の HTML ページから、${name}
、${grant_type}
、${auth_time}
など、それらの属性のいずれかにアクセスできます。user.getAttributes()
から返される値は、実際には認証用のid_token
の要求です。 使用可能な要求の完全な一覧については、「Microsoft ID プラットフォームの ID トークン」を参照してください。src/main/java/<yourGroupId>/<yourGroupId> に security という名前のフォルダーを作成し、
yourGroupId
を、[グループ] で入力した値に置き換えます。security フォルダーに "WebSecurityConfiguration.java" という名前の新しい Java ファイルを作成し、テキスト エディターで開きます。
次のコードを入力し、適宜、
yourGroupId
を変更してから、ファイルを保存して閉じます。package yourGroupId.yourGroupId.security; import com.azure.spring.cloud.autoconfigure.aadb2c.AadB2cOidcLoginConfigurer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { private final AadB2cOidcLoginConfigurer configurer; public WebSecurityConfiguration(AadB2cOidcLoginConfigurer configurer) { this.configurer = configurer; } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest() .authenticated() .and() .apply(configurer) ; } }
home.html ファイルを spring-cloud-azure-starter-active-directory-b2c sample: aad-b2c-web-application から src/main/resources/templates にコピーし、
${your-profile-edit-user-flow}
と${your-password-reset-user-flow}
を以前に作成したユーザー フローの名前で置き換えます。
アプリのビルドとテスト
コマンド プロンプトを開き、ディレクトリをアプリの pom.xml ファイルがあるフォルダーに変更します。
Spring Boot アプリケーションを Maven でビルドし、実行します。次に例を示します。
Note
ローカルの Spring Boot アプリの実行に使用されるシステム クロックに準じた時刻が正確であることは、非常に重要です。 OAuth 2.0 を使用する場合、クロックのずれの許容範囲はごくわずかです。 誤差が 3 分でもサインインは失敗し、
[invalid_id_token] An error occurred while attempting to decode the Jwt: Jwt used before 2020-05-19T18:52:10Z
のようなエラーが示されることがあります。 このドキュメントの執筆時点では、time.gov に、クロックが実際の時刻からどれくらいずれているかを示すインジケーターがあります。 アプリは、+0.019 秒のずれで正常に実行されました。mvn -DskipTests clean package mvn -DskipTests spring-boot:run
Maven によってアプリケーションがビルドされ、起動したら、Web ブラウザーで
http://localhost:8080/
を開きます。ログイン ページにリダイレクトされます。サインインに関するテキストを含むリンクを選択します。 Azure AD B2C にリダイレクトされ、認証プロセスが開始されるはずです。
正常にログインすると、ブラウザーにサンプルの
home page
が表示されます。
トラブルシューティング
以下のセクションでは、発生する可能性のあるいくつかの問題の解決方法について説明します。
属性に属性名がない
サンプルを実行しているとき、Missing attribute 'name' in attributes
メッセージの例外が発生することがあります。 この例外のログは、次の出力のようになります。
java.lang.IllegalArgumentException: Missing attribute 'name' in attributes
at org.springframework.security.oauth2.core.user.DefaultOAuth2User.<init>(DefaultOAuth2User.java:67) ~[spring-security-oauth2-core-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser.<init>(DefaultOidcUser.java:89) ~[spring-security-oauth2-core-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService.loadUser(OidcUserService.java:144) ~[spring-security-oauth2-client-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService.loadUser(OidcUserService.java:63) ~[spring-security-oauth2-client-5.3.6.RELEASE.jar:5.3.6.RELEASE]
このエラーが発生した場合は、「チュートリアル: Azure Active Directory B2C 内にユーザー フローを作成する」で作成したユーザー ワークフローをよく調べてください。 ユーザー ワークフローを作成するとき、[ユーザー属性と要求] で、必ず [表示名] の属性と要求を選択してください。 また、必ず application.yml ファイルで user-name-attribute-name
を正しく構成してください。
B2C エンドポイントへのサインインがループになる
この問題の原因として、localhost
の Cookie が汚れていることが考えられます。 localhost
の Cookie をクリーンアップしてから、もう一度お試しください。
まとめ
このチュートリアルでは、Azure Active Directory B2C スターターを使用した新しい Java Web アプリケーションの作成、新しい Azure AD B2C テナントの構成とそこでの新しいアプリケーションの登録を行ってから、Spring の注釈とクラスを使用して Web アプリを保護するようにアプリケーションを構成しました。
リソースをクリーンアップする
予想外の課金を防ぐために、この記事で作成したリソースが不要になったら、Azure portal を使用して削除してください。
次のステップ
Spring および Azure の詳細については、Azure ドキュメント センターで引き続き Spring に関するドキュメントをご確認ください。