MSAL4J と Azure Active Directory B2C を使用して Java WebSphere アプリのサインインを有効にする
この記事では、Microsoft Authentication Library for Java (MSAL4J) を使用してユーザーを Azure Active Directory B2C (Azure AD B2C) に対して認証する Java Servlet アプリケーションについて説明します。
次の図は、アプリのトポロジを示しています。
このアプリでは MSAL4J を使用してユーザーのサインインを行い、Azure AD B2C から ID トークンを取得します。 ID トークンにより、ユーザーが Azure AD B2C テナントに対して認証されていることが証明されます。
前提条件
- JDK - バージョン 8 以降
- Maven 3
- Azure AD B2C テナント。 詳細については、「チュートリアル: Azure Active Directory B2C テナントを作成する」参照してください。
- Azure AD B2C テナント内のユーザー アカウント。
推奨事項
- Java / Jakarta Servlets に関するある程度の知識。
- Linux/OSX ターミナルに関するある程度の知識。
- トークンの検査に必要な jwt.ms。
- ネットワークの活動監視とトラブルシューティングに必要な Fiddler。
- 開発に関する最新の情報について、Microsoft Entra ID ブログを確認してください。
サンプルのセットアップ
次のセクションでは、サンプル アプリケーションを設定する方法を示します。
サンプル リポジトリを複製またはダウンロードする
サンプルを複製するには、Bash ウィンドウを開き、次のコマンドを使用します。
git clone https://github.com/Azure-Samples/ms-identity-msal-java-samples.git
cd 3-java-servlet-web-app/1-Authentication/sign-in-b2c
または、ms-identity-msal-java-samples リポジトリに移動し、.zip ファイルでダウンロードして、ハード ドライブに展開します。
重要
Windows でファイル パスの長さが制限を超える場合は、ハード ドライブのルート近くのディレクトリにリポジトリを複製または展開してください。
サンプル アプリケーションを Azure AD B2C テナントに登録する
このサンプルには、テストのために事前に登録されたアプリケーションが含まれています。 自分の Azure AD B2C テナントとアプリケーションを使用する場合は、次のセクションに記載された手順に従い、アプリケーションを Azure portal で登録して構成します。 そうしない場合は、「サンプルを実行する」の手順に進みます。
アプリケーションを作成するための Azure AD B2C テナントを選択する
テナントを選択するには、次の手順に従います。
Azure portal にサインインします。
ご利用のアカウントが複数の Azure AD B2C テナントに存在する場合は、Azure portal の画面の隅にあるプロファイルを選択し、ディレクトリの切り替えを選択して、ポータルのセッションを目的の Azure AD B2C テナントに変更します。
ユーザー フローとカスタム ポリシーの作成
サインアップ、サインイン、プロファイルの編集、パスワードのリセットなど、一般的なユーザー フローを作成するには、「チュートリアル: Azure Active Directory B2C 内にユーザー フローを作成する」を参照してください。
Azure Active Directory B2C でもカスタム ポリシーを作成することをお勧めしますが、それについては、このチュートリアルでは説明しません。
外部 ID プロバイダーを追加する
「チュートリアル:Azure Active Directory B2C でアプリケーションに ID プロバイダーを追加する」を参照してください。
アプリを登録する (ms-identity-b2c-java-servlet-webapp-authentication)
アプリを登録するには、次の手順に従います。
Azure portal に移動して、Azure AD B2C を選びます。
ナビゲーション ペインでアプリの登録を選択し、新しい登録を選択します。
表示される アプリケーションの登録ページで、アプリケーションの登録情報を入力します。
- 名前セクションに、アプリのユーザーに表示されるわかりやすいアプリケーション名を入力します (例:
ms-identity-b2c-java-servlet-webapp-authentication
)。 - [サポートされているアカウントの種類] で、[任意の組織のディレクトリ内のアカウントと、個人用の Microsoft アカウント (Skype、Xbox、Outlook.com など)] を選択します。
- [リダイレクト URI (省略可能)] セクションで、コンボボックスの [Web] を選択し、リダイレクト URI 「
http://localhost:8080/ms-identity-b2c-java-servlet-webapp-authentication/auth_redirect
」を入力します。
- 名前セクションに、アプリのユーザーに表示されるわかりやすいアプリケーション名を入力します (例:
[登録] を選択して、アプリケーションを作成します。
アプリの登録ページで、アプリケーション (クライアント) ID の値を見つけてメモします。 この値は、後ほどアプリの構成ファイルで使用します。
[保存] を選択して変更を保存します。
アプリの登録ページで、ナビゲーション ペインにある 証明書とシークレットを選択してページを開き、シークレットの生成と証明書のアップロードを行います。
[クライアント シークレット] セクションで、 [新しいクライアント シークレット] を選択します。
キーの説明 (例: アプリのシークレット) を入力します。
1 年、2 年、無期限のいずれかの期間を選びます。
[追加] を選択します。 生成された値が表示されます。
生成した値をコピーしてから保存します。 この値は後ほど、コードの構成ファイルに使用します。 この値は二度と表示されず、他の方法でも取得はできません。 そのため、必ず Azure portal から保存した後に、他の画面やペインに移動してください。
アプリの登録を使用するようにアプリ (ms-identity-b2c-java-servlet-webapp-authentication) を構成する
アプリを構成するには、次の手順に従います。
Note
以降の手順では、ClientID
は Application ID
または AppId
と同じです。
IDE でプロジェクトを開きます。
./src/main/resources/authentication.properties ファイルを開きます。
aad.clientId
プロパティを見つけて、既存の値をアプリケーション ID または Azure portal からコピーしたms-identity-b2c-java-servlet-webapp-authentication
アプリケーションのclientId
に変更します。aad.secret
プロパティを見つけて、Azure portal のms-identity-b2c-java-servlet-webapp-authentication
アプリケーションの作成時に保存した値に既存の値を置き換えます。aad.scopes
プロパティを見つけて、既存のアプリケーション clientId を、このセクションの手順 1 でaad.clientId
に入力した値に置き換えます。aad.authority
プロパティを探して、fabrikamb2c
の最初のインスタンスを、Azure portal のms-identity-b2c-java-servlet-webapp-authentication
アプリケーションで作成した Azure AD B2C テナントの名前に置き換えます。aad.authority
プロパティを探して、fabrikamb2c
の 2 番目のインスタンスを、Azure portal のms-identity-b2c-java-servlet-webapp-authentication
アプリケーションで作成した Azure AD B2C テナントの名前に置き換えます。aad.signInPolicy
プロパティを見つけて、Azure portal でms-identity-b2c-java-servlet-webapp-authentication
アプリケーションを作成した際に、Azure AD B2C テナント で作成したサインアップ/サインイン ユーザー フロー ポリシーの名前に置き換えます。aad.passwordResetPolicy
プロパティを見つけて、Azure portal でms-identity-b2c-java-servlet-webapp-authentication
アプリケーションを作成した際に、Azure AD B2C テナント で作成したパスワード リセット ユーザー フロー ポリシーの名前に置き換えます。aad.editProfilePolicy
プロパティを見つけて、Azure portal でms-identity-b2c-java-servlet-webapp-authentication
アプリケーションを作成した際に、Azure AD B2C テナント で作成したプロファイル編集ユーザー フロー ポリシーの名前に置き換えます。
サンプルをビルドする
Maven を使用してサンプルをビルドするには、サンプルの pom.xml ファイルが含まれているディレクトリに移動して、次のコマンドを実行します。
mvn clean package
このコマンドを実行すると、.war ファイルが作成されます。これはさまざまなアプリケーション サーバーで実行できます。
サンプルを実行する
以降の手順では、WebSphere をインストールし、サーバーが設定されていることを前提としています。 サーバーのセットアップの基本について、「Azure 仮想マシンで (従来の) WebSphere Application Server クラスターをデプロイする」のガイダンスを参照してください。
WebSphere にデプロイする前に、次の手順を使用してサンプル本体の構成を変更してから、パッケージをビルドまたはリビルドする必要があります。
アプリの authentication.properties ファイルに移動し、
app.homePage
の値を、使用を計画しているサーバーの URL とポート番号に変更します (次の例を参照)。# app.homePage is by default set to dev server address and app context path on the server # for apps deployed to azure, use https://your-sub-domain.azurewebsites.net app.homePage=https://<server-url>:<port-number>/msal4j-servlet-auth/
このファイルを保存した後、次のコマンドを使用してアプリをリビルドします。
mvn clean package
コードのビルドが終了したら、.war ファイルをターゲット サーバーのファイル システムにコピーします。
また、Azure アプリの登録でも同じ変更を行う必要があります。Azure portal で、認証タブのリダイレクト URI の値に対し、これを設定してください。
開発者用の Microsoft ID プラットフォームの [アプリの登録] ページに移動します。
検索ボックスを使用してアプリの登録を検索します (例:
java-servlet-webapp-authentication
)。名前を選択して、アプリの登録を開きます。
コマンドメニューから 認証 を選択します。
Web - リダイレクト URI セクションで、URI の追加を選択します。
アプリの URI を、/auth/redirect を追加して入力します (例:
https://<server-url>:<port-number>/auth/redirect
)。[保存] を選択します。
WebSphere の Integrated Solutions Console を使用してサンプルをデプロイするには、次の手順に従います。
アプリケーション タブで、新しいアプリケーションを選択し、新しいエンタープライズ アプリケーションを選択します。
ビルドした .war ファイルを選択し、Web モジュールのマップ コンテキスト ルートのインストール手順が表示されるまで次へを選択します。 その他の既定の設定はそのままで問題ありません。
コンテキスト ルートの場合は、サンプル構成/Azure アプリの登録で設定した 'リダイレクト URI' のポート番号の後と同じ値に設定します。 つまり、リダイレクト URI が
http://<server-url>:9080/msal4j-servlet-auth/
である場合、コンテキスト ルートはmsal4j-servlet-auth
になります。完了 を選択します。
アプリケーションのインストールが完了したら、アプリケーションタブの WebSphere エンタープライズ アプリケーション セクションに移動します。
アプリケーションの一覧からインストールした .war ファイルを選択し、開始を選択してデプロイします。
デプロイが完了したら、
http://<server-url>:9080/{whatever you set as the context root}
に移動します。アプリケーションが表示されます。
サンプルの確認
次の手順に従ってサンプルを操作します。
- サインインまたはサインアウトの状態が、画面の中央に表示されます。
- 画面の隅にある状況依存ボタンを選択します。 このボタンは、アプリを最初に実行するときにサインインと表示します。
- 次のページに移動し、指示に従って、選択した ID プロバイダーのアカウントでサインインします。
- 状況依存ボタンの表示がサインアウトに変わり、ユーザー名が表示されます。
- ID トークンの詳細を選択すると、ID トークンのデコードされた要求の一部が表示されます。
- プロファイルを編集することもできます。 リンクを選択して、表示名、居住地、職業などの詳細を編集します。
- 画面隅のボタンを使用してサインアウトします。
- サインアウトした後、トークンの詳細ページの次の URL に移動します:
http://localhost:8080/ms-identity-b2c-java-servlet-webapp-authentication/auth_token_details
。 ここで、アプリが ID トークン要求ではなく401: unauthorized
エラーを表示することを確認できます。
コードについて
このサンプルでは、MSAL4J を使用して Azure AD B2C テナントへのユーザーのサインインを行う方法を示します。
Contents
次の表に、サンプル プロジェクト フォルダーの内容を示します。
ファイル/フォルダー | 説明 |
---|---|
AuthHelper.java | 認証に使用するヘルパー関数。 |
Config.java | 起動時に実行され、プロパティ リーダーとロガーを構成します。 |
authentication.properties | Microsoft Entra ID とプログラム構成。 |
AuthenticationFilter.java | 認証されていない要求を、保護されたリソースの 401 ページにリダイレクトします。 |
MsalAuthSession | HttpSession を使用してインスタンス化されます。 すべての MSAL 関連セッション属性をセッション属性に格納します。 |
____Servlet.java | 使用可能なすべてのエンドポイントは、末尾が ____Servlet.java である .java クラスに定義されます。 |
CHANGELOG.md | サンプルに対する変更の一覧。 |
CONTRIBUTING.md | サンプルに貢献するためのガイドライン。 |
ライセンス | サンプルのライセンス。 |
ConfidentialClientApplication
ConfidentialClientApplication
インスタンスが AuthHelper.java ファイルに作成されます (次の例を参照)。 このオブジェクトにより Azure AD B2C 認証 URL の作成、および認証トークンとアクセス トークンの交換が行われます。
IClientSecret secret = ClientCredentialFactory.createFromSecret(SECRET);
confClientInstance = ConfidentialClientApplication
.builder(CLIENT_ID, secret)
.b2cAuthority(AUTHORITY + policy)
.build();
インスタンス化には次のパラメーターが使用されます。
- アプリのクライアント ID。
- クライアント シークレット。機密クライアント アプリケーションに必要です。
- Azure AD B2C の認証機関が
UserFlowPolicy
と連結され、サインアップ、サインイン、プロファイルの編集、またはパスワード リセットが行われます。
上記の例では、Config.java ファイルにあるプロパティ リーダ0を使用して、値が authentication.properties ファイルから読み取られます。
ステップバイステップのチュートリアル
次の手順で、アプリの機能をチュートリアルで紹介します。
サインイン プロセスの最初のステップでは、Azure Active Directory B2C テナントの
/authorize
エンドポイントに要求を送信します。 MSAL4JConfidentialClientApplication
インスタンスを使用して承認要求 URL を作成すると、アプリがブラウザーをこの URL にリダイレクトします (次の例を参照)。final ConfidentialClientApplication client = getConfidentialClientInstance(policy); final AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters .builder(REDIRECT_URI, Collections.singleton(SCOPES)).responseMode(ResponseMode.QUERY) .prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build(); final String redirectUrl = client.getAuthorizationRequestUrl(parameters).toString(); Config.logger.log(Level.INFO, "Redirecting user to {0}", redirectUrl); resp.setStatus(302); resp.sendRedirect(redirectUrl);
このコードの機能を次の一覧で示します。
AuthorizationRequestUrlParameters
: AuthorizationRequestUrl を作成するために設定する必要があるパラメーター。REDIRECT_URI
: Azure AD B2C がユーザー資格情報を収集した後、認証コードと共にブラウザーをリダイレクトする場所。SCOPES
: スコープはアプリケーションで要求されるアクセス許可です。通常、ID トークンの応答を受信するには、
openid profile offline_access
の 3 つのスコープがあれば十分です。 ただし、MSAL4J では、Azure AD B2C からのすべての応答にもアクセス トークンが含まれている必要があります。Azure AD B2C でアクセス トークンと ID トークンを分配するには、要求に追加のリソース スコープを含める必要があります。 このアプリは実際には外部リソース スコープを必要としないため、アクセス トークンを受け取るために、自分のクライアント ID が 4 番目のスコープとして追加されます。
authentication.properties ファイルに、アプリで要求されるすべてのスコープの一覧が入力されています。
ResponseMode.QUERY
: Azure AD B2C は、HTTP POST 要求のフォーム パラメーターとして、または HTTP GET 要求のクエリ文字列パラメーターとして応答を返すことができます。Prompt.SELECT_ACCOUNT
: Azure AD B2C は、認証対象のアカウントを選択するようユーザーに求める必要があります。state
: アプリで各トークン要求のセッションに設定され、対応する Azure AD B2C リダイレクト コールバックを受信した後に破棄される一意の変数。 状態変数を使用すると、Azure AD B2C 承認要求から/auth_redirect endpoint
への Azure AD B2C 要求がこのアプリとこのセッションから確実に送信され、CSRF 攻撃が防止されます。 これは、AADRedirectServlet.java ファイルで行われます。nonce
: アプリによって各トークン要求のセッションに設定され、対応するトークンを受信した後に破棄される一意の変数。 この nonce は、Azure AD B2C に分配された結果のトークンに変換され、トークンリプレイ攻撃の発生を防ぎます。
Azure Active Directory B2C により、ユーザーにサインイン プロンプトが表示されます。 サインインが成功すると、ユーザーのブラウザーはアプリのリダイレクト エンドポイントにリダイレクトされます。 このエンドポイントへの有効な要求には、、認証コードが含まれています。
その後、
ConfidentialClientApplication
インスタンスは、この承認コードを Azure Active Directory B2C の ID トークンとアクセス トークンとで交換します (次の例を参照)。final AuthorizationCodeParameters authParams = AuthorizationCodeParameters .builder(authCode, new URI(REDIRECT_URI)) .scopes(Collections.singleton(SCOPES)).build(); final ConfidentialClientApplication client = AuthHelper .getConfidentialClientInstance(policy); final Future<IAuthenticationResult> future = client.acquireToken(authParams); final IAuthenticationResult result = future.get();
このコードの機能を次の一覧で示します。
AuthorizationCodeParameters
: ID トークンやアクセス トークンと承認コードを交換するために設定する必要があるパラメーター。authCode
: リダイレクト エンドポイントで受信された承認コード。REDIRECT_URI
: 前のステップで使用したリダイレクト URI を、再度渡す必要があります。SCOPES
: 前のステップで使用したスコープを、再度渡す必要があります。
acquireToken
が成功した場合、トークン要求が抽出され、セッションに格納されている nonce に対して nonce 要求が検証されます (次の例を参照)。parseJWTClaimsSetAndStoreResultInSession(msalAuth, result, serializedTokenCache); validateNonce(msalAuth) processSuccessfulAuthentication(msalAuth);
nonce が正常に検証されると、
MsalAuthSession
クラスによって公開されるメソッドを利用して、認証状態がサーバー側セッションに入ります (次の例を参照)。msalAuth.setAuthenticated(true); msalAuth.setUsername(msalAuth.getIdTokenClaims().get("name"));
詳細
- Azure Active Directory B2C とは
- Active Directory B2C で使用できるアプリケーションの種類
- Azure Active Directory B2C の推奨事項とベスト プラクティス
- Azure AD B2C のセッション
- Java 用 Microsoft 認証ライブラリ (MSAL)
このシナリオおよびその他のシナリオでの OAuth 2.0 プロトコルの動作の詳細については、「Microsoft Entra ID の認証シナリオ」を参照してください。
次のステップ
Azure Virtual Machines にある従来の WebSphere に Java WebSphere アプリをデプロイする