グループとグループ要求を使用して Java Tomcat アプリをセキュリティで保護する

この記事では、Microsoft Authentication Library (MSAL) for Java によるユーザー サインイン機能を備えた Tomcat アプリの作成方法を説明します。 このアプリには、Microsoft Entra ID セキュリティ グループのメンバーシップを基にページへのアクセスを制限する機能も追加します。

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

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

クライアント アプリではユーザーが MSAL for Java (MSAL4J) を使用して Microsoft Entra ID テナントにサインインし、Microsoft Entra ID から ID トークンを取得します。 この ID トークンにより、このテナントでユーザーが認証されます。 アプリのルートは、ユーザーの認証状態とグループ メンバーシップに基づいて保護されます。

このシナリオを紹介するビデオ、「アプリ ロール、セキュリティ グループ、スコープ、ディレクトリ ロールを使用した承認をアプリケーションに実装する」をご覧ください。

前提条件

推奨事項

  • Java / Jakarta Servlets に関するある程度の知識。
  • Linux/OSX terminal ターミナルまたは Windows PowerShell に関するある程度の知識。
  • トークンの検査に必要な 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/3-Authorization-II/groups

または、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-groups)

最初に、クイック スタート: Microsoft ID プラットフォームにアプリケーションを登録するに記載された説明に従って Azure portal に新しいアプリを登録します。

次の手順を実行して、登録を完了します。

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

  2. [新規登録] を選択します。

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

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

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

  6. [保存] を選択して変更を保存します。

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

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

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

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

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

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

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

  14. アクセス許可の追加 を選択します。

  15. [Microsoft API] タブが選択されていることを確認します。

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

  17. I 委任されたアクセス許可セクションで、リストから User.ReadGroupMember.Read.All を選択します。 必要に応じて検索ボックスを使用します。

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

  19. GroupMember.Read.All では管理者の同意が必要であるため、テナントのすべてのアカウントがアクセス許可を要求した場合に同意を付与するか質問されたら、{テナント} の管理者の同意を付与/取り消すを選択し、はいを選択します。 このアクションを実行するには、Microsoft Entra ID テナント管理者である必要があります。


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

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

Note

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

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

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

  3. {enter-your-tenant-id-here} という文字列を見つけます。 アプリを この組織ディレクトリ内のアカウントのみ オプションで登録している場合は、既存の値を Microsoft Entra テナント ID に変更します。

  4. {enter-your-client-id-here} という文字列を見つけて、既存の値をアプリケーション ID または Azure portal からコピーした java-servlet-webapp-groups アプリケーションの clientId に変更します。

  5. {enter-your-client-secret-here} という文字列を見つけて、既存の値を、Azure portal で java-servlet-webapp-groups アプリを作成するときに保存した値に置き換えます。

セキュリティ グループを構成する

アプリケーションでグループ要求をどのように受け取るかを細かく設定するための方法として、次の選択肢があります。

Note

グループ ID ではなく、オンプレミス グループの samAccountName または On Premises Group Security Identifier を使用する場合は、「Microsoft Entra ID を使ってアプリケーションに対するグループ要求を構成する」の「Active Directory から同期されたグループ属性を使用する場合の前提条件」を参照してください。

サインイン済みのユーザーが割り当てられているすべてのグループ (入れ子になったグループを含む) を受け取るようアプリケーションを構成する

アプリケーションを構成するには、以下の手順に従います。

  1. アプリの登録ページで、ナビゲーション ペインにあるトークンの構成を選択してページを開き、アプリケーションにトークンが発行されることで可能になる要求を構成します。

  2. グループ要求の追加を選択して、グループ要求の編集画面を開きます。

  3. セキュリティ グループまたはすべてのグループ (配布リストを含むが、アプリケーションに割り当てられているグループは含まない) オプションを選択します。 両方のオプションを選択すると、セキュリティ グループ オプションが無効になります。

  4. ID セクションで、グループ ID を選択します。 Microsoft Entra ID が、ユーザーのサインイン後にアプリが受け取る ID トークンのグループ要求で、ユーザーが割り当てられているグループのオブジェクト ID を送信します。

ユーザーが割り当てられる可能性のある、フィルター処理されたグループのセットからグループ要求の値を受け取るようアプリケーションを構成する

このオプションは、次のような場合に使用します。

  • アプリケーションが、サインインしているユーザーが割り当てられる可能性のあるグループを選択したセットに対して処理を行う。
  • アプリケーションが、このユーザーがテナントで割り当てられているすべてのセキュリティ グループに対して処理を行うわけではない。

このオプションを使用すると、アプリケーションの使用量超過の問題を防げます。

Note

この機能は、Microsoft Entra ID Free エディション では使用できません。

この選択肢を使用する場合、入れ子になったグループを割り当てることはできません。

この選択肢をアプリで有効にするには、次の手順を使います。

  1. アプリの登録ページで、ナビゲーション ペインにあるトークンの構成を選択してページを開き、アプリケーションにトークンが発行されることで可能になる要求を構成します。

  2. グループ要求の追加を選択して、グループ要求の編集画面を開きます。

  3. アプリケーションに割り当てられているグループを選択します。

    セキュリティ グループすべてのグループ (配布リストを含むが、アプリケーションに割り当てられたグループは含まない) などの他のオプションを選択すると、アプリがこのオプションを使用することを選択した場合の利点が無効になります。

  4. ID セクションで、グループ ID を選択します。 この選択により、Microsoft Entra ID は、ID トークンのグループ要求でユーザーが割り当てられているグループのオブジェクト ID を送信します。

  5. API の公開オプションを使用して Web API を公開している場合、アクセスセクションのグループ ID オプションを選択することもできます。 Microsoft Entra ID が、アクセス トークンのグループ要求でユーザーが割り当てられているグループのオブジェクト ID を送信します。

  6. アプリの登録ページで、ナビゲーション ペインにある概要を選択して、アプリケーションの概要画面を開きます。

  7. ローカル ディレクトリでのマネージド アプリケーションで、アプリケーションの名前が表示されたハイパーリンクを選択します。 このフィールド タイトルは Managed application in ... のように切り取られる場合があります。 このリンクを選択すると、アプリケーションを作成したテナント内のアプリケーションのサービス プリンシパルに関連付けられているエンタープライズ アプリケーションの概要ページが表示されます。 ブラウザーの [戻る] ボタンを使用して、アプリの登録ページに戻ることができます。

  8. ナビゲーション ペインでユーザーとグループを選択してページを開き、ユーザーとグループをアプリケーションに割り当てます。

  9. ユーザーの追加を選択します。

  10. 結果画面からユーザーとグループを選択します。

  11. このアプリケーションに割り当てるグループを選択します。

  12. 選択を選択して、グループの選択を完了します。

  13. 割り当てを選択して、グループの割り当て操作を完了します。

    以上の手順で、アプリにサインインするユーザーが、これらの割り当てられたグループの 1 つ以上のメンバーである場合、アプリケーションはグループ要求で選択されたグループを受け取ることができます。

  14. ナビゲーション ウィンドウでプロパティを選択してページを開き、アプリケーションの基本プロパティのリストを表示します。ユーザーの割り当てが必要フラグをはいに設定します。

重要

ユーザーの割り当てが必要はいに設定すると、ユーザーとグループ ペインでアプリケーションに割り当てられたユーザーのみがアプリにサインインできていることを Microsoft Entra ID がチェックします。 ユーザーは直接割り当てることも、所属するセキュリティ グループを割り当てることもできます。

グループ ID を認識するようにアプリ (java-servlet-webapp-groups) を構成する

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

重要

トークン構成ページで groupID 以外のオプション (DNSDomain\sAMAccountName など) を選択している場合は、次の手順でオブジェクト ID ではなくグループ名 (例: contoso.com\Test Group) を入力する必要があります。

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

  2. {enter-your-admins-group-id-here} という文字列を見つけて、既存の値を、Azure portal からコピーした GroupAdmin グループのオブジェクト ID に置き換えます。 プレースホルダーの値から中かっこも削除してください。

  3. {enter-your-users-group-id-here} という文字列を見つけて、既存の値を、Azure portal からコピーした GroupMember グループのオブジェクト ID に置き換えます。 プレースホルダーの値から中かっこも削除してください。

サンプルをビルドする

Maven を使用してサンプルをビルドするには、サンプルの pom.xml ファイルが含まれているディレクトリに移動して、次のコマンドを実行します。

mvn clean package

このコマンドを実行すると、 さまざまなアプリケーション サーバーで実行できる .war ファイルが生成されます。

サンプルの実行

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

前提条件

Maven プラグインを構成する

Azure App Service に対するデプロイ プロセスでは、Azure CLI からの Azure 資格情報が自動的に使用されます。 Azure CLI がローカルにインストールされていない場合、Maven プラグインは OAuth またはデバイス ログインを使用して認証します。 詳細については、Maven プラグインによる認証に関するページを参照してください。

プラグインを構成するには、次の手順に従います。

  1. 次のコマンドを実行してデプロイを構成します。 このコマンドは、Azure App Service オペレーティング システム、Java バージョン、および Tomcat バージョンを設定するのに役立ちます。

    mvn com.microsoft.azure:azure-webapp-maven-plugin:2.12.0:config
    
  2. 新しい実行構成を作成するで、Y を押して、Enter を押します。

  3. Windows の場合は、OS の値を定義します1 を押し、Linux の場合は 2 を押してから、Enter を押します。

  4. Java 11 の場合は javaVersion の値を定義します2 を押し、Enter を押します。

  5. Tomcat 9.0 の場合は、webContainer の値を定義します4 を押し、Enter を押します。

  6. pricingTier の値を定義しますEnter を押し、既定値である P1v2 層を選択します。

  7. 確認Y を押し、Enter を押します。

デプロイ プロセスの出力例を次に示します。

Please confirm webapp properties
AppName : msal4j-servlet-auth-1707209552268
ResourceGroup : msal4j-servlet-auth-1707209552268-rg
Region : centralus
PricingTier : P1v2
OS : Linux
Java Version: Java 11
Web server stack: Tomcat 9.0
Deploy to slot : false
Confirm (Y/N) [Y]: [INFO] Saving configuration to pom.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  37.112 s
[INFO] Finished at: 2024-02-06T08:53:02Z
[INFO] ------------------------------------------------------------------------

選択内容の確認後、プラグインによって、アプリを Azure App Service で実行するよう構成するのに必要なプラグイン要素および設定が、プロジェクトの pom.xml ファイルに追加されます。

pom.xml ファイルの関連部分は、次の例のようになります。

<build>
    <plugins>
        <plugin>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>>azure-webapp-maven-plugin</artifactId>
            <version>x.xx.x</version>
            <configuration>
                <schemaVersion>v2</schemaVersion>
                <resourceGroup>your-resourcegroup-name</resourceGroup>
                <appName>your-app-name</appName>
            ...
            </configuration>
        </plugin>
    </plugins>
</build>

pom.xml 内で App Service の構成を直接変更できます。 一般的な構成をいくつか次の表に示します。

プロパティ Required 説明
subscriptionId false サブスクリプション ID です。
resourceGroup true アプリの Azure リソース グループ。
appName true アプリの名前。
region false アプリをホストするリージョン。 既定値は centralus です。 有効なリージョンについては、「サポートされているリージョン」を参照してください。
pricingTier false アプリの価格レベル。 運用環境のワークロードでは、既定値は P1v2 です。 Java の開発とテストに推奨される最小値は B2 です。 詳細については、「App Service の価格」を参照してください。
runtime false ランタイム環境の構成。 詳細については、「構成の詳細」を参照してください。
deployment false デプロイの構成。 詳細については、「構成の詳細」を参照してください。

構成の完全な一覧については、プラグインのリファレンス ドキュメントを参照してください。 すべての Azure Maven プラグインでは、一連の構成が共通しています。 これらの構成については、「共通の構成」を参照してください。 Azure App Service に固有の構成については、「Azure アプリ: 構成の詳細」を参照してください。

後で使用するために appNameresourceGroup の値を保存しておいてください。

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

アプリケーションを App Service にデプロイすると、リダイレクト URL が、デプロイされたアプリ インスタンスのリダイレクト URL に変更されます。 これらの設定をプロパティー ファイルで変更しするには、次の手順を使用します。

  1. アプリの authentication.properties ファイルに移動し、app.homePage の値をデプロイされたアプリのドメイン名に変更します (次の例を参照)。 たとえば、前の手順でアプリ名に example-domain を選択している場合は、app.homePage の値に https://example-domain.azurewebsites.net を使用する必要があります。 プロトコルを http から https に変更することも必要です。

    # 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://<your-app-name>.azurewebsites.net
    
  2. このファイルを保存した後、次のコマンドを使用してアプリをリビルドします。

    mvn clean package
    

重要

この同じ authentication.properties ファイルに、aad.secret の設定があります。 この値を App Service にデプロイすることはお勧めしません。 また、この値をコードに残しておくことや、それを git リポジトリにプッシュすることは望ましくありません。 このシークレット値をコードから削除する方法の詳細な説明については、「App Service へのデプロイ - シークレットの削除」セクションを参照してください。 ここにはシークレット値を Key Vault にプッシュするための手順や、Key Vault 参照を使用するための手順が説明されています。

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

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

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

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

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

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

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

  6. アプリの URI を、/auth/redirect を追加して入力します。たとえば https://<your-app-name>.azurewebsites.net/auth/redirect のようになります。

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

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

以上で、アプリを Azure App Service にデプロイする準備ができました。 次のコマンドを使用して、デプロイを実行するために Azure 環境にサインインしていることを確認します。

az login

pom.xml ファイルにすべての構成が準備されています。これで、次のコマンドを使用して Java アプリを Azure にデプロイできます。

mvn package azure-webapp:deploy

デプロイが完了すると、アプリケーションを http://<your-app-name>.azurewebsites.net/ で起動できます。 ローカル Web ブラウザーで URL を開くと、msal4j-servlet-auth アプリケーションのスタート ページが表示されます。

サンプルの確認

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

  1. サインインまたはサインアウトの状態が、画面の中央に表示されます。
  2. 画面の隅にある状況依存ボタンを選択します。 このボタンは、アプリを最初に実行するときにサインインと表示します。
  3. 次のページに記載された指示に従い、Microsoft Entra ID テナントのアカウントでサインインします。
  4. 同意画面に、必要となるスコープが表示されます。
  5. 状況依存ボタンの表示がサインアウトに変わり、ユーザー名が表示されます。
  6. ID トークンの詳細を選択すると、ID トークンのデコードされた要求の一部が表示されます。
  7. グループを選択すると、サインインしているユーザーのセキュリティ グループ メンバーシップに関する情報が表示されます。
  8. 管理のみまたは 通常のユーザーを選択して、保護されたエンドポイントを要求するグループにアクセスします。
    • サインインしているユーザーがGroupAdminグループに含まれる場合、ユーザーは両方のページを入力できます。
    • サインインしているユーザーがGroupMember グループに含まれる場合、ユーザーは通常のユーザー ページのみを入力できます。
    • サインインしているユーザーがどちらのグループに含まれない場合、ユーザーは 2 つのページのいずれかにアクセスできません。
  9. 画面隅のボタンを使用してサインアウトします。
  10. サインアウトした後、ID トークンの詳細を選択して、ユーザーが承認されていない場合に、アプリに ID トークン要求の代わりに表示される 401: unauthorized エラーを確認します。

コードについて

このサンプルでは、MSAL for Java (MSAL4J) を使用してユーザーがサインインし、グループ要求を含む ID トークンを取得します。 ID トークンで排出されるグループの数が多すぎる場合、サンプルは Microsoft Graph SDK for Java を使用して Microsoft Graph からグループ メンバーシップ データを取得します。 ユーザーが所属するグループに応じて、サインインしているユーザーは、Admins OnlyRegular Users の保護されたページのいずれにもアクセスできないか、1 つ、または両方にアクセスできます。

このサンプルの動作をレプリケートする場合は、Maven を使用して MSAL4J と Microsoft Graph SDK をプロジェクトに追加する必要があります。 pom.xml ファイルと、src/main/java/com/microsoft/azuresamples/msal4j フォルダーの helpers フォルダーと authservlets フォルダーにあるコンテンツをコピーできます。 authentication.properties ファイルも必要です。 これらのクラスとファイルには、さまざまなアプリケーションで使用できる汎用コードが含まれています。 サンプルの残りもコピーできますが、他のクラスとファイルは、このサンプルの目的に合わせて特別にビルドされたものです。

内容

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

ファイル/フォルダー 説明
src/main/java/com/microsoft/azuresamples/msal4j/groupswebapp/ このディレクトリには、アプリの基幹業務ロジックを定義するクラスが含まれています。
src/main/java/com/microsoft/azuresamples/msal4j/authservlets/ このディレクトリには、サインインとサインアウトのエンドポイントに使用されるクラスが含まれています。
____Servlet.java 使用可能なすべてのエンドポイントは、末尾が ____Servlet.java である .java クラスに定義されます。
src/main/java/com/microsoft/azuresamples/msal4j/helpers/ 認証に使用するヘルパー クラス。
AuthenticationFilter.java 認証されていない要求を、保護されたエンドポイントの 401 ページにリダイレクトします。
src/main/resources/authentication.properties Microsoft Entra ID とプログラム構成。
src/main/webapp/ このディレクトリには UI - JSP テンプレートが含まれています
CHANGELOG.md サンプルに対する変更の一覧。
CONTRIBUTING.md サンプルに貢献するためのガイドライン。
ライセンス サンプルのライセンス。

超過分の処理などのグループ要求をトークンで処理する

以降のセクションでは、アプリによるグループ要求の処理方法について説明します。

グループ要求

サインインしているユーザーがメンバーとして含まれるセキュリティ グループのオブジェクト ID は、次の例に示すように、トークンのグループ要求で返されます。

{
  ...
  "groups": [
    "0bbe91cc-b69e-414d-85a6-a043d6752215",
    "48931dac-3736-45e7-83e8-015e6dfd6f7c",]
  ...
}

グループの超過処理要求

トークンのサイズが HTTP ヘッダー サイズの上限を超えないよう、Microsoft ID プラットフォームでは、グループ要求に含まれるオブジェクト ID の数が制限されます。

超過制限は、SAML トークンの場合は 150、JWT トークンの場合は 200、シングル ページ アプリケーションの場合は 6 です。 ユーザーが超過分の制限を超えるグループのメンバーである場合、Microsoft ID プラットフォームは、トークン内のグループ要求のグループ ID を出力しません。 代わりに、Microsoft Graph API に照会してユーザーのグループ メンバーシップを取得するようアプリケーションに指示する超過要求がトークンに追加されます(次の例を参照)。

{
  ...
  "_claim_names": {
    "groups": "src1"
    },
    {
   "_claim_sources": {
    "src1": {
        "endpoint":"[Graph Url to get this user's group membership from]"
        }
    }
  ...
}

テスト用にこのサンプルで超過シナリオを作成する

超過シナリオを作成するには、次の手順に従います。

  1. 作成するグループの数が多く、それらをユーザーを割り当てる場合は、AppCreationScripts フォルダーにある BulkCreateGroups.ps1 ファイルを使用します。 このファイルを使用しては、開発中の超過シナリオをテストできます。 BulkCreateGroups.ps1 スクリプトにあるユーザーの objectId を変更することを忘れないでください。

  2. このサンプルを実行して超過分が発生すると、ユーザーのサインイン後に _claim_names がホーム ページに表示されます。

  3. グループの超過分が発生しないように、可能であればグループ フィルター機能を使用することを強くお勧めします。 詳細については、「ユーザーが割り当てられる可能性のある、フィルター処理されたグループのセットからグループ要求の値を受け取るようアプリケーションを構成する」を参照してください。

  4. グループの超過分の発生を回避できない場合は、次の手順を使用してトークン内のグループ要求を処理することをお勧めします。

    1. 要求 _claim_names をチェックし、groups になるいずれかの値が含まれていないか確認してください。 この要求は超過分を示します。
    2. 見つかった場合は、_claim_sources に指定されたエンドポイントを呼び出して、ユーザーのグループを取得します。
    3. 見つからなければ、ユーザーのグループのグループ要求を調べます。

Note

超過分の処理には、サインインしているユーザーのグループ メンバーシップを読み取るために、Microsoft Graph を呼び出す必要があるため、getMemberObjects 関数に対する GroupMember.Read.All のアクセス許可がアプリに必要です。

Microsoft Graph のプログラミングの詳細については、「Microsoft Graph の開発者向け概要」の動画を参照してください。

ConfidentialClientApplication

ConfidentialClientApplication インスタンスが AuthHelper.java ファイルに作成されます (次の例を参照)。 このオブジェクトにより Microsoft Entra 認証 URL の作成と、アクセス トークンの認証トークンの交換が行われます。

// getConfidentialClientInstance method
IClientSecret secret = ClientCredentialFactory.createFromSecret(SECRET);
confClientInstance = ConfidentialClientApplication
                      .builder(CLIENT_ID, secret)
                      .authority(AUTHORITY)
                      .build();

インスタンス化には次のパラメーターが使用されます。

  • アプリのクライアント ID。
  • クライアント シークレット。機密クライアント アプリケーションに必要です。
  • Microsoft Entra ID 認証機関。Microsoft Entra テナント ID が含まれます。

上記の例では、Config.java ファイルにあるプロパティ リーダ0を使用して、値が authentication.properties ファイルから読み取られます。

ステップバイステップのチュートリアル

次の手順で、アプリの機能をチュートリアルで紹介します。

  1. サインイン プロセスの最初のステップでは、Microsoft Entra ID テナントの /authorize エンドポイントに要求を送信します。 承認要求の URL を作成するには、MSAL4J の ConfidentialClientApplication インスタンスを利用します。 アプリでブラウザーをこの URL にリダイレクトし、ユーザーはそこでサインインします。

    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: Microsoft Entra がユーザー資格情報を収集した後、認証コードと共にブラウザーをリダイレクトする場所。 これは Azure portal にある Microsoft Entra ID アプリ登録のリダイレクト URI と一致する必要があります。
    • SCOPES: スコープはアプリケーションで要求されるアクセス許可です。
      • 通常、ID トークンの応答を受信するには、openid profile offline_access の 3 つのスコープがあれば十分です。
      • authentication.properties ファイルに、アプリで要求されるすべてのスコープの一覧が入力されています。 User.Readなど、その他のスコープを追加できます。
  2. Microsoft Entra ID により、ユーザーにサインイン プロンプトが表示されます。 サインインが成功すると、ユーザーのブラウザーはアプリのリダイレクト エンドポイントにリダイレクトされます。 このエンドポイントへの有効な要求には、、認証コードが含まれています。

  3. その後、この承認コードは、ConfidentialClientApplication のインスタンスによって、Microsoft Entra ID の ID トークンとアクセス トークンに交換されます。

    // 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 のインスタンスを使用して) IdentityContextData をインスタンス化できます。

    // 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());
    
    // handle groups overage if it has occurred.
    handleGroupsOverage(contextAdapter);
    
  5. 前の手順の後、IdentityContextData のインスタンスを使用して context.getGroups() を呼び出し、グループ メンバーシップを抽出します。

  6. ユーザーが 200 を超えるグループのメンバーである場合、呼び出しの呼び出handleGroupsOverage()context.getGroups()がない場合は空になる可能性があります。 一方、 context.getGroupsOverage() 超過分が発生したことを通知し、グループの完全なリストを取得するには Microsoft Graph の呼び出しが必要であることを示す戻り true値です。 このアプリケーションで超過の発生時に context.setGroups() を使用する方法については、AuthHelper.java にある handleGroupsOverage() メソッドを参照してください。

ルートを保護する

サンプル アプリでルートへのアクセスをフィルター処理する方法については、AuthenticationFilter.java を参照してください。 authentication.properties ファイルを見ると、認証済みのユーザーだけがアクセスできるルートが app.protect.authenticated プロパティにコンマで区切って入力されていることがわかります (次の例を参照)。

# for example, /token_details requires any user to be signed in and does not require special groups claim
app.protect.authenticated=/token_details

app.protect.groups でコンマ区切りのルール セットに入力されたすべてのルートでは、認証されていないユーザーに対する制限がないこともわかります (次の例を参照)。 ただし、これらのルートには、グループ メンバーシップのリストもスペース区切りで入力されています。 これらのグループの少なくとも 1 つに属しているユーザーだけが、認証後にこれらのルートにアクセスできます。

# define short names for group IDs here for the app. This is useful in the next property (app.protect.groups).
# EXCLUDE the curly braces, they are in this file only as delimiters.
# example:
# app.groups=groupA abcdef-qrstuvw-xyz groupB abcdef-qrstuv-wxyz
app.groups=admin {enter-your-admins-group-id-here}, user {enter-your-users-group-id-here}

# A route and its corresponding group(s) that can view it, <space-separated>; the start of the next route & its group(s) is delimited by a <comma-and-space-separator>
# this says: /admins_only can be accessed by admin group, /regular_user can be accessed by admin group and user group
app.protect.groups=/admin_only admin, /regular_user admin user

スコープ

スコープはアプリケーションが要求するアクセス レベルを Microsoft Entra ID に通知します。

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

アプリケーションで要求されるスコープについては、authentication.properties を参照してください。 既定では、アプリケーションはスコープの値を GroupMember.Read.All に設定します。 Microsoft Graph API のこのスコープが、アプリケーションがユーザーのグループ メンバーシップを取得するために Graph を呼び出す場合に要求されます。

詳細