Microsoft ID プラットフォームと OAuth 2.0 暗黙的な許可のフロー
Microsoft ID プラットフォームでは、OAuth 2.0 の仕様で説明されているように、OAuth 2.0 の暗黙的な許可フローがサポートされています。 暗黙的な許可には、トークン (ID トークンまたはアクセス トークン) が /token エンドポイントではなく /authorize エンドポイントから直接返されるという特徴があります。 これは多くの場合、"ハイブリッド フロー" と呼ばれる承認コード フローの一部として使用され、承認コードと共に /authorize 要求で ID トークンを取得します。
この記事では、Microsoft Entra ID からのトークンを要求するために、アプリケーションでプロトコルに対して直接プログラミングする方法について説明します。 可能な場合は、トークンを取得してセキュリティで保護された Web API を呼び出す代わりに、サポートされている Microsoft 認証ライブラリ (MSAL) を使用することをお勧めします。 MSAL を使用するコード サンプルの一覧については、Microsoft ID プラットフォーム コード サンプルを参照してください。
警告
マイクロソフトは、暗黙的な許可のフローを使用しないようお勧めします。 ほとんどのシナリオでは、より安全な代替手段を利用でき、推奨されます。 このフローの構成によっては、アプリケーションで非常に高い信頼度が要求されるため、他のフローには存在しないリスクが伴います。 このフローは、より安全なフローが実行可能ではない場合にのみ使用してください。 詳細については、「暗黙的な許可フローに関するセキュリティの問題」を参照してください。
プロトコルのダイアグラム
次の図は、暗黙的なサインイン フローの全体像を示しています。各手順については、この後のセクションで詳しく説明します。
OAuth2 の暗黙的な許可の適切なシナリオ
暗黙的な許可は、サード パーティの クッキー がなくてもアプリケーションに影響を与えないサインイン フローの最初の対話的な部分でしか信頼できません。 つまり、アプリケーションが承認エンドポイントからのトークンとコードを要求するハイブリッド フローの一部としてのみこの許可を使用すべきです。 ハイブリッド フローでは、更新トークンと交換可能なコードをアプリケーションが受け取ることができるため、アプリケーションのログイン セッションは時間が経過しても有効なままになります。
認証コード フローを優先する
サード パーティのクッキーのサポートを削除するブラウザーでは、暗黙的な許可のフローは、認証方法として適切ではありません。 暗黙的なフローのサイレント シングル サインオン (SSO) 機能は、サード パーティのクッキーがないと機能しないため、新しいトークンを取得しようとするとアプリケーションが中断します。 新しいアプリケーションではすべて、暗黙的なフローの代わりにシングル ページ アプリをサポートする認証コード フローを使用することを強くお勧めします。 既存のシングル ページ アプリも認証コード フローに移行するようにしてください。
暗黙的な許可フローに関するセキュリティの問題
暗黙的な許可フローは、サーバーが POST データの安全な処理を制御できる従来の Web アプリケーションを対象としています。 暗黙的な許可フローを使用してトークンを配信するには、主に 2 つの方法があります。response_mode
が URL フラグメントとして返されるか、クエリ パラメーターとして (form POST
と GET
を使用して) 返されます。 response_mode=form_post
である暗黙的なフローでは、トークンは HTML 形式の POST を介してクライアントのリダイレクト URI に安全に配信されます。 このメソッドは、トークンが URL フラグメントで公開されないようにします。これにより、ブラウザー履歴または参照元ヘッダーによるトークン漏えいのリスクを回避できます。
暗黙的フローに関するセキュリティ上の問題は、トークンが response_mode=fragment
を使用して配信されるときに発生します。 URL フラグメントは、#
記号の後にある URL の一部であり、ブラウザーが新しいページを要求したときにサーバーに送信されませんが、ブラウザーで実行されている JavaScript で使用できます。 これは、トークンがページで実行されている JavaScript に公開されることを意味します。これは、ページにサード パーティ製のスクリプトが含まれている場合、セキュリティ上のリスクになる可能性があります。 SPA のトークンに関するこのセキュリティ上の問題は、form POST
を使用した暗黙的なフローにも適用されません。
暗黙的な許可またはハイブリッド フローを使用してアクセス トークンまたは ID トークンの発行を要求された場合にそれを許可するべきタイミングは?
暗黙的な許可とハイブリッド フローは、他の OAuth フローほど安全ではありません。 絶対に必要でない限り、アプリの登録で暗黙的な許可またはハイブリッド フローを使用してアクセス トークンまたは ID トークンの発行を要求された場合、それを許可するべきではありません。 あなた (または開発者) が認証と認可を実装するためにアプリケーションで MSAL を使用している場合、どちらのフィールドも有効にする必要はありません。
ただし、あなた (または開発者) がアプリケーションで MSAL を使用していない場合のため、アクセス トークンまたは ID トークンを有効にするべきタイミングの概要が次の表に示されています。
構築中のアプリケーションの種類 | アプリの登録で有効にするべきトークン |
---|---|
PKCE で認可コード フローを使用しない SPA (シングルページ アプリケーション) | アクセス トークンおよび ID トークン |
暗黙的フローを使用して JavaScript 経由で Web API を呼び出す Web または SPA アプリケーション | アクセス トークンおよび ID トークン |
ハイブリッド認証を使用する ASP.NET Core Web アプリとその他の Web アプリ | ID トークン |
サインイン要求を送信する
最初にユーザーをアプリにサインインするために、OpenID Connect 認証要求を送信し、Microsoft ID プラットフォームから id_token
を取得します。
重要
ID トークンおよびアクセス トークンを正しく要求するには、Microsoft Entra 管理センターの [アプリの登録] ページのアプリ登録で、[暗黙の付与およびハイブリッド フロー] セクションの [ID トークン] および [アクセス トークン] を選択して、対応する暗黙的な許可フローを有効にする必要があります。 それが有効でない場合は、unsupported_response
エラー
The provided value for the input parameter 'response_type' is not allowed for this client. Expected value is 'code'
// Line breaks for legibility only
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&response_type=id_token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid
&response_mode=fragment
&state=12345
&nonce=678910
パラメーター | 型 | 内容 |
---|---|---|
tenant |
required | 要求パスの {tenant} の値を使用して、アプリケーションにサインインできるユーザーを制御します。 使用できる値は、common 、organizations 、consumers およびテナント識別子です。 詳細については、 プロトコルの基礎に関するページを参照してください。 重要なこととして、あるテナントから別のテナントにユーザーをサインインさせるゲスト シナリオでは、ユーザーをリソース テナントに正しくサインインさせるためにテナント識別子を指定する必要があります。 |
client_id |
必須 | アプリに割り当てられている [Microsoft Entra管理センター - アプリの登録] ページのアプリケーション (クライアント) ID。 |
response_type |
必須 | OpenID Connect サインインでは、 id_token を指定する必要があります。 response_type 、token が含まれる場合もあります。 ここで token を使用すると、アプリでは /authorize エンドポイントへ 2 度目の要求を行うことなく、/authorize エンドポイントからアクセス トークンをすぐに受け取ることができます。 token response_type を使用する場合、scope パラメーターには、トークンを発行するリソースを示すスコープを含める必要があります (たとえば、Microsoft Graph では user.read )。 また、承認コード フローで使用するため、承認コードを提供するのに token の代わりに code を含めることもできます。 このid_token +code 応答は、ハイブリッド フローと呼ばれることもあります。 |
redirect_uri |
推奨 | アプリのリダイレクト URI。アプリは、この URI で認証応答を送受信します。 これは、Microsoft Entra 管理センターに登録したリダイレクト URI のいずれかと完全に一致する必要があります。ただし、URL エンコードが行われている必要があります。 |
scope |
必須 | スコープのスペース区切りリスト。 OpenID Connect (id_tokens ) では、スコープとして openid を指定する必要があります。このスコープは、承認 UI で "サインイン" アクセス許可に変換されます。 必要に応じて、その他のユーザー データにアクセスするために email および profile スコープを含めることも可能です。 アクセス トークンを要求する場合、さまざまなリソースに対する同意を求めるこの要求に、他のスコープが含まれていてもかまいません。 |
response_mode |
推奨 | 結果として得られたトークンをアプリに返す際に使用するメソッドを指定します。 既定値は、アクセス トークンだけの query (ただし、要求に id_token が含まれている場合は fragment ) です。 セキュリティ上の理由から、暗黙的フローの form_post を使用して、トークンが URL フラグメントで公開されないようにすることをお勧めします。 |
state |
推奨 | トークン応答にも返される要求に含まれる値。 任意の文字列を指定することができます。 クロスサイト リクエスト フォージェリ攻撃を防ぐために通常、ランダムに生成された一意の値が使用されます。 この状態は、認証要求の前にアプリ内でユーザーの状態 (表示中のページやビューなど) に関する情報をエンコードする目的にも使用されます。 |
nonce |
必須 | 要求に追加する (アプリによって生成された) 値。この値が、最終的な ID トークンに要求として追加されます。 アプリでこの値を確認することにより、トークン再生攻撃を緩和することができます。 通常、この値はランダム化された一意の文字列であり、要求の送信元を特定する際に使用できます。 Id_token が要求された場合のみ必須です。 |
prompt |
省略可能 | ユーザーとの必要な対話の種類を指定します。 現時点で有効な値は、login 、none 、select_account 、consent のみです。 prompt=login を指定すると、ユーザーはその要求に対して自分の認証情報の入力を強制され、シングル サインオンが無効になります。 prompt=none はその反対であり、ユーザーにどのような対話型プロンプトも表示されないようにします。 SSO で確認なしで要求を完了できない場合は、Microsoft ID プラットフォームからエラーが返されます。 prompt=select_account は、ユーザーを、セッションで記憶されているすべてのアカウントが表示されるアカウント ピッカーに送ります。 prompt=consent では、ユーザーがサインインした後で OAuth 同意ダイアログが表示され、アプリへのアクセス許可の付与をユーザーに求めます。 |
login_hint |
省略可能 | このパラメーターを使用すると、ユーザー名が事前にわかっている場合、ユーザーに代わって、サインイン ページのユーザー名とメール アドレスのフィールドに事前に入力することができます。 多くの場合、アプリは、以前のサインインから login_hint オプション クレームを抽出した後、認証時にこのパラメーターを使用します。 |
domain_hint |
省略可能 | これが含まれていると、ユーザーがサインイン ページで実行する電子メール ベースの検出プロセスがスキップされ、多少効率化されたユーザー エクスペリエンスが提供されます。 このパラメーターは、1 つのテナントで動作する基幹業務アプリで一般的に使用され、アプリでは特定のテナント内のドメイン名が提供されます。これにより、ユーザーがそのテナントのフェデレーション プロバイダーに転送されます。 このヒントは、ゲストがこのアプリケーションにサインインできないようにし、FIDO などのクラウド認証情報の使用を制限します。 |
この時点で、ユーザーに認証情報の入力と認証が求められます。 また、Microsoft ID プラットフォームでは、ユーザーが scope
クエリ パラメーターに示されたアクセス許可に同意していることも確認されます。 ユーザーが同意したアクセス許可がこれらの中にない場合、必要なアクセス許可に同意するようユーザーに求めます。 詳細については、「アクセス許可、同意、およびマルチテナント アプリ」を参照してください。
ユーザーが認証され、同意すると、Microsoft ID プラットフォームは response_mode
パラメーターで指定されたメソッドを使用して、指定された redirect_uri
でアプリに応答を返します。
成功応答
response_mode=fragment
と response_type=id_token+code
を使用した成功応答は、次のようになります (読みやすいように改行してあります)。
GET https://localhost/myapp/#
code=0.AgAAktYV-sfpYESnQynylW_UKZmH-C9y_G1A
&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
パラメーター | 説明 |
---|---|
code |
response_type に code が含まれる場合に含まれます。 これは、承認コード フローでの使用に適した承認コードです。 |
access_token |
response_type に token が含まれる場合に含まれます。 アプリが要求したアクセス トークン。 アクセス トークンはデコードしないようにする必要があります。そうしないと、検証した場合に不透明な文字列として扱われます。 |
token_type |
response_type に token が含まれる場合に含まれます。 これは常に Bearer です。 |
expires_in |
response_type に token が含まれる場合に含まれます。 キャッシュ用に有効なトークンの秒数を示します。 |
scope |
response_type に token が含まれる場合に含まれます。 access_token が有効な 1 つ以上のスコープを示します。 要求されたスコープであっても、ユーザーに該当しなければ含まれない場合もあります。 たとえば、個人アカウントを使用してログインするときに Microsoft Entra 専用スコープが要求された場合がそれに当たります。 |
id_token |
署名付き JSON Web トークン (JWT)。 アプリは、このトークンのセグメントをデコードして、サインインしたユーザーに関する情報を要求することができます。 アプリはこの値をキャッシュして表示できますが、承認やセキュリティ境界のためにこの値を使用することはできません。 ID トークンの詳細については、id_token reference を参照してください。 注: openid スコープが要求され、response_type に id_tokens が含まれる場合のみ提供されます。 |
state |
要求に state パラメーターが含まれている場合、同じ値が応答にも含まれることになります。 要求と応答に含まれる状態値が同一であることをアプリ側で確認する必要があります。 |
警告
この例のトークンを含めて、自分が所有していないすべての API について、トークンの検証や読み取りを行わないでください。 Microsoft サービスのトークンには、JWT として検証されない特殊な形式を使用できます。また、コンシューマー (Microsoft アカウント) ユーザーに対して暗号化される場合もあります。 トークンの読み取りは便利なデバッグおよび学習ツールですが、コード内でこれに対する依存関係を取得したり、自分で制御する API 用ではないトークンについての詳細を想定したりしないでください。
エラー応答
アプリ側でエラーを適切に処理できるよう、 redirect_uri
にはエラー応答も送信されます。
GET https://localhost/myapp/#
error=access_denied
&error_description=the+user+canceled+the+authentication
パラメーター | 説明 |
---|---|
error |
発生したエラーの種類を分類したりエラーに対処したりする際に使用するエラー コード文字列。 |
error_description |
認証エラーの根本的な原因を開発者が特定しやすいように記述した具体的なエラー メッセージ。 |
アクセス トークンをサイレントに取得する
これでユーザーをシングルページ アプリにサインインさせたので、Microsoft Graph などの Microsoft ID プラットフォームによってセキュリティ保護された Web API を呼び出すためのアクセス トークンをサイレントに取得できます。 このメソッドを使用すると、token
response_type を使用してトークンを既に取得している場合でも、ユーザーをリダイレクトさせて再度サインインさせることなく、その他のリソースのトークンを取得できます。
重要
暗黙のフローのこの部分は、既定でサード パーティの Cookie が 削除されるため、異なるブラウザーをまたいでアプリケーションを使用すると、そのアプリケーションでは機能しない可能性があります。 現在でも Incognito で使用されていない Chromium ベースのブラウザーでは機能しますが、開発者はフローのこの部分を使用することを再検討する必要があります。 サード パーティの Cookie をサポートしていないブラウザーでは、ログイン ページのセッション Cookie がブラウザーによって削除されるため、ユーザーがサインインしていないことを示すエラーが表示されます。
通常の OpenID Connect/OAuth フローでは、これは Microsoft ID プラットフォームの /token
エンドポイントに要求を発行することによって行います。 非表示の iframe でこの要求を実行し、他の Web API 用の新しいトークンを取得できます。
// Line breaks for legibility only
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444&response_type=token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
&response_mode=fragment
&state=12345
&nonce=678910
&prompt=none
&login_hint=myuser@mycompany.com
URL のクエリ パラメーターの詳細については、「サインイン要求を送信する」を参照してください。
ヒント
ご使用のアプリの登録から実際の client_id
と username
を使用して、次の要求をブラウザー タブにコピーして貼り付けてみてください。 これにより、サイレント トークン要求の動作を確認できます。
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={your-client-id}&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read&response_mode=fragment&state=12345&nonce=678910&prompt=none&login_hint={username}
これは、iframe 内で開くのではなく、ブラウザー バーに直接入力するため、サード パーティの Cookie がサポートされていないブラウザーでも機能します。
prompt=none
パラメーターに応じて、要求はすぐに成功または失敗し、アプリケーションに戻ります。 response_mode
パラメーターで指定された方法を使用して、指定された redirect_uri
でアプリに応答が送信されます。
成功応答
response_mode=fragment
を使用した場合の正常な応答は次のようになります。
GET https://localhost/myapp/#
access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
&token_type=Bearer
&expires_in=3599
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fdirectory.read
パラメーター | 説明 |
---|---|
access_token |
response_type に token が含まれる場合に含まれます。 この場合は、Microsoft Graph 用にアプリケーションが要求したアクセス トークンです。 アクセス トークンはデコードしないようにする必要があります。そうしないと、検証した場合に不透明な文字列として扱われます。 |
token_type |
これは常に Bearer です。 |
expires_in |
キャッシュ用にトークンが有効になっている秒数を示します。 |
scope |
アクセス トークンが有効な 1 つ以上のスコープを示します。 要求されたスコープをユーザーに適用できなかった場合 (サインインのために個人用アカウントが使用されているときに Microsoft Entra 専用スコープが要求された場合)、必ずしもすべてのスコープが含まれないことがあります。 |
id_token |
署名付き JSON Web トークン (JWT)。 response_type に id_token が含まれる場合に含まれます。 アプリは、このトークンのセグメントをデコードして、サインインしたユーザーに関する情報を要求することができます。 アプリはこの値をキャッシュして表示できますが、承認やセキュリティ境界のためにこの値を使用することはできません。 id_token の詳細については、id_token のリファレンスを参照してください。 注: openid スコープが要求された場合のみ提供されます。 |
state |
要求に state パラメーターが含まれている場合、同じ値が応答にも含まれることになります。 要求と応答に含まれる状態値が同一であることをアプリ側で確認する必要があります。 |
エラー応答
アプリ側で適切に処理できるように、 redirect_uri
にエラーの応答が送信される場合もあります。 prompt=none
の場合、次のエラーが発生します。
GET https://localhost/myapp/#
error=user_authentication_required
&error_description=the+request+could+not+be+completed+silently
パラメーター | 説明 |
---|---|
error |
発生したエラーの種類を分類したりエラーに対処したりする際に使用するエラー コード文字列。 |
error_description |
認証エラーの根本的な原因を開発者が特定しやすいように記述した具体的なエラー メッセージ。 |
Iframe 要求でこのエラーを受信した場合、ユーザーは対話形式でもう一度サインインして新しいトークンを取得する必要があります。 この場合は、アプリケーションに適した任意の方法で処理できます。
トークンを更新する
暗黙的な許可では、更新トークンは提供されません。 ID トークンとアクセス トークンはどちらも短時間で期限切れになるため、これらのトークンを定期的に更新するようにアプリを準備しておく必要があります。 どちらの種類のトークンを更新する場合も、ID プラットフォームの動作を制御するための prompt=none
パラメーターを使用して、この前で言及した非表示の iframe 要求を実行できます。 新しい ID トークンを受け取りたい場合は、response_type
と scope=openid
で id_token
を使うことに加えて、nonce
パラメーターも使用してください。
サード パーティの Cookie をサポートしていないブラウザーでは、ユーザーがサインインしていないことを示すエラーが発生します。
サインアウト要求を送信する
OpenID Connect end_session_endpoint
を使用すると、ユーザーのセッションを終了させ、Microsoft ID プラットフォームによって設定された Cookie をクリアする要求がアプリから Microsoft ID プラットフォームへ送信されます。 ユーザーが Web アプリケーションから完全にサインアウトするには、アプリがユーザーとのセッションを終了し (通常、トークン キャッシュをクリアするか Cookie を切断する)、ブラウザーを以下にリダイレクトする必要があります。
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/logout?post_logout_redirect_uri=https://localhost/myapp/
パラメーター | 型 | 内容 |
---|---|---|
tenant |
required | 要求パスの {tenant} の値を使用して、アプリケーションにサインインできるユーザーを制御します。 使用できる値は、common 、organizations 、consumers およびテナント識別子です。 詳細については、 プロトコルの基礎に関するページを参照してください。 |
post_logout_redirect_uri |
推奨 | サインアウト完了後にユーザーが戻る URL。 この値は、アプリケーションに登録されているリダイレクト URI のいずれかと一致する必要があります。 含まれていない場合、Microsoft ID プラットフォームにより汎用メッセージが表示されます。 |
関連項目
- MSAL JS のサンプルを見直して、コーディング作業を開始します。
- 暗黙的な許可の代わりとなる、新しいより優れた手段として承認コード フローを見直します。