Microsoft Authentication Library (MSAL) を使用してトークンを取得し、キャッシュする

アクセス トークンにより、クライアントは Azure によって保護された Web API を安全に呼び出すことができます。 Microsoft Authentication Library (MSAL) を使用してトークンを取得するには、いくつかの方法があります。 Web ブラウザーを使用したユーザー操作が必要なものもあれば、ユーザーの操作を必要としないものもあります。 通常、トークンを取得するために使われる方法は、アプリケーションがパブリック クライアント アプリケーション (デスクトップまたはモバイル) か、機密クライアント アプリケーション (Web アプリ、Web API、またはデーモン アプリ) かによって異なります。

MSAL では、トークンは取得された後でキャッシュされます。 アプリケーション コードでは、他の手段でトークンの取得を試行する前に、まず、キャッシュからのトークンの自動的な取得を試みる必要があります。

また、キャッシュからアカウントを削除することで、トークン キャッシュをクリアすることもできます。 ただし、これによってブラウザーにあるセッション Cookie が削除されることはありません。

トークンを取得するときのスコープ

スコープは、クライアント アプリケーションがアクセスを要求できる、Web API によって公開されているアクセス許可です。 クライアント アプリケーションでは、Web API にアクセスするためのトークンを取得するために認証要求を行うとき、これらのスコープに対するユーザーの同意を要求します。 MSAL を使うと、Microsoft ID プラットフォーム API にアクセスするためのトークンを取得できます。 v2.0 プロトコルでは、リソースではなくスコープが要求で使用されます。 受け付けるトークンのバージョンに関する Web API の構成に基づいて、v2.0 エンドポイントから MSAL にアクセス トークンが返されます。

いくつかの MSAL のトークン取得方法には、scopes パラメーターが必要です。 scopes パラメーターは、要求された必要とするアクセス許可とリソースを宣言する文字列のリストです。 よく知られたスコープとしては、Microsoft Graph アクセス許可があります。

Web API のスコープを要求する

アプリケーションでリソース API に対する特定のアクセス許可を備えたアクセス トークンを要求する必要がある場合、API のアプリ ID URI を含むスコープを、<app ID URI>/<scope> 形式で渡します。

さまざまなリソースのスコープ値の例を次に示します。

  • Microsoft Graph API: https://graph.microsoft.com/User.Read
  • カスタム Web API: api://11111111-1111-1111-1111-111111111111/api.read

スコープ値の形式は、アクセス トークンを受け取るリソース (API) と、それが受け入れる aud 要求の値によって異なります。

Microsoft Graph の場合のみ、user.read スコープは https://graph.microsoft.com/User.Read にマップされ、両方のスコープ形式を同じ意味で使用できます。

Azure Resource Manager API (https://management.core.windows.net/) などの特定の Web API では、アクセス トークンの audience クレーム (aud) に末尾のスラッシュ (/) が必要です。 この場合は、二重スラッシュ (//) を含めて、スコープを https://management.core.windows.net//user_impersonation として渡します。

その他の API では、スコープ値にスキームやホストが含まれないことが必要になる場合があり、アプリ ID (GUID) とスコープ名のみを想定する場合もあります。次に例を示します。

11111111-1111-1111-1111-111111111111/api.read

ヒント

ダウンストリーム リソースが制御下にない場合、アクセス トークンをリソースに渡すときに 401 またはその他のエラーが発生した場合は、異なるスコープ値の形式 (たとえば、スキームとホストを含めたり省略したりする) を試すことが必要な場合もあります。

アプリケーションによって提供される機能やその要件が変更されると、スコープ パラメーターを使用して、必要に応じて追加のアクセス許可を要求できます。 このような動的スコープを使用すると、ユーザーはスコープに対する増分の同意を行うことができ ます。

たとえば、ユーザーをサインインさせますが、最初はすべてのリソースへのアクセスを拒否します。 その後、トークン取得メソッドで予定表のスコープを要求して、そうすることへのユーザーの同意を取得することにより、ユーザーの予定表を表示する機能を提供できます。 たとえば、https://graph.microsoft.com/User.Readhttps://graph.microsoft.com/Calendar.Read のスコープを要求して行います。

(キャッシュからの) トークンの自動的な取得

MSAL は、1 つのトークン キャッシュ (または、機密クライアント アプリケーションの場合は 2 つのキャッシュ) を保持しており、取得した後のトークンをキャッシュします。 多くの場合、トークンを自動的に取得しようとすると、キャッシュ内のトークンに基づいて、より多くのスコープを備える別のトークンが取得されます。 また、期限切れが近いトークンを更新することもできます (トークン キャッシュには更新トークンも含まれるため)。

アプリケーションのソース コードでは、まず、キャッシュからトークンを自動的に取得することを試みる必要があります。 メソッドの呼び出しで "UI が必要" エラーまたは例外が返される場合、他の手段でトークンの取得を試みます。

トークンの自動取得を試行すべきではないフローが 2 つあります。

  • クライアント資格情報フローでは、ユーザー トークン キャッシュは使用されず、アプリケーション トークン キャッシュが使用されます。 この方法では、セキュリティ トークン サービス (STS) に要求を送信する前に、このアプリケーション トークン キャッシュの確認が行われます。
  • Web アプリの承認コード フローでは、ユーザーをサインインさせることでアプリケーションが取得したコードを引き換えて、より多くのスコープに同意させます。 (アカウントでなく) コードがパラメーターとして渡されるため、メソッドはコードを引き換える前にキャッシュを参照することができません。そのため、サービスの呼び出しを起動します。

OpenID Connect 認可コード フローが使われる Web アプリケーションの場合、コントローラーで推奨されるパターンは次のとおりです。

  • カスタマイズされたシリアル化を使用してトークン キャッシュで機密クライアント アプリケーションをインスタンス化します。
  • 承認コード フローを使用してトークンを取得します

トークンの取得

トークンを取得する方法は、アプリケーションがパブリック クライアントか機密クライアントかによって決まります。

パブリック クライアント アプリケーション

パブリック クライアント アプリケーション (デスクトップとモバイル) では、以下のことができます。

  • UI またはポップアップ ウィンドウを使用してユーザーをサインインさせ、対話形式でトークンを取得します。
  • ドメインまたは Azure に参加済みの Windows コンピューターでデスクトップ アプリケーションが実行されている場合、統合 Windows 認証 (IWA および Kerberos) を使用して、サインインしたユーザーのトークンを、確認を表示せずに取得します。
  • .NET Framework デスクトップ クライアント アプリケーションで、ユーザー名とパスワードを使用してトークンを取得します (推奨されません)。 機密クライアント アプリケーションでは、ユーザー名とパスワードを使わないでください。
  • Web ブラウザーがないデバイスで実行されているアプリケーションでは、デバイス コード フローを使用してトークンを取得します。 ユーザーは URL とコードを提供された後、別のデバイスの Web ブラウザーに移動し、コードを入力してサインインします。 その後、Microsoft Entra ID はブラウザーのないデバイスにトークンを送り返します。

機密クライアント アプリケーション

機密クライアント アプリケーション (Web アプリ、Web API、または Windows サービスなどのデーモン アプリ) の場合は、以下のことができます。

  • クライアント資格情報フローを使用して、ユーザーではなくアプリケーション自体に対するトークンを取得します。 この手法は、同期ツールに対して、または特定のユーザーではなくユーザー一般を処理するツールに対して、使用できます。
  • ユーザーに代わって API を呼び出す Web API に対しては、On-Behalf-Of (OBO) フローを使用します。 ユーザー アサーションに基づいてトークンを取得するため、アプリケーションはクライアントの資格情報で識別されます (たとえば、SAML または JWT トークン)。 このフローは、サービス間呼び出しで特定のユーザーのリソースにアクセスする必要があるアプリケーションによって使用されます。 トークンは、ユーザー単位ではなくセッション単位でキャッシュする必要があります。
  • Web アプリでは、ユーザーが承認要求 URL でサインインした後、承認コード フローを使用してトークンを取得します。 OpenID Connect アプリケーションでは、通常、このメカニズム (ユーザーは OpenID Connect を使用してサインイン可能) を使用してから、ユーザーに代わって Web API にアクセスします。 トークンは、ユーザー単位またはセッション単位でキャッシュできます。 ユーザー単位でトークンをキャッシュする場合は、Microsoft Entra ID が条件付きアクセス ポリシーの状態を頻繁に確認できるように、セッションの有効期間を制限することをお勧めします。

認証の結果

クライアントがアクセス トークンを要求すると、Microsoft Entra ID はアクセス トークンに関するメタデータを含む認証結果も返します。 この情報には、アクセス トークンの有効期限や、それが有効なスコープが含まれます。 このデータを使用すると、アプリはアクセス トークン自体を解析しなくても、そのアクセス トークンのインテリジェントなキャッシュを実行できます。 認証結果では以下が公開されます。

  • Web API がリソースにアクセスするためのアクセス トークン。 この文字列は、通常は Base64 でエンコードされた JWT ですが、クライアントがアクセス トークン内を参照することはありません。 この形式が変わらないことは保証されておらず、リソース用に暗号化できます。 クライアント上のアクセス トークンのコンテンツに応じてコードを記述している人は、エラーとクライアント ロジックの中断を起こす最も一般的な原因の 1 つです。
  • ユーザーの ID トークン (JWT)。
  • トークンの有効期限。トークンの有効期限が切れる日付と時刻を示します。
  • テナント ID には、ユーザーが見つかったテナントが含まれています。 ゲスト ユーザー (Microsoft Entra B2B のシナリオ) の場合、テナント ID は一意のテナントではなく、ゲスト テナントです。 トークンがユーザーの名前で提供されると、認証結果にはこのユーザーに関する情報も含まれます。 (アプリケーションの) ユーザーなしでトークンが要求される機密クライアント フローの場合、このユーザー情報は null です。
  • トークンが発行されたスコープ。
  • ユーザーの一意の ID。

(上級) バックグラウンドのアプリやサービスで、キャッシュされたユーザーのトークンにアクセスする

不在のユーザーに代わって操作を続けられるよう、アクセス トークン キャッシュの使用をバックグラウンドのアプリ、API、サービスに許可するため、MSAL のトークン キャッシュ実装を利用できます。 これは特に、ユーザーがフロントエンド Web アプリを終了した後、バックグラウンドのアプリやサービスがユーザーの代わりに作業を続けなければならない場合に便利です。

現在、ほとんどのバックグラウンド プロセスにおいて、ユーザーの不在時にユーザーのデータを使用して認証または再認証しなければならないとき、アプリケーションのアクセス許可が使用されます。 アプリケーションのアクセス許可は多くの場合、特権の昇格を必要とする管理者の同意を必要とするため、不要な衝突が発生します。その理由は、開発者のアプリに対してユーザーが最初に同意した以上のアクセス権を取得することを開発者が意図しなかったことにあります。

GitHub にあるこのコード サンプルからは、バックグラウンド アプリから MSAL のトークン キャッシュにアクセスすることでこの不要な衝突を回避する方法を確認できます。

バックグラウンドのアプリ、API、サービスからログイン ユーザーのトークン キャッシュにアクセスする

関連項目

MSAL でサポートされるプラットフォームの中には、そのプラットフォームのライブラリのドキュメントに追加のトークン キャッシュ関連情報が含まれているものがあります。 例: