ロールとロール要求を使用して Java WebLogic アプリをセキュリティで保護する
この記事では、OpenID Connect を使用してユーザーのサインインを行い、Microsoft Entra ID アプリケーション ロール (アプリ ロール) で認証を行う WebLogic アプリについて説明します。
このアプリケーションは、Microsoft Entra ID のアプリケーション ロールとロール要求機能を使用して、ロールベースのアクセス制御 (RBAC) を実装します。 もう 1 つの方法は、Microsoft Entra ID のグループとグループ要求を使うことです。 Microsoft Entra ID グループとアプリケーション ロールは相互に排他的ではありません。 両方を使用して、アクセスをきめ細かく制御することができます。
また、RBAC にアプリケーション ロールとロール要求を使用することで、認証ポリシーをセキュアに適用することもできます。
このシナリオとサンプルを紹介するビデオ、「アプリ ロール、セキュリティ グループ、スコープ、ディレクトリ ロールを使用した承認をアプリケーションに実装する」をご覧ください。
このシナリオやその他のシナリオでのプロトコルの使用について詳しくは、「認証と承認」を参照してください。
このアプリケーションでは、MSAL for Java (MSAL4J) を使用してユーザーのサインインを行い、Microsoft Entra ID から ID トークンを取得します。
このサンプルは、最初に MSAL for Java (MSAL4J) を使用してユーザーのサインインを行います。 ホーム ページには、ユーザーが ID トークン内の要求を確認するためのオプションが表示されます。 このアプリケーションでは、ユーザーが割り当てられているアプリ ロールに応じて、特権管理者ページまたは通常のユーザー ページを表示することもできます。 これを例示する目的は、アプリケーション内で、ユーザーによる特定の機能やページへのアクセスを、所属するロールに基づいて一部のユーザーに制限する方法を示すことです。
このような承認は、RBAC を使用して実装されます。 RBAC を使用する場合、管理者は、個々のユーザーまたはグループではなく、ロールにアクセス許可を付与します。 その後、管理者はロールをさまざまなユーザーやグループに割り当てて、コンテンツや機能に誰がアクセスできるかを制御します。
このサンプル アプリケーションには、次の 2 つのアプリケーション ロールを定義します。
PrivilegedAdmin
: 管理者のみページと通常のユーザー ページへのアクセスが許可されます。RegularUser
: 通常のユーザー ページへのアクセスが許可されます。
これらのアプリケーション ロールは Azure portal でアプリケーションの登録マニフェストに定義されます。 ユーザーがアプリケーションにサインインすると、Microsoft Entra ID はロール メンバーシップの形式でユーザーに個別に付与された各ロールに対し、ロール要求を出力します。
Azure portal を通じて、ユーザーとグループをロールに割り当てることができます。
Note
https://login.microsoftonline.com/common/
エンドポイントがユーザーのサインイン権限として使用されている場合、テナント内の ゲスト ユーザーにはロール要求が存在しません。 次のような https://login.microsoftonline.com/tenantid
テナント ID エンドポイントにユーザーをサインインさせる必要があります。
前提条件
- JDK - バージョン 8 以降
- Maven 3
- Microsoft Entra ID テナント。 詳細については、「Microsoft Entra ID テナントの取得方法」をご覧ください。
- 組織のディレクトリに含まれるアカウントだけを操作する (シングルテナント モード) 場合は、自分の Microsoft Entra ID テナントのユーザー アカウント。 テナントにまだユーザー アカウントを作成していない場合は、作成してから続行する必要があります。 詳細については、「ユーザーを作成、招待、削除する方法」をご覧ください。
推奨事項
- 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/3-Authorization-II/roles
または、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-servlet-webapp-roles)
最初に、クイック スタート: Microsoft ID プラットフォームにアプリケーションを登録するに記載された説明に従って Azure portal に新しいアプリを登録します。
次の手順を実行して、登録を完了します。
開発者用の Microsoft ID プラットフォームの [アプリの登録] ページに移動します。
[新規登録] を選択します。
表示される アプリケーションの登録ページで、アプリケーションの登録情報を入力します。
名前セクションに、アプリのユーザーに表示されるわかりやすいアプリケーション名を入力します (例:
java-servlet-webapp-roles
)。サポートされているアカウントの種類で、次のオプションのいずれかを選択します。
- 自分のテナントのユーザーのみが使用するアプリケーションをビルドしている場合は (シングルテナント アプリケーション)、この組織のディレクトリ内のアカウントのみを選択します。
リダイレクト URI セクションで、コンボ ボックスの Web を選択し、リダイレクト URI:
http://localhost:8080/msal4j-servlet-roles/auth/redirect
を入力します。
[登録] を選択して、アプリケーションを作成します。
アプリの登録ページで、アプリケーション (クライアント) ID の値を見つけてメモします。 この値は、後ほどアプリの構成ファイルで使用します。
[保存] を選択して変更を保存します。
アプリの登録ページで、ナビゲーション ペインにある 証明書とシークレットを選択してページを開き、シークレットの生成と証明書のアップロードを行います。
[クライアント シークレット] セクションで、 [新しいクライアント シークレット] を選択します。
キーの説明 (例: アプリのシークレット) を入力します。
1 年、2 年、無期限のいずれかの期間を選びます。
[追加] を選択します。 生成された値が表示されます。
生成した値をコピーしてから保存します。 この値は後ほど、コードの構成ファイルに使用します。 この値は二度と表示されず、他の方法でも取得はできません。 そのため、必ず Azure portal から保存した後に、他の画面やペインに移動してください。
アプリケーション ロールの定義
次の手順に従って、アプリのロールを定義します。
同じアプリの登録で、ナビゲーション ペインからアプリ ロールを選択します。
アプリ ロールの作成を選択し、次の値を入力または選択します。
- 表示名で、PrivilegedAdmin などのわかりやすい名前を入力します。
- 許可されるメンバーの種類で、ユーザーを選択します。
- 値に PrivilegedAdmin と入力します。
- 説明に管理ページを表示する権限を持つ管理者と入力します。
アプリ ロールの作成を選択し、次の値を入力または選択します。
- 表示名に、RegularUser などのわかりやすい名前を入力します。
- 許可されるメンバーの種類で、ユーザーを選択します。
- 値に RegularUser と入力します。
- 説明にユーザー ページを表示できる通常のユーザーと入力します。
[適用] を選択して変更を保存します。
アプリケーション ロールにユーザーを割り当てる
先ほどに定義したアプリ ロールにユーザーを追加するには、「ロールにユーザーとグループを割り当てる」のガイドラインに従ってください。
アプリの登録を使用するためにアプリ (java-servlet-webapp-roles) を構成する
アプリを構成するには、次の手順に従います。
Note
以降の手順では、ClientID
は Application ID
または AppId
と同じです。
IDE でプロジェクトを開きます。
authentication.properties ファイルを開きます。
{enter-your-tenant-id-here}
という文字列を見つけます。 既存の値を Microsoft Entra ID のテナント ID に置き換えます。{enter-your-client-id-here}
という文字列を見つけて、既存の値をアプリケーション ID または Azure portal からコピーしたjava-servlet-webapp-call-graph
アプリケーションのclientId
に変更します。{enter-your-client-secret-here}
という文字列を見つけて、既存の値を、Azure portal でjava-servlet-webapp-roles
アプリを作成するときに保存した値に置き換えます。app.roles
プロパティを見つけて、値がapp.roles=admin PrivilegedAdmin, user RegularUser
に設定されていることを確認するか、指定したロールの名前に置き換えます。
サンプルをビルドする
Maven を使用してサンプルをビルドするには、サンプルの pom.xml ファイルが含まれているディレクトリに移動して、次のコマンドを実行します。
mvn clean package
このコマンドを実行すると、.war ファイルが作成されます。これはさまざまなアプリケーション サーバーで実行できます。
サンプルのデプロイ
以降の手順では、WebLogic をインストールし、いくつかサーバー ドメインをセットアップします。
WebLogic にデプロイする前に、次の手順を使用してサンプル本体の構成を変更してから、パッケージをビルドまたはリビルドする必要があります。
サンプルで、クライアント ID、テナント、リダイレクト URL などを構成した application.properties ファイルまたは authentication.properties ファイルを探します。
このファイルで、
localhost:8080
またはlocalhost:8443
への参照を、WebLogic が実行される URL とポートに変更します。既定ではlocalhost:7001
になります。また、Azure アプリの登録でも同じ変更を行う必要があります。Azure portal で、認証タブのリダイレクト URI の値に対し、これを設定してください。
Web コンソールを使用してサンプルを WebLogic にデプロイするには、次の手順に従います。
DOMAIN_NAME\bin\startWebLogic.cmd を使用して WebLogic サーバーを起動します。
ブラウザーで WebLogic web コンソール (
http://localhost:7001/console
) に移動します。ドメイン構造>デプロイに移動し、インストール、ファイルのアップロードの順に選択して、Maven を使用してビルドする .war ファイルを探します。
[この展開をアプリケーションとしてインストールする] を選択し、次へを選択します。終了を選択して、保存を選択します。
ほとんどの設定は既定のままで問題ありませんが、サンプル構成または Azure アプリの登録で設定したリダイレクト URI と一致するようにアプリケーションを指定する必要があります。 つまり、リダイレクト URI が
http://localhost:7001/msal4j-servlet-auth
であれば、アプリケーション名をmsal4j-servlet-auth
にする必要があります。ドメイン構造>のデプロイに戻り、アプリケーションを起動します。
アプリケーションが起動したら、
http://localhost:7001/<application-name>/
に移動します。これで、アプリケーションにアクセスできます。
サンプルの確認
次の手順に従ってサンプルを操作します。
- サインインまたはサインアウトの状態が、画面の中央に表示されます。
- 画面の隅にある状況依存ボタンを選択します。 このボタンは、アプリを最初に実行するときにサインインと表示します。
- 次のページに記載された指示に従い、Microsoft Entra ID テナントのアカウントでサインインします。
- 同意画面に、必要となるスコープが表示されます。
- 状況依存ボタンの表示がサインアウトに変わり、ユーザー名が表示されます。
- ID トークンの詳細を選択すると、ID トークンのデコードされた要求の一部が表示されます。
- 管理者のみを選択し、
/admin_only
ページを表示します。 このページを表示できるのは、PrivilegedAdmin
のアプリ ロールを持つユーザーだけです。 それ以外のユーザーには、承認エラー メッセージが表示されます。 - 通常のユーザーを選択し、
/regular_user
ページを表示します。 このページを表示できるのは、RegularUser
またはPrivilegedAdmin
のアプリ ロールを持つユーザーだけです。 それ以外のユーザーには、承認エラー メッセージが表示されます。 - 画面隅のボタンを使用してサインアウトします。
コードについて
このサンプルでは、MSAL for Java (MSAL4J) を使用してユーザーがサインインし、ロール要求を含む ID トークンを取得します。 存在するロール要求に基づいて、サインインしているユーザーは、Admins Only
と Regular Users
の保護されたページのいずれにもアクセスできないか、1 つ、または両方にアクセスできます。
このサンプルの動作をレプリケートする場合は、src/main/java/com/microsoft/azuresamples/msal4j フォルダーにある pom.xml ファイルと、helpers フォルダーおよび authservlets フォルダーの内容をコピーします。 authentication.properties ファイルも必要です。 これらのクラスとファイルには、さまざまなアプリケーションで使用できる汎用コードが含まれています。 サンプルの残りもコピーできますが、他のクラスとファイルは、このサンプルの目的に合わせて特別にビルドされたものです。
Contents
次の表に、サンプル プロジェクト フォルダーの内容を示します。
ファイル/フォルダー | 説明 |
---|---|
src/main/java/com/microsoft/azuresamples/msal4j/roles/ | このディレクトリには、アプリの基幹業務ロジックを定義するクラスが含まれています。 |
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 トークンのロール要求を処理する
トークンのロール要求には、サインインしているユーザーが割り当てられているロールの名前が含まれます (次の例を参照)。
{
...
"roles": [
"Role1",
"Role2",]
...
}
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 ファイルから読み取られます。
ステップバイステップのチュートリアル
次の手順で、アプリの機能をチュートリアルで紹介します。
サインイン プロセスの最初のステップでは、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 ID がユーザー資格情報を収集した後、認証コードと共にブラウザーをリダイレクトする場所。 これは Azure portal にある Microsoft Entra ID アプリ登録のリダイレクト URI と一致する必要があります。SCOPES
: スコープはアプリケーションで要求されるアクセス許可です。- 通常、ID トークンの応答を受信するには、
openid profile offline_access
の 3 つのスコープがあれば十分です。 - authentication.properties ファイルに、アプリで要求されるすべてのスコープの一覧が入力されています。
User.Read
など、その他のスコープを追加できます。
- 通常、ID トークンの応答を受信するには、
Microsoft Entra ID により、ユーザーにサインイン プロンプトが表示されます。 サインインが成功すると、ユーザーのブラウザーはアプリのリダイレクト エンドポイントにリダイレクトされます。 このエンドポイントへの有効な要求には、、認証コードが含まれています。
その後、この承認コードは、
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
: 前のステップで使用したスコープを、再度渡す必要があります。
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());
ルートを保護する
サンプル アプリでルートへのアクセスをフィルター処理する方法については、「AuthenticationFilter.java」を参照してください。 authentication.properties ファイルを見ると、認証済みのユーザーだけがアクセスできるルートが app.protect.authenticated
プロパティにコンマで区切って入力されていることがわかります (次の例を参照)。
# for example, /token_details requires any user to be signed in and does not require special roles claim(s)
app.protect.authenticated=/token_details
app.protect.roles
でコンマ区切りのルール セットに入力されたすべてのルートでは、認証されていないユーザーに対する制限がないこともわかります (次の例を参照)。 ただし、これらのルートには、アプリ ロール メンバーシップのリストもスペース区切りで入力されています。認証後に、対応するロールの少なくとも 1 つを持つユーザーのみがこれらのルートにアクセスできます。
# local short names for app roles - for example, sets admin to mean PrivilegedAdmin (useful for long rule sets defined in the next key, app.protect.roles)
app.roles=admin PrivilegedAdmin, user RegularUser
# A route and its corresponding <space-separated> role(s) that can access it; the start of the next route & its role(s) is delimited by a <comma-and-space-separator>
# this says: /admins_only can be accessed by PrivilegedAdmin, /regular_user can be accessed by PrivilegedAdmin role and the RegularUser role
app.protect.roles=/admin_only admin, /regular_user admin user
スコープ
スコープはアプリケーションが要求するアクセス レベルを Microsoft Entra ID に通知します。
Microsoft Entra ID は、要求されたスコープに基づいて、サインイン時にユーザーに同意ダイアログを表示します。 ユーザーが 1 つ以上のスコープに同意してトークンを取得すると、同意先のスコープが結果の access_token
にエンコードされます。
アプリケーションで要求されるスコープについては、authentication.properties を参照してください。 これらの 3 つのスコープは MSAL で要求され、既定で Microsoft Entra ID によって指定されます。
詳細
- Java 用 Microsoft 認証ライブラリ (MSAL)
- Microsoft ID プラットフォーム
- クイック スタート: Microsoft ID プラットフォームにアプリケーションを登録する
- Microsoft Entra ID アプリケーションの同意エクスペリエンスについて理解する
- ユーザーおよび管理者の同意について
- MSAL コードのサンプル
- アプリケーションにアプリ ロールを追加してトークンで受け取る方法
- Microsoft Entra ID でアプリのユーザー割り当てを管理する
次のステップ
Azure Virtual Machines 上の WebLogic に Java WebLogic アプリをデプロイする