Java CLIアプリケーション(not Webアプリケーション)からADB2Cにアクセスして認証する方法 3つ。
実装にはMSAL for Javaを使う。
MSAL for .NET を使えば.NETアプリやUnityからも同様に認証できるはず。
1. インタラクティブなトークン取得
認証には「OAuth 2.0 認可コード フロー + PKCE」が使用される。
MSAL4JがローカルホストでWebサーバーを動かして、それがADB2Cが連携することで、ブラウザーベースの認証が行われる。
認証するときにブラウザーが開かれ、ADB2Cのログイン画面が表示される。
ユーザーIDとパスワードを入力すると、ローカルホストのWebサーバーに認可コードが渡されるので、MSAL4JはトークンエンドポイントにアクセスしてIDトークンとアクセストークンを取得する。
ADB2Cの設定
- ユーザーフロー
- 「サインイン」か「サインアップとサインイン」を構成する
- アプリケーションの登録
- アプリを登録する際に「パブリック クライアント フローを許可する」を有効にする
- クライアントシークレットは作成しなくていい
- プラットフォーム構成は「モバイル アプリケーションとデスクトップ アプリケーション」を選ぶとよい
- リダイレクトURIは
http://localhost
とする(ポート番号無し、末尾スラッシュ無しでよい)
- リダイレクトURIは
- 「暗黙的な許可およびハイブリッド フロー」では、IDトークンとアクセストークンの両方にチェックを入れておく(たぶん必要)
- APIの公開(スコープ)は、設定してもしなくてもいい
- 設定しない場合も、Javaコードで指定するスコープに値を入れる必要がある(後述)
- 設定する場合は、「APIの公開」で任意のスコープを登録し、「APIのアクセス許可」で、登録したスコープを許可する
- アクセス許可の設定ページの一番下にある「エンタープライズ アプリケーション」へのリンクをたどり、「(ADB2C テナント名)に管理者の同意を与えます。」ボタンを押して、管理者として同意しておくこと
- アプリを登録する際に「パブリック クライアント フローを許可する」を有効にする
Javaコード
-
com.microsoft.aad.msal4j.PublicClientApplication
を使用する- クライアントシークレットを使わない
- Authority は
https://<yourdomain>.b2clogin.com/<yourdomain>.onmicrosoft.com/<policyname>/
(サインインフローなど) -
InteractiveRequestParameters
を引数にしてacquireToken
を呼び出す - scopesには アプリのクライアントIDを指定するか、APIの公開で設定したスコープを指定する
- MSAL4Jが必ずアクセストークンを要求するため、APIスコープを設定しない場合は回避策としてクライアントIDを渡す。 https://github.com/AzureAD/microsoft-authentication-library-for-java/wiki/Known-Issues-and-Workarounds#b2c
- APIスコープを設定している場合は、
https://<yourdomain>.onmicrosoft.com/<application id>/<scope.name>
のような形式
2. プログラムからユーザーIDとパスワードを渡してトークンを取得
認証には「OAuth 2.0 リソース所有者パスワード資格情報フロー(ROPC)」が使用される。
ブラウザーは必要ないので便利だが、プログラムがユーザーのパスワードを直接扱うため、一般的にはリスクがあり推奨されない方法とされる。
(たとえば、悪意のあるOSSライブラリーが組み込まれたプログラムを起動してしまうと、実行ユーザーの権限で、メモリ上のユーザーIDとパスワードが盗まれ、外部に送信してしまうかもしれない。また、MFAを有効にできないので、盗まれたユーザーIDとパスワードが悪用されやすい。)
ADB2Cの設定
- ユーザーフロー
- 「リソース所有者のパスワード資格情報 (ROPC) を使用してサインインする」を構成する
- アプリケーションの登録
- アプリを登録する際に「パブリック クライアント フローを許可する」を有効にする
- クライアントシークレットは作成しなくていい
- プラットフォーム構成は必要ない
- 暗黙のフローを有効にする必要があるが、プラットフォーム構成をせずに暗黙のフローを有効にするには、「マニフェスト」からオンラインエディターで
"oauth2AllowImplicitFlow": true,
と書き換えて保存する。 - APIの公開(スコープ)は、設定してもしなくてもいい
- 設定しない場合も、Javaコードで指定するスコープに値を入れる必要がある(後述)
- 設定する場合は、「APIの公開」で任意のスコープを登録し、「APIのアクセス許可」で、登録したスコープを許可する
- アクセス許可の設定ページの一番下にある「エンタープライズ アプリケーション」へのリンクをたどり、「(ADB2C テナント名)に管理者の同意を与えます。」ボタンを押して、管理者として同意しておくこと
- アプリを登録する際に「パブリック クライアント フローを許可する」を有効にする
Javaコード
-
com.microsoft.aad.msal4j.PublicClientApplication
を使用する- クライアントシークレットを使わない
- Authority は
https://<yourdomain>.b2clogin.com/<yourdomain>.onmicrosoft.com/<policyname>/
(ROPCフロー) -
UserNamePasswordParameters
を引数にしてacquireToken
を呼び出す - scopesには アプリのクライアントIDを指定するか、APIの公開で設定したスコープを指定する
- MSAL4Jが必ずアクセストークンを要求するため、APIスコープを設定しない場合は回避策としてクライアントIDを渡す。 https://github.com/AzureAD/microsoft-authentication-library-for-java/wiki/Known-Issues-and-Workarounds#b2c
- APIスコープを設定している場合は、
https://<yourdomain>.onmicrosoft.com/<application id>/<scope.name>
のような形式
3. ユーザーではなく、デーモンアプリとしてトークンを取得する
認証には「OAuth 2.0 クライアント資格情報フロー」が使用される。
クライアントIDとクライアントシークレットだけで認証し、ADB2Cに登録したアプリケーション自身のトークンを取得することになる。
IDトークンは得られず、アクセストークンだけが得られる。
トークンに含まれる sub/oidクレームの値は、アプリケーションのサービスプリンシパルのオブジェクト IDである。(「概要」の、「ローカル ディレクトリでのマネージド アプリケーション」から表示可能。)
ADB2Cの設定
- ユーザーフロー
- 「サインイン」か「サインアップとサインイン」を構成する
- ユーザーのサインインを伴わないはずなので、別の構成でもよいかもしれない
- 「サインイン」か「サインアップとサインイン」を構成する
- アプリケーションの登録
- パブリック クライアント フローを許可しない
- クライアントシークレットを追加しておく
- プラットフォーム構成は必要ない
- 暗黙的な許可の設定は必要ない
- APIの公開(スコープ)は、設定してもしなくてもいい
- 設定しない場合も、「APIの公開」でアプリケーション ID の URIを設定しておく(デフォルトはクライアントIDの値)
- 設定する場合は、「APIの公開」で任意のスコープを登録し、「APIのアクセス許可」で、登録したスコープを許可する
- アクセス許可の設定ページの一番下にある「エンタープライズ アプリケーション」へのリンクをたどり、「(ADB2C テナント名)に管理者の同意を与えます。」ボタンを押して、管理者として同意しておくこと
Java コード
-
com.microsoft.aad.msal4j.ConfidentialClientApplication
を使用する- クライアントシークレットを使う
- Authority は
https://<yourdomain>.b2clogin.com/<yourdomain>.onmicrosoft.com/<policyname>/
-
ClientCredentialParameters
を引数にしてacquireToken
を呼び出す - scopesには APIの公開で設定したスコープを指定する
- アプリケーション ID URIだけ設定している場合は、
https://<yourdomain>.onmicrosoft.com/<application id>/.default
- APIスコープを設定している場合は、
https://<yourdomain>.onmicrosoft.com/<application id>/<scope.name>
のような形式
- アプリケーション ID URIだけ設定している場合は、