ブラウザーに格納されている OAuth 2.0 アクセス トークンの "トークンリプレイ" に対する保護を強化するために、MSAL は Access Token Proof-of-Posession 認証スキームを提供します。
Access Token Proof-of-Possession( AT PoP) は、アクセス トークンを要求元のブラウザーおよびクライアント アプリケーションに暗号でバインドする認証スキームです。つまり、別のアプリケーションまたはデバイスから使用することはできません。
AT PoPがエンド ツー エンドで動作し、目的のセキュリティ アップグレードを提供するためには、アクセス トークンを発行する承認サービスと、アクセスを提供するリソース サーバーの両方がAT PoPをサポートする必要があることを理解しておくことが重要です。
ベアラー アクセス トークンとバインド (PoP) アクセス トークン
ベアラー アクセス トークン
MSAL v2 API によって返される標準的な 認証結果 には、 accessToken プロパティが含まれています。 既定の Bearer 認証スキームで使用する場合、 accessToken プロパティの値は、承認サーバーによって提供されるアクセス トークン シークレットです。 この成果物は MSAL によってキャッシュされ、リソース要求に、要求の Authorization ヘッダーのベアラー トークンとして追加する必要があります。
ベアラー アクセス トークンの使用例:
// Using the Bearer scheme (default), acquireTokenRedirect returns an AuthenticationResult object containing the Bearer access token secret
const { accessToken } = await myMSALObj.acquireTokenRedirect(popTokenRequest);
// The bearer token secret is appended to the Authorization header
const headers = new Headers();
const authHeader = `Bearer ${accessToken}`; // The Bearer label is used in this header
headers.append("Authorization", authHeader);
バインドされたアクセス トークン
A.K.A PoP Token または Signed HTTP Request。 MSAL トークン要求で POP 認可スキームが有効になっている場合でも、認可サーバーは引き続き、Bearer アクセス トークンのように見える JSON Web Token のアクセス トークン シークレットを提供し、それも MSAL によってキャッシュされます。 主な違いは、 POP スキームを使用する場合、そのアクセス トークン シークレットは非対称暗号化キーペアを介してユーザーのブラウザーにバインドされることです。
アクセス トークン シークレットは新しい JSON Web トークンにラップされます。このトークンは、 HMAC (ハッシュベースのメッセージ認証コード) ハッシュ アルゴリズムと、MSAL が生成、格納、管理するキーペアの秘密キーを使用して署名されます。 署名された JWT は、AuthorizationResult プロパティの下のaccessToken オブジェクトに追加され、呼び出された MSAL v2 API から返されます。
クライアント アプリケーションは、返された認証結果を受け取ると、認証結果からaccessToken値を抽出し、Authorization ラベルの代わりに PoP ラベルを使用して、PoP で保護されたリソース要求のBearer ヘッダーに追加できます。
注: 署名された JWT (署名済み HTTP 要求または SHR と呼ばれます) は、MSAL によってキャッシュされることはありません。 MSAL v2 API が呼び出されるたびに、MSAL はキャッシュから有効な生アクセス トークン シークレットを取得するか、承認サーバーから新しいアクセス トークンを要求します。 その後、MSAL は、そのアクセス トークンに署名し、認証結果で返します。
バインド (PoP) アクセス トークンの使用例:
// Using the POP scheme (default), acquireTokenRedirect returns an AuthenticationResult object containing the Signed HTTP Request (PoP Token)
const { accessToken } = await myMSALObj.acquireTokenRedirect(popTokenRequest);
// The SHR is appended to the Authorization header
const headers = new Headers();
const authHeader = `PoP ${accessToken}`; // The PoP label is used in this header
headers.append("Authorization", authHeader);
PoP トークン要求の作成
承認サービスとリソース サーバーがアクセス トークン バインドをサポートすることを確認したら、アクセス トークン PoP 固有の属性を含むトークン要求オブジェクトを構築することで、バインドされたアクセス トークンを取得するように MSAL 認証および承認要求オブジェクトを構成できます。 要求オブジェクトでは次の属性はすべて省略可能ですが、 所有証明を有効にするには authorizationScheme を手動で "pop" に設定する必要があります。
AT PoP リクエスト パラメーター
| 名前 | 説明 | 必須 |
|---|---|---|
authenticationScheme |
MSAL が Bearer または PoP トークンを取得する必要があるかどうかを示します。 既定値は Bearer です。 |
必須 |
resourceRequestMethod |
署名されたトークンを使用する要求の HTTP メソッドのすべて大文字の名前 (GET、 POST、 PUTなど) |
必須 |
resourceRequestUri |
アクセス トークンが発行されている保護されたリソースの URL | 必須 |
shrClaims |
SignedHTTPRequest に追加するカスタム クライアント要求を含む文字列化された JSON オブジェクト。 詳細については、 カスタム SHR 要求 のドキュメントを参照してください。 | オプション |
shrNonce |
Base64URL が文字列としてエンコードされた、サーバーによって生成された署名付きタイムスタンプ。 この nonce は、PoP トークンの事前生成を可能にするために、クロック スキュー攻撃とタイムトラベル攻撃を軽減するために使用されます。 詳細については、 SHR サーバー Nonce のドキュメントを参照してください。 | オプション |
注: このドキュメントでは、shrNonceにSignedHttpRequestを追加する方法を示しますが、サーバー nonce 取得パターンは範囲外です。 サーバーで生成されたノンスの取得方法の詳細については、SHR Server Nonce dcoumentationを参照してください。
トークン リダイレクト要求の取得の例
const popTokenRequest = {
scopes: ["User.Read"],
authenticationScheme: msal.AuthenticationScheme.POP,
resourceRequestMethod: "POST",
resourceRequestUri: "YOUR_RESOURCE_ENDPOINT",
shrClaims: "{\"shrClaim1\": \"claimValue\"}",
shrNonce: "NONCE_ACQUIRED_FROM_RESOURCE_SERVER"
}
要求が構成され、 POP が authenticationSchemeとして設定されたら、 acquireTokenRedirect MSAL v2 API に送信できます。
const response = await myMSALObj.acquireTokenRedirect(popTokenRequest);
// Once a Pop Token has been acquired, it can be added on the authorization header of a resource request
const headers = new Headers();
const authHeader = `${response.tokenType} ${response.accessToken}`;
headers.append("Authorization", authHeader);
const options = {
method: popTokenRequest.resourceRequestMethod,
headers: headers
};
// After the request has been built and the POP access token has bee appended, the request can be executed using an API like "fetch"
fetch(endpoint, options)
.then(response => response.json())
.then(response => callback(response, endpoint))
.catch(error => console.log(error));
});
トークンをサイレントに取得するリクエストの例
PoP アクセス トークンをサイレントモードで取得するには、対話型の acquireToken API と同じ変更がトークン要求構成に必要です。
const silentPopTokenRequest = {
scopes: ["User.Read"],
authenticationScheme: msal.AuthenticationScheme.POP, // Default is "BEARER"
resourceRequestMethod: "POST",
resourceRequestUri: "YOUR_RESOURCE_ENDPOINT",
shrClaims: "{\"shrClaim1\": \"claimValue\"}",
shrNonce: "NONCE_ACQUIRED_FROM_RESOURCE_SERVER"
}
// Try to acquire token silently
const { accessToken } = await myMSALObj.acquireTokenSilent(silentPopTokenRequest).catch(async (error) => {
console.log("Silent token acquisition failed.");
if (error instanceof msal.InteractionRequiredAuthError) {
// Fallback to interaction if silent call fails
console.log("Acquiring token using redirect");
myMSALObj.acquireTokenRedirect(silentPopTokenRequest);
} else {
console.error(error);
}
});
// Once a Pop Token has been acquired, it can be added on the authorization header of a resource request
const headers = new Headers();
const authHeader = `PoP ${accessToken}`;
headers.append("Authorization", authHeader);
const options = {
method: popTokenRequest.resourceRequestMethod,
headers: headers
};
// After the request has been built and the POP access token has bee appended, the request can be executed using an API like "fetch"
fetch(endpoint, options)
.then(response => response.json())
.then(response => callback(response, endpoint))
.catch(error => console.log(error));
});
PoP キー管理
所有証明認証スキームは、非対称暗号化キーペアに依存して、アクセス トークンをユーザーのブラウザーにバインドします。 MSAL Browser は、最初に承認サービスからアクセス トークンを要求するときにこのキーペアを生成し、 IndexedDB を使用して格納します。 この暗号化キーペアは、バインドされたアクセス トークンがサイレントで要求されるたびに、 SHR に署名するために使用されます。
バインドされたアクセス トークンを更新した場合、MSAL は期限切れのバインドされたアクセス トークンを要求したときに生成された暗号化キーペアを削除し、新しいアクセス トークンの新しい暗号化キーペアを生成し、キーストアに新しいキーペアを格納します。
高度な機能: アプリケーションで管理される暗号化キーペア
Warning
所有証明プロトコルに精通しており、独自の暗号化キーペアを生成するための特定の要件がある場合を除き、この機能を使用することはお勧めしません。 ほとんどの場合、このドキュメントの残りの部分で説明されているように PoP の使用をお勧めします。
独自の暗号化キーペアを生成することを選択した場合、この機能により、アプリケーションは popKid を要求パラメーターとして指定できます。 MSAL JS は、トークン発行者がトークンに cnf を埋め込むが、 発行されたトークンを符号なしで返すようにします。 対象のリソースに転送される前にアクセストークンに署名するのは、アプリケーションの責任です。
また、この動作を利用する場合は、を除く残りの authenticationSchemeが設定されていないことを確認してください。
アクセス トークンが非同期的に保存される理由
たとえば、ほとんどの MSAL 資格情報とキャッシュ 項目 ( ID Tokens など) は、同期的に格納および削除できます。 これは、これらのキャッシュ項目は localStorage または sessionStorage (同期的に操作できます) に格納され、非同期アクセス制限を持つ他の格納された項目には依存関係がないためです。
他のキャッシュ項目とは異なり、 Access Tokens は非同期的にキャッシュに保存されます。 その理由は、アクセス トークンが暗号化キーペアにバインドされ、 IndexedDBに格納されている場合、アクセス トークンを置き換える場合にも、暗号化キーペアを置き換える必要があるということです。
IndexedDBへのキーの削除と書き込みが非同期操作であることを考えると、アクセス トークンを保存するプロセスは、必然的に拡張機能によって非同期になります。