Microsoft ID プラットフォームと OAuth 2.0 クライアント資格情報フロー
OAuth 2.0 クライアント資格情報付与フローでは、Web サービス (機密クライアント) が、別の Web サービスを呼び出すときにユーザーを偽装するのではなく、独自の資格情報を使用して認証を行うことができます。
クライアント資格情報フローでは、アクセス許可は管理者によってアプリケーション自体に直接付与されます。 アプリがリソースにトークンを提示すると、認証に関係するユーザーがいないため、リソースはアプリ自体がアクションを実行する承認を持っていることを強制します。 この記事では、次の両方の手順について説明します。
この記事では、アプリケーション内のプロトコルに対して直接プログラムする方法について説明します。 可能な場合は、代わりにサポートされている Microsoft 認証ライブラリ (MSAL) を使用してトークンを取得し、セキュリティで保護された Web API呼び出 client_id
および client_secret
を使ってアクセス トークンを取得することができます。更新トークンを取得するためには client_secret
も必要ですが、ここではアクセス トークンの取得に使用します。
より高いレベルの保証のために、Microsoft ID プラットフォームでは、呼び出し元サービスは、共有シークレットではなく、証明書 またはフェデレーション資格情報を使用して認証することもできます。 アプリケーション独自の資格情報が使用されているため、これらの資格情報は安全に保管する必要があります。 、その資格情報をソース コードに公開したり、Web ページに埋め込んだり、広く分散されたネイティブ アプリケーションで使用したり しないでください。
プロトコル図
クライアント資格情報フロー全体は、次の図のようになります。 各手順については、この記事の後半で説明します。
を示す図
直接承認を取得する
アプリは、通常、次の 2 つの方法のいずれかでリソースにアクセスするための直接承認を受け取ります。
これら 2 つの方法は Microsoft Entra ID で最も一般的であり、クライアント資格情報フローを実行するクライアントとリソースに推奨されます。 リソースは、他の方法でクライアントを承認することもできます。 各リソース サーバーは、そのアプリケーションに最も適した方法を選択できます。
アクセス制御リスト
リソース プロバイダーは、特定のレベルのアクセス権を認識して付与するアプリケーション (クライアント) ID の一覧に基づいて、承認チェックを適用できます。 リソースは、Microsoft ID プラットフォームからトークンを受け取ると、トークンをデコードし、appid
および iss
要求からクライアントのアプリケーション ID を抽出できます。 次に、アプリケーションが保持するアクセス制御リスト (ACL) とアプリケーションを比較します。 ACL の細分性と方法は、リソースによって大きく異なる場合があります。
一般的なユース ケースは、ACL を使用して Web アプリケーションまたは Web API のテストを実行することです。 Web API は、特定のクライアントに完全なアクセス許可のサブセットのみを付与できます。 API でエンド ツー エンドのテストを実行するには、Microsoft ID プラットフォームからトークンを取得して API に送信するテスト クライアントを作成します。 次に、API は、API の機能全体へのフル アクセスについて、テスト クライアントのアプリケーション ID の ACL をチェックします。 この種類の ACL を使用する場合は、呼び出し元の appid
値だけでなく、トークンの iss
値が信頼されていることを確認してください。
この種類の承認は、個人の Microsoft アカウントを持つコンシューマー ユーザーが所有するデータにアクセスする必要があるデーモンとサービス アカウントに共通です。 組織が所有するデータの場合は、アプリケーションのアクセス許可を通じて必要な承認を取得することをお勧めします。
roles
要求なしでトークンを制御する
この ACL ベースの承認パターンを有効にするために、Microsoft Entra ID では、アプリケーションが別のアプリケーションのトークンを取得することを承認する必要はありません。 したがって、アプリ専用トークンは、roles
要求なしで発行できます。 API を公開するアプリケーションでは、トークンを受け入れるためにアクセス許可チェックを実装する必要があります。
アプリケーションに対するロールのないアプリケーション専用のアクセス トークンをアプリケーションで取得できないようにするには、割り当て要件がアプリに対して有効になるようにします。 これにより、ロールが割り当てされていないユーザーとアプリケーションは、このアプリケーションのトークンを取得できなくなります。
アプリケーションのアクセス許可
ACL を使用する代わりに、API を使用して一連の アプリケーションのアクセス許可公開できます。 これらは、組織の管理者によってアプリケーションに付与され、その組織とその従業員が所有するデータへのアクセスにのみ使用できます。 たとえば、Microsoft Graph では、次の操作を行うために、いくつかのアプリケーションアクセス許可が公開されています。
- すべてのメールボックスでメールを読み取る
- すべてのメールボックスのメールの読み取りと書き込み
- 任意のユーザーとしてメールを送信する
- ディレクトリ データの読み取り
(Microsoft Graph ではなく) 独自の API でアプリ ロール (アプリケーションのアクセス許可) を使用するには、まず、Microsoft Entra 管理センターの API のアプリ登録で アプリ ロールを公開
(ユーザーではなく) アプリケーションとして認証する場合、委任されたアクセス許可
アプリケーションのアクセス許可の詳細については、「アクセス許可と同意」を参照してください。
推奨: アプリロールを割り当てるために管理者をアプリにサインインさせる
通常、アプリケーションのアクセス許可を使用するアプリケーションをビルドする場合、アプリには、管理者がアプリのアクセス許可を承認するページまたはビューが必要です。 このページは、アプリケーションのサインイン フローやアプリの設定の一部、または専用の "接続" フローにすることができます。 多くの場合、ユーザーが職場または学校の Microsoft アカウントでサインインした後にのみ、この 接続 ビューをアプリに表示することは理にかなっています。
ユーザーをアプリにサインインさせる場合は、ユーザーにアプリケーションのアクセス許可の承認を求める前に、ユーザーが属している組織を特定できます。 厳密には必要ではありませんが、ユーザーにとってより直感的なエクスペリエンスを作成するのに役立ちます。 ユーザーにサインインするには、Microsoft ID プラットフォーム プロトコルのチュートリアル
ディレクトリ管理者にアクセス許可を要求する
組織の管理者にアクセス許可を要求する準備ができたら、管理者の同意エンドポイント
// Line breaks are for legibility only.
GET https://login.microsoftonline.com/{tenant}/adminconsent?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&state=12345
&redirect_uri=http://localhost/myapp/permissions
ヒント: ブラウザーに次の要求を貼り付けてみます。
https://login.microsoftonline.com/common/adminconsent?client_id=00001111-aaaa-2222-bbbb-3333cccc4444&state=12345&redirect_uri=http://localhost/myapp/permissions
パラメーター | 条件 | 説明 |
---|---|---|
tenant |
必須 | アクセス許可を要求するディレクトリ テナント。 これは GUID またはフレンドリ名の形式で指定できます。 ユーザーが属しているテナントがわからない場合に、ユーザーが任意のテナントでサインインできるようにする場合は、common を使用します。 |
client_id |
必須 | [Microsoft Entra 管理センター - アプリの登録] エクスペリエンスからアプリに割り当てられたアプリケーション (クライアント) ID。 |
redirect_uri |
必須 | アプリが処理するために応答を送信するリダイレクト URI。 ポータルに登録したリダイレクト URI のいずれかと完全に一致する必要があります。ただし、URL エンコードする必要があり、追加のパス セグメントを含めることができる点が異なります。 |
state |
推奨 | 要求に含まれ、トークン応答でも返される値。 任意のコンテンツの文字列を指定できます。 状態は、認証要求が発生する前のユーザーの状態 (ページやビューなど) に関する情報をエンコードするために使用されます。 |
この時点で、Microsoft Entra ID は、テナント管理者のみがサインインして要求を完了できるように強制します。 管理者は、アプリ登録ポータルでアプリに対して要求したすべての直接アプリケーションのアクセス許可を承認するように求められます。
成功した応答
管理者がアプリケーションのアクセス許可を承認した場合、成功した応答は次のようになります。
GET http://localhost/myapp/permissions?tenant=aaaabbbb-0000-cccc-1111-dddd2222eeee&state=state=12345&admin_consent=True
パラメーター | 説明 |
---|---|
tenant |
アプリケーションに要求されたアクセス許可を GUID 形式で付与したディレクトリ テナント。 |
state |
トークン応答にも返される要求に含まれる値。 任意のコンテンツの文字列を指定できます。 状態は、認証要求が発生する前のユーザーの状態 (ページやビューなど) に関する情報をエンコードするために使用されます。 |
admin_consent |
を Trueに設定します。 |
エラー応答
管理者がアプリケーションのアクセス許可を承認しない場合、失敗した応答は次のようになります。
GET http://localhost/myapp/permissions?error=permission_denied&error_description=The+admin+canceled+the+request
パラメーター | 説明 |
---|---|
error |
エラーの種類を分類するために使用でき、エラーに対応するために使用できるエラー コード文字列。 |
error_description |
エラーの根本原因を特定するのに役立つ特定のエラー メッセージ。 |
アプリ プロビジョニング エンドポイントから正常な応答を受け取った後、アプリは要求した直接のアプリケーションアクセス許可を取得しました。 これで、必要なリソースのトークンを要求できます。
トークンを取得する
アプリケーションに必要な承認を取得したら、API のアクセス トークンの取得に進みます。 クライアント資格情報の付与を使用してトークンを取得するには、/token
Microsoft ID プラットフォームに POST 要求を送信します。 いくつかの異なるケースがあります。
最初のケース: 共有シークレットを使用してトークン要求にアクセスする
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 //Line breaks for clarity
Host: login.microsoftonline.com:443
Content-Type: application/x-www-form-urlencoded
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=qWgdYAmab0YSkuL1qKv5bPX
&grant_type=client_credentials
# Replace {tenant} with your tenant!
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=00001111-aaaa-2222-bbbb-3333cccc4444&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=A1bC2dE3f...&grant_type=client_credentials' 'https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token'
パラメーター | 条件 | 説明 |
---|---|---|
tenant |
必須 | アプリケーションが操作を計画しているディレクトリ テナント (GUID またはドメイン名形式)。 |
client_id |
必須 | アプリに割り当てられているアプリケーション ID。 この情報は、アプリを登録したポータルで確認できます。 |
scope |
必須 | この要求で scope パラメーターに渡される値は、必要なリソースのリソース識別子 (アプリケーション ID URI) で、サフィックスは .default である必要があります。 含まれるすべてのスコープは、1 つのリソースに対するスコープである必要があります。 複数のリソースのスコープを含めると、エラーが発生します。 Microsoft Graph の例では、値は https://graph.microsoft.com/.default です。 この値は、アプリ用に構成したすべての直接アプリケーションアクセス許可のうち、エンドポイントが使用するリソースに関連付けられているトークンを発行する必要があることを Microsoft ID プラットフォームに通知します。 /.default スコープの詳細については、同意に関するドキュメントを参照してください。 |
client_secret |
必須 | アプリ登録ポータルでアプリ用に生成したクライアント シークレット。 クライアント シークレットは、送信前に URL でエンコードする必要があります。 代わりに Authorization ヘッダーに資格情報を提供する基本的な認証パターン RFC 6749 もサポートされています。 |
grant_type |
必須 | client_credentials に設定する必要があります。 |
2 番目のケース: 証明書を使用したアクセス トークン要求
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 // Line breaks for clarity
Host: login.microsoftonline.com:443
Content-Type: application/x-www-form-urlencoded
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_id=11112222-bbbb-3333-cccc-4444dddd5555
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNScUtqRlBuZDdSRnd2d1pJMCJ9.eyJ{a lot of characters here}M8U3bSUKKJDEg
&grant_type=client_credentials
パラメーター | 条件 | 説明 |
---|---|---|
tenant |
必須 | アプリケーションが操作を計画しているディレクトリ テナント (GUID またはドメイン名形式)。 |
client_id |
必須 | アプリに割り当てられているアプリケーション (クライアント) ID。 |
scope |
必須 | この要求で scope パラメーターに渡される値は、必要なリソースのリソース識別子 (アプリケーション ID URI) で、サフィックスは .default である必要があります。 含まれるすべてのスコープは、1 つのリソースに対するスコープである必要があります。 複数のリソースのスコープを含めると、エラーが発生します。 Microsoft Graph の例では、値は https://graph.microsoft.com/.default です。 この値は、アプリ用に構成したすべての直接アプリケーションアクセス許可のうち、エンドポイントが使用するリソースに関連付けられているトークンを発行する必要があることを Microsoft ID プラットフォームに通知します。 /.default スコープの詳細については、同意に関するドキュメントを参照してください。 |
client_assertion_type |
必須 | 値は urn:ietf:params:oauth:client-assertion-type:jwt-bearer に設定する必要があります。 |
client_assertion |
必須 | 作成する必要があるアサーション (JSON Web トークン) です。このアサーションは、アプリケーションの資格情報として登録した証明書で署名する必要があります。 証明書の登録方法とアサーションの形式の詳細については、証明書資格情報に関する記事を参照してください。 |
grant_type |
必須 | client_credentials に設定する必要があります。 |
証明書ベースの要求のパラメーターは、共有シークレット ベースの要求とは 1 つの方法でのみ異なります。client_secret
パラメーターは、client_assertion_type
パラメーターと client_assertion
パラメーターに置き換えられます。
3 番目のケース: フェデレーション資格情報を使用したアクセス トークン要求
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 // Line breaks for clarity
Host: login.microsoftonline.com:443
Content-Type: application/x-www-form-urlencoded
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_id=11112222-bbbb-3333-cccc-4444dddd5555&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNScUtqRlBuZDdSRnd2d1pJMCJ9.eyJ{a lot of characters here}M8U3bSUKKJDEg
&grant_type=client_credentials
パラメーター | 条件 | 説明 |
---|---|---|
client_assertion |
必須 | アプリケーションが、Kubernetes などの Microsoft ID プラットフォームの外部にある別の ID プロバイダーから取得するアサーション (JWT または JSON Web トークン)。 この JWT の詳細は、フェデレーション ID 資格情報としてアプリケーションに登録する必要があります。 ワークロード ID フェデレーション について読むことで、他の ID プロバイダーから生成されたアサーションをどのように設定して使用するかを学びましょう。 |
要求内のすべてが証明書ベースのフローと同じですが、client_assertion
のソースを除く重要な例外があります。 このフローでは、アプリケーションは JWT アサーション自体を作成しません。 代わりに、アプリは別の ID プロバイダーによって作成された JWT を使用します。 これは ワークロード ID フェデレーションと呼ばれ、別の ID プラットフォーム内のアプリ ID を使用して Microsoft ID プラットフォーム内のトークンを取得します。 これは、Azure の外部でコンピューティングをホストしているが、Microsoft ID プラットフォームによって保護されている API にアクセスするなど、クラウド間のシナリオに最適です。 他の ID プロバイダーによって作成される JWT の必要な形式については、アサーション形式を参照してください。
成功した応答
任意のメソッドからの正常な応答は次のようになります。
{
"token_type": "Bearer",
"expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBP..."
}
パラメーター | 説明 |
---|---|
access_token |
要求されたアクセス トークン。 アプリは、このトークンを使用して、セキュリティで保護されたリソース (Web API など) に対する認証を行うことができます。 |
token_type |
トークンの種類の値を示します。 Microsoft ID プラットフォームがサポートする唯一の種類は、bearer です。 |
expires_in |
アクセス トークンが有効な時間 (秒単位)。 |
警告
この例のトークンをコードに含め、所有していない API のトークンの検証や読み取りを試みないでください。 Microsoft サービスのトークンでは、JWT として検証されない特殊な形式を使用できます。また、コンシューマー (Microsoft アカウント) ユーザー向けに暗号化することもできます。 トークンの読み取りは便利なデバッグおよび学習ツールですが、コード内でこれに依存したり、制御する API 用ではないトークンに関する詳細を想定したりしないでください。
エラー応答
エラー応答 (400 Bad Request) は次のようになります。
{
"error": "invalid_scope",
"error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://foo.microsoft.com/.default is not valid.\r\nTrace ID: 0000aaaa-11bb-cccc-dd22-eeeeee333333\r\nCorrelation ID: aaaa0000-bb11-2222-33cc-444444dddddd\r\nTimestamp: 2016-01-09 02:02:12Z",
"error_codes": [
70011
],
"timestamp": "YYYY-MM-DD HH:MM:SSZ",
"trace_id": "0000aaaa-11bb-cccc-dd22-eeeeee333333",
"correlation_id": "aaaa0000-bb11-2222-33cc-444444dddddd"
}
パラメーター | 説明 |
---|---|
error |
発生するエラーの種類を分類し、エラーに対応するために使用できるエラー コード文字列。 |
error_description |
認証エラーの根本原因を特定するのに役立つ可能性のある特定のエラー メッセージ。 |
error_codes |
診断に役立つ STS 固有のエラー コードの一覧。 |
timestamp |
エラーが発生した時刻。 |
trace_id |
診断に役立つ、要求の一意の識別子。 |
correlation_id |
コンポーネント間での診断に役立つ、要求の一意の識別子。 |
トークンを使用する
トークンを取得したので、トークンを使用してリソースに要求を行います。 トークンが期限切れになったら、/token
エンドポイントに要求を繰り返して、新しいアクセス トークンを取得します。
GET /v1.0/users HTTP/1.1
Host: graph.microsoft.com:443
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbG...
ターミナルで次のコマンドを試し、トークンを実際のトークンに置き換えてください。
curl -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbG..." 'https://graph.microsoft.com/v1.0/users'
コード サンプルとその他のドキュメント
Microsoft 認証ライブラリのクライアントの資格情報の概要に関するドキュメントを参照してください。
サンプル | プラットホーム | 説明 |
---|---|---|
active-directory-dotnetcore-daemon-v2 | .NET 6.0 以降 | ユーザーの代わりに、アプリケーションの ID を使用して Microsoft Graph に対してクエリを実行するテナントのユーザーを表示する ASP.NET Core アプリケーション。 このサンプルでは、認証に証明書を使用するバリエーションも示しています。 |
active-directory-dotnet-daemon-v2 | ASP.NET MVC | ユーザーの代わりに、アプリケーションの ID を使用して Microsoft Graph のデータを同期する Web アプリケーション。 |
ms-identity-javascript-nodejs-console | Node.js コンソール | アプリケーションの ID を使用して Microsoft Graph にクエリを実行してテナントのユーザーを表示する Node.js アプリケーション |