條件式存取驗證內容的開發人員指南
條件式存取是零信任控制平面,讓您針對原則存取所有的應用程式 (無論新舊、私人或公用、內部部署或多雲端)。 使用條件式存取驗證內容,您可以在這些應用程式內套用不同的原則。
條件式存取驗證內容 (驗證內容) 可讓您將細微的原則套用至敏感性資料和動作,而非僅在應用層級上。 您可以針對最低權限存取來精簡零信任原則,同時將使用者的分歧降至最低,讓使用者更具生產力,並讓您的資源更安全。 目前,應用程式會使用 OpenId Connect 來驗證公司開發的驗證,以保護敏感性資源,例如高價值交易或檢視員工個人資料。
若要從應用程式和服務內觸發逐步驗證,請使用 Microsoft Entra 條件式存取引擎的驗證內容功能。 開發人員現在有能力從他們的應用程式內,選擇性地要求增強式驗證,例如從他們的使用者進行 MFA。 這項功能可協助開發人員為應用程式的多數元件建立更順暢的使用者體驗,同時對於更安全作業和資料的存取仍會受到增強式驗證控制項的保護。
問題陳述
IT 系統管理員和監管者通常會對平衡「過於頻繁地以額外的驗證因素提示使用者」和「部分包含敏感資料和作業的應用程式和服務達到足夠的安全性和原則遵循」感到掙扎。 您可以選擇強式原則,但會在使用者存取多數資料和動作時影響他們的生產力,或選擇對於敏感性資源而言強度不足的原則。
因此,假設應用程式可以混用這兩種功能,此時可以在相對較少安全性的情況下運作,針對多數使用者和作業使用較不頻繁的提示,並且在使用者存取更敏感性的部分時,有條件地升級安全性需求?
常見場景
例如,雖然使用者可能會使用多重要素驗證登入 SharePoint,但存取包含敏感性文件的 SharePoint 網站集合可能需要相容的裝置,而且只能從受信任的 IP 範圍存取。
必要條件
第一,您的應用程式應該使用 OpenID Connect/ OAuth 2.0 通訊協定與Microsoft 身分識別平台整合,以進行驗證和授權。 建議您使用 Microsoft 身分識別平台驗證程式庫,以整合該應用程式與 Microsoft Entra ID 並保護。 Microsoft 身分識別平台文件 是瞭解如何將應用程式與 Microsoft 身分識別平台整合的好起點。 條件式存取驗證內容功能支援建置於產業標準 OpenID Connect 通訊協定所提供的通訊協定延伸。 開發人員使用條件式存取驗證內容參考值搭配 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 系統管理員一種將潛在的敏感性動作對應至驗證內容識別碼的方法。 步驟大致如下:
- 識別程式碼中可讓您對應驗證內容識別碼的動作。
- 在應用程式的管理入口網站中建立畫面 (或對等功能),讓 IT 系統管理員可以將敏感性動作對應至可用的驗證內容識別碼。
- 如需操作範例,請參閱程式碼範例,使用條件式存取驗證內容並執行升級驗證。
這些步驟是您必須在程式碼基底中執行的變更。 這些步驟包含廣泛的內容
- 查詢 MS Graph 以列出所有可用的驗證內容。
- 允許 IT 系統管理員選取敏感性/高級權限作業,並使用條件式存取原則針對可用的驗證內容指派這些作業。
- 將此對應資訊儲存在您的資料庫/本機存放區中。
第三:在此範例中,我們假設您的應用程式是 Web API,然後需要針對儲存的對應評估呼叫,並據以針對其用戶端應用程式提出宣告挑戰。 若要準備此動作,請採取下列步驟:
在受驗證內容保護的敏感性作業中,針對稍早儲存的驗證內容識別碼對應評估 acrs 宣告中的值,並觸發 宣告挑戰,如下列程式碼片段所提供。
下圖顯示使用者、用戶端應用程式和 Web API 之間的互動。
接下來的程式碼片段來自程式碼範例,請使用條件式存取驗證內容來執行升級驗證。 第一個方法,API 中的
CheckForRequiredAuthContext()
- 檢查要呼叫的應用程式動作是否需要升級驗證。 這會藉由檢查其資料庫是否有這個方法的儲存對應來執行此動作
- 如果此動作確實需要較高的驗證內容,則會檢查 acr 宣告中是否有現有的相符驗證內容識別碼。
- 如果找不到相符的驗證內容識別碼,系統便會提出宣告挑戰。
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 身分識別平台中的宣告挑戰 一文中說明。
在用戶端應用程式中,攔截宣告挑戰,並將使用者重新導向回 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");
(選擇性) 宣告用戶端功能。 用戶端功能可協助資源提供者 (RP) 如同上述的 Web API,以偵測呼叫用戶端應用程式是否瞭解宣告挑戰,然後可以據以自訂回應。 這項功能很有用,因為並非所有 API 用戶端都能處理宣告挑戰,有些較舊的用戶端則仍預期會有不同的回應。 如需詳細資訊,請參閱用戶端功能一節。
注意事項及建議
請勿在應用程式程式碼中寫入驗證內容值。 應用程式應該使用 MS Graph 呼叫來讀取和套用驗證內容。 這種做法對於多租用戶應用程式來說很重要。 驗證內容值會因 Microsoft Entra 租用戶而異,且 Microsoft Entra ID 免費版無法使用。 如需應用程式如何在其程式碼中查詢、設定和使用驗證內容的詳細資訊,請參閱程式碼範例,使用條件式存取驗證內容來執行升級驗證,以瞭解應用程式應該如何查詢、設定及使用其程式碼中的驗證內容。
應用程式本身是條件式存取原則的目標時,請勿使用驗證內容。 當應用程式的組件需要使用者符合較高層級的驗證時,此功能的效果最佳。
程式碼範例
- 使用條件式存取驗證內容,在 Web 應用程式中執行高權限作業的升級驗證
- 使用條件式存取驗證內容,在 Web API 中執行高權限作業的升級驗證
- 使用條件式存取驗證內容,針對 React 單頁應用程式和 Express Web API 中的高級權限作業執行逐步驗證
條件式存取預期行為的驗證內容 [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 的新權杖。
隱含 ACRS 隨機評估的驗證內容和工作階段預期行為
間隔登入的頻率
條件式存取會將「依間隔登入頻率」視為在登入頻率間隔內,當所有目前驗證因素驗證瞬間都位於登入頻率間隔內時,符合機會性 ACRS 評估。 如果第一個因素驗證時刻過時了,或第二個因素 (MFA) 存在且驗證時刻過時了,則不符合間隔登入的頻率,ACRS 便不會在權杖中隨機發出。
Cloud App Security (CAS)
當 CAS 工作階段在要求期間建立時,條件式存取會視 CAS 工作階段控制項已符合隨機的 ACRS 評估。 例如,當一個要求傳入,且套用條件式存取原則並強制執行 CAS 工作階段,而同時有另一個條件式存取原則也要求 CAS 工作階段時,由於 CAS 工作階段會強制執行,因此便符合隨機評估的 CAS 工作階段控制項。
租用戶包含保護驗證內容之條件式存取原則時的預期行為
下表顯示透過隨機評估將 ACRS 新增至權杖宣告的所有邊角案例。
原則 A:要求所有使用者的 MFA,但要求 "c1" acrs 時,不包括使用者 "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" 全部隨機新增 |