條件式存取驗證內容的開發人員指南

條件式存取是 零信任 控制平面,可讓您以原則為目標來存取所有應用程式 – 舊版或新版、私人或公用、內部部署或多重雲端。 透過 條件式存取驗證內容,您可以在這些應用程式中套用不同的原則。

條件式存取驗證內容(驗證內容)可讓您將細微原則套用至敏感數據和動作,而不只是在應用層級。 您可以精簡您的 零信任 原則,以取得最低許可權的存取權,同時將使用者摩擦降到最低,並讓使用者更有生產力,且您的資源更安全。 目前,應用程式會使用 OpenId 連線 來進行公司開發的驗證,以保護敏感性資源,例如高價值交易或檢視員工個人資料。

若要從應用程式和服務內觸發逐步驗證,請使用 Microsoft Entra 條件式存取引擎的驗證內容功能。 開發人員現在有能力要求增強的增強式驗證,選擇性地從其應用程式內的使用者要求 MFA。 這項功能可協助開發人員為其應用程式的大部分部分建置更順暢的用戶體驗,同時存取更安全的作業和數據仍落後於更強大的驗證控制。

問題說明

IT 系統管理員和監管者通常會在平衡提示使用者時,過於頻繁地驗證因素,並針對包含敏感數據和作業的應用程式和服務,達到適當的安全性和原則遵循。 當使用者存取大部分的數據和動作或對敏感性資源不夠強的原則時,它可以是影響用戶生產力的強式原則之間的選擇。

那麼,如果應用程式能夠混合這兩者,他們可以在功能上以相對較低的安全性和較不頻繁的提示來運作大多數使用者和作業,但在使用者存取更敏感元件時有條件地加緊安全性需求呢?

常見案例

例如,雖然使用者可能會使用多重要素驗證登入 SharePoint,但存取包含敏感性檔的 SharePoint 網站集合可能需要相容的裝置,而且只能從受信任的 IP 範圍存取。

必要條件

首先,您的應用程式應該使用 OpenID 連線/ OAuth 2.0 通訊協定來與 Microsoft 身分識別平台 整合,以進行驗證和授權。 建議您使用 Microsoft 身分識別平台 驗證連結庫,將應用程式與 Microsoft Entra ID 整合及保護。 Microsoft 身分識別平台 檔是開始瞭解如何整合應用程式與 Microsoft 身分識別平台 的好位置。 條件式存取驗證內容功能支援是以業界標準 OpenID 連線 通訊協定所提供的通訊協定延伸模組為基礎所建置。 開發人員使用 條件式存取驗證內容參考 搭配 Claims Request 參數,讓應用程式能夠觸發和滿足原則。

其次條件式存取 需要 Microsoft Entra ID P1 授權。 如需授權的詳細資訊,請參閱 Microsoft Entra 定價頁面

第三,目前只能供登入用戶的應用程式使用。 不支援以自己身分進行驗證的應用程式。 使用驗證流程和應用程式案例指南來瞭解 Microsoft 身分識別平台 中支援的驗證應用程式類型和流程。

整合步驟

一旦您的應用程式使用支援的驗證通訊協定整合,並在具有可供使用條件式存取功能的 Microsoft Entra 租使用者中註冊之後,您就可以開始在登入使用者的應用程式中整合這項功能的程式。

注意

這項功能的詳細逐步解說也可在應用程式中使用條件式存取驗證內容進行逐步驗證時,以記錄會話的形式提供。

首先,在租使用者中宣告並讓驗證內容可供使用。 如需詳細資訊,請參閱 設定驗證內容

C1-C99 值可用於作為租使用者中的驗證內容標識碼 驗證內容的範例可能是:

  • C1 - 需要強身份驗證
  • C2 – 需要相容的裝置
  • C3 – 需要信任的位置

建立或修改條件式存取原則,以使用條件式存取驗證內容。 範例原則可能是:

  • 登入此 Web 應用程式的所有使用者都應該已順利完成驗證內容識別碼 C1 的 2FA。
  • 登入此 Web 應用程式的所有使用者都應該已順利完成 2FA,也應該從驗證內容識別碼 C3 的特定 IP 位址範圍存取 Web 應用程式。

注意

條件式存取驗證內容值會宣告和維護與應用程式分開。 不建議應用程式對驗證內容標識碼進行硬式相依性。 條件式存取原則通常是由IT系統管理員所製作,因為它們可以進一步瞭解可用來套用原則的資源。 例如,對於 Microsoft Entra 租使用者,IT 系統管理員會知道有多少租使用者的使用者能夠針對 MFA 使用 2FA,因此可以確保需要 2FA 的條件式存取原則限定在這些配備的使用者範圍內。 同樣地,如果應用程式用於多個租使用者,則使用中的驗證內容標識符可能不同,而且在某些情況下,完全無法使用。

第二:建議計劃使用條件式存取驗證內容的應用程式開發人員先提供應用程式管理員或IT系統管理員一種將潛在敏感性動作對應至驗證內容標識符的方法。 步驟大致如下:

  1. 程序代碼中的身分識別動作,可用來對應驗證內容識別碼。
  2. 在應用程式的系統管理入口網站中建置畫面(或對等功能),IT 系統管理員可用來對應敏感性動作與可用的驗證內容識別碼。
  3. 如需如何完成的範例, 請參閱使用條件式存取驗證內容來執行逐步驗證 的程式碼範例。

這些步驟是您需要在程式碼基底中執行的變更。 步驟廣泛構成

  • 查詢 MS Graph 以 列出所有可用的驗證內容
  • 允許IT系統管理員選取敏感性/高許可權作業,並使用條件式存取原則針對可用的驗證內容指派這些作業。
  • 將此對應資訊儲存在您的資料庫/本地存儲中。

建立驗證內容的設定流程

第三:您的應用程式,在此範例中,我們會假設它是 Web API,然後需要針對已儲存的對應評估呼叫,並據此引發其用戶端應用程式的宣告挑戰。 若要準備此動作,必須採取下列步驟:

  1. 在受驗證內容作業保護的敏感性和保護中,針對稍早儲存的驗證內容標識碼對應評估 acrs 宣告中的值,並引發宣告挑戰,如下列代碼段所示。

  2. 下圖顯示使用者、用戶端應用程式和 Web API 之間的互動。

    顯示使用者、Web 應用程式、API 和 Microsoft Entra 識別子互動的圖表

    下列代碼段來自程式代碼範例: 使用條件式存取驗證內容來執行逐步驗證。 API 中的第一個方法 CheckForRequiredAuthContext()

    • 檢查所呼叫的應用程式動作是否需要進行逐步驗證。 其做法是檢查其資料庫是否有這個方法的已儲存對應
    • 如果此動作確實需要提升許可權的驗證內容,它會檢查 acrs 宣告是否有現有的相符驗證內容識別碼。
    • 如果找不到相符的驗證內容標識符,則會引發 宣告挑戰
    public void CheckForRequiredAuthContext(string method)
    {
        string authType = _commonDBContext.AuthContext.FirstOrDefault(x => x.Operation == method
                    && x.TenantId == _configuration["AzureAD:TenantId"])?.AuthContextId;
    
        if (!string.IsNullOrEmpty(authType))
        {
            HttpContext context = this.HttpContext;
            string authenticationContextClassReferencesClaim = "acrs";
    
            if (context == null || context.User == null || context.User.Claims == null
                || !context.User.Claims.Any())
            {
                throw new ArgumentNullException("No Usercontext is available to pick claims from");
            }
    
            Claim acrsClaim = context.User.FindAll(authenticationContextClassReferencesClaim).FirstOrDefault(x
                => x.Value == authType);
    
            if (acrsClaim == null || acrsClaim.Value != authType)
            {
                if (IsClientCapableofClaimsChallenge(context))
                {
                    string clientId = _configuration.GetSection("AzureAd").GetSection("ClientId").Value;
                    var base64str = Convert.ToBase64String(Encoding.UTF8.GetBytes("{\"access_token\":{\"acrs\":{\"essential\":true,\"value\":\"" + authType + "\"}}}"));
    
                    context.Response.Headers.Append("WWW-Authenticate", $"Bearer realm=\"\", authorization_uri=\"https://login.microsoftonline.com/common/oauth2/authorize\", client_id=\"" + clientId + "\", error=\"insufficient_claims\", claims=\"" + base64str + "\", cc_type=\"authcontext\"");
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    string message = string.Format(CultureInfo.InvariantCulture, "The presented access tokens had insufficient claims. Please request for claims requested in the WWW-Authentication header and try again.");
                    context.Response.WriteAsync(message);
                    context.Response.CompleteAsync();
                    throw new UnauthorizedAccessException(message);
                }
                else
                {
                    throw new UnauthorizedAccessException("The caller does not meet the authentication  bar to carry our this operation. The service cannot allow this operation");
                }
            }
        }
    }
    

    注意

    宣告挑戰的格式描述於 Microsoft 身分識別平台 的 Claims Challenge 一文中。

  3. 在用戶端應用程式中,攔截宣告挑戰,並將使用者重新導向回 Microsoft Entra ID,以進行進一步的原則評估。 下列代碼段來自程式代碼範例: 使用條件式存取驗證內容來執行逐步驗證

    internal static string ExtractHeaderValues(WebApiMsalUiRequiredException response)
    {
        if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized && response.Headers.WwwAuthenticate.Any())
        {
            AuthenticationHeaderValue bearer = response.Headers.WwwAuthenticate.First(v => v.Scheme == "Bearer");
            IEnumerable<string> parameters = bearer.Parameter.Split(',').Select(v => v.Trim()).ToList();
            var errorValue = GetParameterValue(parameters, "error");
    
            try
            {
                // read the header and checks if it contains error with insufficient_claims value.
                if (null != errorValue && "insufficient_claims" == errorValue)
                {
                    var claimChallengeParameter = GetParameterValue(parameters, "claims");
                    if (null != claimChallengeParameter)
                    {
                        var claimChallenge = ConvertBase64String(claimChallengeParameter);
    
                        return claimChallenge;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        return null;
    }
    

    如果出現宣告挑戰,請在呼叫 Web API 時處理例外狀況,將使用者重新導向回 Microsoft Entra ID 以供進一步處理。

    try
    {
        // Call the API
        await _todoListService.AddAsync(todo);
    }
    catch (WebApiMsalUiRequiredException hex)
    {
        // Challenges the user if exception is thrown from Web API.
        try
        {
            var claimChallenge =ExtractHeaderValues(hex);
            _consentHandler.ChallengeUser(new string[] { "user.read" }, claimChallenge);
    
            return new EmptyResult();
        }
        catch (Exception ex)
        {
            _consentHandler.HandleException(ex);
        }
    
        Console.WriteLine(hex.Message);
    }
    return RedirectToAction("Index");
    
  4. (選擇性)宣告用戶端功能。 用戶端功能可協助資源提供者 (RP)如上述 Web API,以偵測呼叫用戶端應用程式是否瞭解宣告挑戰,然後據以自定義其回應。 這項功能可能很有用,因為並非所有 API 用戶端都能夠處理宣告挑戰,有些較舊的用戶端仍預期有不同的回應。 如需詳細資訊,請參閱用戶端功能一節

注意事項和建議

不要在您的應用程式中硬式編碼驗證內容值。 應用程式應該使用 MS Graph 呼叫來讀取和套用驗證內容。 這種做法對於 多租用戶應用程式而言非常重要。 驗證內容值會因 Microsoft Entra 租使用者而異,且無法在 Microsoft Entra ID Free Edition 中使用。 如需應用程式在其程式代碼中如何查詢、設定及使用驗證內容的詳細資訊,請參閱程式碼範例: 使用條件式存取驗證內容來執行逐步驗證 ,作為應用程式在程式碼中查詢、設定和使用驗證內容的方式。

請勿使用驗證內容,其中應用程式本身會成為條件式存取原則的目標。 當應用程式的某些部分要求使用者符合較高層級的驗證時,此功能最適用。

程式碼範例

條件式存取預期行為的驗證內容 [ACR]

要求中的明確驗證內容滿意度

用戶端可以透過要求主體中的宣告,明確要求具有驗證內容 (ACRS) 的令牌。 如果已要求 ACRS,條件式存取會允許在完成所有挑戰時,以要求的 ACRS 發出令牌。

當租使用者中的條件式存取未保護驗證內容時的預期行為

當指派給 ACRS 值的所有條件式存取原則都已滿足時,條件式存取可以在令牌的宣告中發出 ACRS。 如果未將條件式存取原則指派給 ACRS 值,則宣告可能仍會發出,因為已滿足所有原則需求。

明確要求 ACRS 時預期行為的摘要數據表

要求 ACRS 已套用原則 已滿足控制件 已新增至宣告的 ACRS
.是 .是
.是 .是
.是 .是 .是 .是
Yes 沒有使用 ACRS 設定的原則 Yes Yes

機會評估的隱含驗證內容滿意度

資源提供者可以選擇加入選擇性的 『acrs』 宣告。 條件式存取會嘗試將 ACRS 新增至令牌宣告機會,以避免往返取得新令牌至 Microsoft Entra ID。 在該評估中,條件式存取會檢查保護驗證內容挑戰的原則是否已滿足,並視需要將 ACRS 新增至令牌宣告。

注意

每個令牌類型都必須個別選擇加入(標識元令牌、存取令牌)。

如果資源提供者未選擇加入選擇性的 『acrs』 宣告,在令牌中取得 ACRS 的唯一方式就是在令牌要求中明確要求它。 它不會取得機會性評估的優點,因此每當令牌宣告中遺漏必要的 ACRS 時,資源提供者會挑戰用戶端取得包含在宣告中的新令牌。

具有隱含 ACRS 機會評估之驗證內容和會話控件的預期行為

依間隔登入頻率

條件式存取會將「依間隔登入頻率」視為在登入頻率間隔內,當所有目前驗證因素驗證瞬間都位於登入頻率間隔內時,符合機會 ACRS 評估。 如果第一個因素驗證瞬間過時,或第二個因素 (MFA) 存在且其驗證瞬間過時,則不滿足間隔的登入頻率,且 ACRS 不會以機會方式在令牌中發出。

雲端 App 安全性(CAS)

條件式存取會在要求期間建立 CAS 工作階段時,將 CAS 會話控件視為對機會性 ACRS 評估感到滿意。 例如,當要求傳入且套用並強制執行 CAS 工作階段的任何條件式存取原則時,此外還有條件式存取原則也需要 CAS 工作階段,因為會強制執行 CAS 工作階段,以滿足 CAS 會話控件的機會性評估。

當租使用者包含保護驗證內容的條件式存取原則時的預期行為

下表顯示 ACRS 透過機會評估新增至令牌宣告的所有邊角案例。

原則 A:要求 「c1」 acrs 時,要求所有使用者的 MFA,不包括使用者 「Ariel」。 原則 B:在要求 「c2」 或 「c3」 acrs 時封鎖所有使用者,不包括使用者 「Jay」。

Flow 要求 ACRS 已套用原則 已滿足控制件 已新增至宣告的 ACRS
存取令牌的 Ariel 要求 “c1” 是的 「c1」。。 “c2” 和 “c3” 否 “c1” (要求)
存取令牌的 Ariel 要求 “c2” 原則 B 原則 B 封鎖
存取令牌的 Ariel 要求 是的 「c1」。。 “c2” 和 “c3” 否 “c1” (從原則 A 中加入機會主義)
Jay 要求存取權杖 (不含 MFA) “c1” 原則 A No
Jay 要求存取權杖 (使用 MFA) “c1” 原則 A Yes “c1” (要求),“c2” (從原則 B 加入機會主義), “c3” (從原則 B 中加入機會主義)
Jay 要求存取權杖 (不含 MFA) “c2” 是 ,適用於 「c2」 和 「c3」。 “c1” 的否 “c2” (要求), “c3” (從原則 B 中以機會方式新增)
Jay 要求存取權杖 (使用 MFA) “c2” “c1”、“c2” 和 “c3” 是 “c1” (A 的盡最大努力)、“c2” (要求)、“c3” (從原則 B 中以機會方式新增)
Jay 要求存取權杖 (使用 MFA) “c1”、“c2” 和 “c3” 是 “c1”、“c2”、“c3” 所有機會加入
Jay 要求存取權杖 (不含 MFA) 是 ,適用於 「c2」 和 「c3」。 “c1” 的否 “c2”、“c3” 所有機會加入

下一步