演習 - MSAL を使用してユーザーをサインインさせる

完了

この演習では、Java 用 Microsoft 認証ライブラリ (MSAL4J) を使用して、サンプルの Java Web アプリケーションに認証を追加し、ユーザーが自分の Microsoft Entra アカウントでサインインできるようにします。

この演習のサンプル アプリケーションである Java サーブレット アプリケーションを使うと、ユーザーはサインインして、ユーザー名と基本的なプロファイル情報を表示できます。 また、Microsoft Graph API を呼び出して、ユーザー情報を表示することもできます。

Java Web アプリケーションの作成

シェルまたはコマンド ラインから:

  1. アプリケーション用のフォルダーを作成します。

    mkdir ~/javawebapp
    
  2. GitHub リポジトリから新しいフォルダーにサンプル アプリケーションをクローンします。

    git clone https://github.com/Azure-Samples/ms-identity-java-servlet-webapp-authentication.git ~/javawebapp
    
  3. この演習のサンプル アプリケーションがあるフォルダーに移動します。

    cd ~/javawebapp/ms-identity-java-servlet-webapp-authentication/2-Authorization-I/call-graph
    

アプリケーションを構成する

コードを構成するには、IntelliJ や VS Code などの適切な IDE でアプリケーション プロジェクトを開きます。

  1. ./src/main/resources/authentication.properties ファイルを開きます。

  2. aad.authority プロパティで、文字列 {enter-your-tenant-id-here} を見つけます。 [この組織のディレクトリ内のアカウントのみ] オプションを使ってアプリを登録したので、次の図に示すように、既存の値を [ディレクトリ (テナント) ID] 値に置き換えます。

  3. aad.clientId プロパティで、文字列 {enter-your-client-id-here} を見つけて、既存の値を、Azure portal からコピーした登録済みアプリケーションの [アプリケーション (クライアント) ID] 値 (clientId 値) に置き換えます。

    Azure portal で Microsoft Entra ID に登録されたアプリのアプリ ID が強調されているスクリーンショット。

  4. aad.secret プロパティで、文字列 {enter-your-client-secret-here} を見つけて、既存の値を、Azure portal でアプリを作成するときに保存したキー値に置き換えます。

アプリケーションの実行

  1. Tomcat サーバーが実行されていること、および Web アプリをそこにデプロイする権限を持っていることを確認します。 サーバーのホスト アドレスが http://localhost:8080 であることを確認します。

  2. Maven を使用してプロジェクトをコンパイルし、パッケージ化します。

    cd ~/javawebapp/2-Authorization-I/call-graph
    mvn clean package
    
  3. ./target/msal4j-servlet-graph.war で、結果の .war ファイルを見つけます。 Tomcat にデプロイするには、この .war ファイルを Tomcat のインストール ディレクトリ内の /webapps/ ディレクトリにコピーして、Tomcat サーバーを起動します。

  4. ブラウザーを開き、http://localhost:8080/msal4j-servlet-graph/ に移動します。 Microsoft Entra ID でのサインインにリダイレクトされます。 サインインに成功すると、次のようなページが表示されます。

    サンプル アプリケーションに正常にサインインした後でページに表示されるユーザー名を示すスクリーンショット。

  5. [ID Token Details] (ID トークンの詳細) ボタンを選ぶと、ID トークンのデコードされたクレームの一部が表示されます。

認証コードの概要

サンプル アプリケーションの認証コードの大部分は、プロジェクトの java/com/microsoft/azuresamples/msal4j/ ディレクトリにあります。 そこに含まれる複数のサーブレットにより、サインイン、サインアウト、および Microsoft Entra ID からのリダイレクト コールバックの処理のための認証エンドポイントが、アプリケーションに提供されます。 これらのサーブレットでは、ディレクトリ java/com/microsoft/azuresamples/msal4j/helpers/ 内のヘルパー クラスを使用して、MSAL によって提供される認証メソッドが呼び出されます。 AuthenticationFilter.java で定義されているサーブレット フィルターにより、保護されたルートへの認証されていない要求は、401 未承認 HTTP エラー ページにリダイレクトされます。

アプリケーションに認証を追加するには、java/com/microsoft/azuresamples/msal4j/authservletsjava/com/microsoft/azuresamples/msal4j/authwebapp ディレクトリにサーブレット クラスを、java/com/microsoft/azuresamples/msal4j/helpers/ ディレクトリにヘルパー クラスを、プロジェクトに認証サーブレット フィルター AuthenticationFilter.java を、それぞれ含める必要があります。 詳細な MSAL 認証コードを次に示します。

  1. MSAL4J は Maven で使用できます。 MSAL4J を依存関係としてプロジェクトの pom.xml ファイルに追加する必要があります。

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>msal4j</artifactId>
        <version>1.17.2</version>
    </dependency>
    
  2. サインイン プロセスの最初のステップでは、Microsoft Entra テナントの /authorize エンドポイントに要求を送信します。 承認要求の URL を作成するには、MSAL4J の ConfidentialClientApplication インスタンスを利用します。 アプリでブラウザーをこの URL にリダイレクトし、ユーザーはそこでサインインします。 次のコードは、AuthHelper クラスの redirectToAuthorizationEndpoint メソッドの実装からの抜粋です。

    final ConfidentialClientApplication client = getConfidentialClientInstance();
    AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
                                                        .builder(Config.REDIRECT_URI, Collections.singleton(Config.SCOPES))
                                                        .responseMode(ResponseMode.QUERY).prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
    
    final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
    contextAdapter.redirectUser(authorizeUrl);
    
    • AuthorizationRequestUrlParameters: AuthorizationRequestUrl を作成するために設定する必要があるパラメーター。
    • REDIRECT_URI:リダイレクト URI は、ID プロバイダーがセキュリティ トークンを送り返す先の URI です。 ユーザー資格情報が収集された後、Microsoft Entra ID によってこの URI にブラウザーが認証コードと共にリダイレクトされます。 Microsoft Entra でのアプリ登録のリダイレクト URI と一致している必要があります。
    • SCOPES:スコープは、アプリケーションによって要求されるアクセス許可です。 通常、ユーザー サインイン用の ID トークン応答を受け取るには 3 つのスコープ openid profile offline_access で十分であり、これらは MSAL によって既定で設定されます。
  3. Microsoft Entra ID により、ユーザーにサインイン プロンプトが表示されます。 サインインの試行が成功した場合、ユーザーのブラウザーは、エンドポイントでの有効な承認コードと共にアプリのリダイレクト エンドポイントにリダイレクトされます。 その後、ConfidentialClientApplication のインスタンスによって、この認証コードが Microsoft Entra ID の ID トークンとアクセス トークンに交換されます。 次のコードは、AuthHelper クラスの processAADCallback メソッドの実装からの抜粋です。

    // First, validate the state, then parse any error codes in response, then extract the authCode. Then:
    // build the auth code params:
    final AuthorizationCodeParameters authParams = AuthorizationCodeParameters
                                                        .builder(authCode, new URI(Config.REDIRECT_URI)).scopes(Collections.singleton(Config.SCOPES)).build();
    
    // Get a client instance and leverage it to acquire the token:
    final ConfidentialClientApplication client = AuthHelper.getConfidentialClientInstance();
    final IAuthenticationResult result = client.acquireToken(authParams).get();
    
    • AuthorizationCodeParameters: ID トークンやアクセス トークンと承認コードを交換するために設定する必要があるパラメーター。
    • authCode: リダイレクト エンドポイントで受信された承認コード。
    • REDIRECT_URI: 前のステップで使用したリダイレクト URI を、再度渡す必要があります。
    • SCOPES: 前のステップで使用したスコープを、再度渡す必要があります。
  4. acquireToken が成功すると、トークン クレームが抽出されます。 nonce チェックに合格すると、結果は context (IdentityContextData のインスタンス) に配置されて、セッションに保存されます。 その後、アプリケーションでそれにアクセスする必要があるときは常に、セッションから IdentityContextAdapterServlet のインスタンスを使用してこれをインスタンス化できます。

    // parse IdToken claims from the IAuthenticationResult:
    // (the next step - validateNonce - requires parsed claims)
    context.setIdTokenClaims(result.idToken());
    
    // if nonce is invalid, stop immediately! this could be a token replay!
    // if validation fails, throws exception and cancels auth:
    validateNonce(context);
    
    // set user to authenticated:
    context.setAuthResult(result, client.tokenCache().serialize());