共用方式為


宣告挑戰、宣告要求和用戶端功能

宣告挑戰是從 API 傳送的回應,指出用戶端應用程式傳送的存取權杖沒有足夠宣告。 這可能是因為權杖無法滿足對該 API 設定的條件式存取原則,或因為存取權杖已撤銷。

用戶端應用程式會提出宣告要求,以將使用者重新導向回識別提供者,並利用宣告擷取新權杖,藉此滿足不符合的其他需求。

使用增強式安全性功能的應用程式 (例如持續存取評估 (CAE)條件式存取驗證內容) 必須做好準備,才能處理宣告的挑戰。

當您的應用程式在對服務的呼叫中宣告其用戶端功能時,您的應用程式會收到來自熱門服務 (例如 Microsoft Graph) 的宣告挑戰。

宣告挑戰標頭格式

宣告挑戰是一個 www-authenticate 指示詞,當存在的存取權杖未獲授權且由 API 傳回標頭,而且需要具有正確功能的新存取權杖時。 宣告挑戰包含多個部分:回應的 HTTP 狀態碼和 www-authenticate 標頭,其本身具有多個部分,而且必須包含宣告指示詞。

以下是範例:

HTTP 401; Unauthorized

www-authenticate =Bearer realm="", authorization_uri="https://login.microsoftonline.com/common/oauth2/authorize", error="insufficient_claims", claims="eyJhY2Nlc3NfdG9rZW4iOnsiYWNycyI6eyJlc3NlbnRpYWwiOnRydWUsInZhbHVlIjoiY3AxIn19fQ=="

HTTP 狀態碼:必須是 401 未經授權

www-驗證回應標頭包含:

參數 必要條件/選擇性 描述
Authentication type 必要 必須是持有人
Realm 選用 正在存取的租用戶識別碼或租用戶網域名稱 (例如 microsoft.com)。 在驗證通過通用端點的情況下,必須是空字串。
authorization_uri 必要 authorize 端點的 URI,可在必要時執行互動式驗證。 如果是在領域中指定,則租用戶資訊必須包含在 authorization_uri 中。 如果 realm 是空字串,則 authorization_uri 必須針對通用端點
error 必要 若應產生宣告挑戰,則必須是 "insufficient_claims"。
claims 當錯誤為 "insufficient_claims" 時,則為必要項。 以引號括住的字串,其中包含 base 64 編碼的宣告要求。 宣告要求應要求 JSON 物件最上層 "access_token" 的宣告。 其值 (要求的宣告) 將會相依於內容,並于本文件稍後指定。 基於大小考慮,信賴憑證者應用程式應該在 base 64 編碼之前縮短 JSON。 上述範例的原始 JSON 為 {"access_token":{"acrs":{"essential":true,"value":"cp1"}}}

401 回應可能包含一個以上的 www-authenticate 標頭。 上表中的所有欄位都必須包含在相同的 www-authenticate 標頭中。 包含宣告挑戰的 www-authenticate 標頭包含其他欄位。 標頭中的欄位未排序。 根據 RFC 7235,每個參數名稱都必須在每個驗證配置挑戰中只出現一次。

宣告要求

當應用程式收到宣告挑戰時,會指出先前的存取權杖不再視為有效。 在此案例中,應用程式應從任何本機快取或使用者工作階段清除權杖。 然後,其應將已登入的使用者重新導向回 Microsoft Entra ID,藉此使用 OAuth 2.0 授權碼流程搭配宣告參數來擷取新的權杖,以滿足不符合的其他需求。

以下是範例:

GET https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/oauth2/v2.0/authorize
?client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&redirect_uri=https%3A%2F%contoso.com%3A44321%2Fsignin-oidc
&response_type=code
&scope=openid%20profile%20offline_access%20user.read%20Sites.Read.All
&response_mode=form_post
&login_hint=kalyan%ccontoso.onmicrosoft.com
&domain_hint=organizations
&claims=%7B%22access_token%22%3A%7B%22acrs%22%3A%7B%22essential%22%3Atrue%2C%22value%22%3A%22c1%22%7D%7D%7D

宣告挑戰應在 Microsoft Entra /authorize 端點的所有呼叫中傳遞,直到成功擷取權杖為止。 擷取權杖之後,就不再需要了。

若要填入宣告參數,開發人員必須:

  1. 解碼先前收到的 base64 字串。
  2. 將字串進行 URL 編碼,並再次新增至宣告參數。

完成此流程後,應用程式會收到具有其他宣告的存取權杖,以證明使用者滿足所需條件。

用戶端功能

用戶端功能可協助資源提供者 (例如 Web API) 偵測呼叫的用戶端應用程式是否了解宣告挑戰,然後可據以自訂回應。 如果並非所有 API 用戶端都能處理宣告挑戰,且某些較舊版本仍預期不同的回應,則這項功能可能會很有幫助。

某些熱門的應用程式 (例如 Microsoft Graph) 只會在呼叫用戶端應用程式宣告其能夠使用用戶端功能來處理時,才會傳送宣告挑戰。

為了避免額外的流量或對使用者體驗造成影響,Microsoft Entra ID 不會假設您的應用程式可以處理宣告挑戰,除非您明確選擇加入。 應用程式將不會收到宣告挑戰 (而且將無法使用相關的功能,例如 CAE 權杖),除非該應用程式宣告已準備好使用 "cp1" 功能來進行處理。

如何將用戶端功能傳達給 Microsoft Entra ID

下列範例宣告參數說明用戶端應用程式如何將其功能傳達給 OAuth 2.0 授權碼流程中的 Microsoft Entra ID。

Claims: {"access_token":{"xms_cc":{"values":["cp1"]}}}

如果您使用 MSAL 程式庫,請使用下列程式碼:

_clientApp = PublicClientApplicationBuilder.Create(App.ClientId)
 .WithDefaultRedirectUri()
 .WithAuthority(authority)
 .WithClientCapabilities(new [] {"cp1"})
 .Build();

使用 Microsoft.Identity.Web 的人員可以將下列程式碼新增至設定檔:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": 'Enter_the_Application_Id_Here' 
    "ClientCapabilities": [ "cp1" ],
    // remaining settings...
},

請參閱下列程式碼片段,以查看 Microsoft Entra ID 的範例要求:

GET https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/oauth2/v2.0/authorize
?client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&redirect_uri=https%3A%2F%contoso.com%3A44321%2Fsignin-oidc
&response_type=code
&scope=openid%20profile%20offline_access%20user.read%20Sites.Read.All
&response_mode=form_post
&login_hint=kalyan%ccontoso.onmicrosoft.com
&domain_hint=organizations
&claims=%7B%22access_token%22%3A%7B%22xms_cc%22%3A%7B%22values%22%3A%5B%22cp1%22%5D%7D%7D%7D

當您已經有宣告參數的現有承載時,您會將其新增至現有的集合。

例如,如果您已有來自條件存取驗證內容作業的下列回應:

{"access_token":{"acrs":{"essential":true,"value":"c25"}}}

則您會在現有的宣告承載中預先加上用戶端功能。

{"access_token":{"xms_cc":{"values":["cp1"]},"acrs":{"essential":true,"value":"c25"}}}

在存取權杖中接收 xms_cc 宣告

若要接收用戶端應用程式是否可以處理宣告挑戰的相關資訊,API 實作者必須要求 xms_cc 作為其應用程式資訊清單中的選擇性宣告。

存取權杖中值為 "cp1" 的 xms_cc 宣告,是識別用戶端應用程式是否能夠處理宣告挑戰的授權方式。 xms_cc 是選擇性宣告,不一定會在存取權杖中發出,即使用戶端傳送含有 "xms_cc" 的宣告要求亦然。 為了讓存取權杖包含 xms_cc 宣告,資源應用程式 (也就是 API 實作者) 必須在其應用程式資訊清單中做為選擇性宣告要求 xms_cc。 作為選擇性宣告來要求時,除非用戶端應用程式在宣告要求中傳送了 xms_ccxms_cc 才會新增至存取權杖。 xms_cc 宣告要求值將會包含在存取權杖中的 xms_cc 宣告值 (如果是已知的值)。 目前唯一已知的值為 cp1

這些值不區分大小寫,且未排序。 如果 xms_cc 宣告要求中指定了多個值,則這些值就會是多重值的集合,並做為 xms_cc 宣告的值。

以下列要求為例:

{ "access_token": { "xms_cc":{"values":["cp1","foo", "bar"] } }}

如果 cp1foobar 是已知的功能,這會導致存取權杖中出現下列程式碼片段的宣告。

"xms_cc": ["cp1", "foo", "bar"]

要求xms_cc選擇性宣告之後,應用程式的指令清單會變更為如下所示:

"optionalClaims":
{
    "accessToken": [
    {
        "additionalProperties": [],
        "essential": false,
        "name": "xms_cc",
        "source": null
    }],
    "idToken": [],
    "saml2Token": []
}

然後,API 可以根據用戶端是否能夠處理宣告挑戰來自訂回應。

Claim ccClaim = context.User.FindAll(clientCapabilitiesClaim).FirstOrDefault(x => x.Type == "xms_cc");
if (ccClaim != null && ccClaim.Value == "cp1")
{
    // Return formatted claims challenge as this client understands this
}
else
{
    // Throw generic exception
    throw new UnauthorizedAccessException("The caller does not meet the authentication bar to carry our this operation. The service cannot allow this operation");
}

程式碼範例

下一步