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

宣告挑戰是從 API 傳送的回應,指出用戶端應用程式傳送的存取令牌沒有足夠的宣告。 這是因為令牌不符合該 API 所設定的條件式存取原則,或已撤銷存取令牌。

用戶端應用程式會提出宣告要求,以將使用者重新導向回識別提供者,以擷取具有符合其他需求之宣告的新令牌。

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

您的應用程式只有在呼叫服務時宣告其用戶端功能時,才會收到來自 Microsoft Graph熱門服務的宣告挑戰。

宣告挑戰標頭格式

宣告挑戰是當 API 所呈現存取令牌未獲授權時所傳回的標頭www-authenticate,而需要具有正確功能的新存取令牌。 宣告挑戰包含多個部分:回應的 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-authenticate response header 包含:

參數 必要條件/選擇性 描述
Authentication type 必要 必須是 持有人。
Realm 選用 正在存取的租使用者標識碼或租使用者功能變數名稱(例如,microsoft.com)。 在驗證通過 一般端點的情況下,必須是空字串。
authorization_uri 必要 必要時可執行互動式驗證之 authorize 端點的 URI。 如果在領域指定,則必須將租使用者資訊包含在authorization_uri中。 如果領域是空字串,則authorization_uri必須針對 一般端點
error 必要 當應產生宣告挑戰時,必須「insufficient_claims」。
claims 當錯誤為 「insufficient_claims」 時需要。 包含基底 64 編碼 宣告要求的引號字串。 宣告要求應該要求 JSON 物件最上層 「access_token」 的宣告。 此值(要求的宣告)將會是內容相依的,稍後在本檔中指定。 基於大小考慮,信賴憑證者應用程式應該在基底 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 端點呼叫的一部分傳遞。 擷取令牌之後,就不再需要它。

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

  1. 譯碼稍早收到的base64字串。
  2. 將字串 URL 編碼,然後再次新增至 claims 參數。

完成此流程之後,應用程式會收到具有其他宣告的存取令牌,以證明使用者符合所需的條件。

用戶端功能

用戶端功能可協助 Web API 等資源提供者偵測呼叫用戶端應用程式是否瞭解宣告挑戰,然後據此自定義其回應。 當並非所有 API 用戶端都能夠處理宣告挑戰時,這項功能可能會很有用,而某些舊版仍預期會有不同的回應。

只有在呼叫的用戶端應用程式宣告能夠使用用戶端功能來處理宣告時,Microsoft Graph 之類的一些熱門應用程式才會傳送宣告挑戰。

為了避免額外的流量或對用戶體驗造成影響,除非您明確選擇加入,否則 Microsoft Entra ID 不會假設您的應用程式可以處理挑戰的宣告。 除非應用程式宣告可以使用 「cp1」 功能來處理宣告,否則不會收到宣告挑戰(且無法使用 CAE 令牌等相關功能)。

如何將用戶端功能傳達給 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_cc時,才會將xms_cc新增至存取令牌。 xms_cc宣告要求的值會包含在存取令牌中xms_cc宣告的值,如果是已知的值。 目前唯一已知的值為 cp1

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

以下列要求為例:

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

如果 cp1、foobar 是已知的功能,這會導致存取權杖中下列代碼段的宣告。

"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");
}

程式碼範例

下一步