適用於:所有 APIM 層
重要
自 2025 年 5 月 1 日起,Azure AD B2C 將不再可供新客戶購買。 在我們的常見問題中深入瞭解。
此情節說明如何設定 Azure API 管理執行個體來保護 API。 我們會使用 Azure AD B2C SPA (驗證碼 + PKCE) 流程來取得令牌,以及 API 管理,以使用 EasyAuth 來保護 Azure Functions 後端。
如需 API 授權的概念概觀,請參閱 APIM 中的 API 驗證和授權。
目標
我們將了解如何在簡易情節中以 Azure Functions 和 Azure AD B2C 來使用 API 管理。 您將建立 JavaScript (JS) 應用程式來呼叫 API,以使用 Azure AD B2C 讓使用者登入。 然後,您將使用 API 管理的 validate-jwt、CORS 和「依金鑰限制速率」原則功能來保護後端 API。
為了深入防禦,我們接著使用 EasyAuth 在後端 API 內再次驗證權杖,並確保 API 管理是唯一可以呼叫 Azure Functions 後端的服務。
您將學到什麼
- 在 Azure Active Directory B2C 中設定單頁應用程式和後端 API
- 建立 Azure Functions 後端 API
- 將 Azure Functions API 匯入 Azure API 管理
- 在 Azure API 管理中保護 API
- 透過 Microsoft 身分識別平台程式庫 (MSAL.js) 呼叫 Azure Active Directory B2C 授權端點
- 儲存 HTML /Vanilla JS 單頁應用程式,並從 Azure Blob 記憶體端點提供服務
必要條件
若要依照本文中的步驟進行,您必須有:
- Azure (StorageV2) 一般用途 V2 儲存體帳戶來裝載前端 JS 單頁應用程式。
- Azure API 管理實例(任何層級都可以運作,包括「取用」,不過適用於完整案例的特定功能在此層中無法使用(依密鑰速率限制和專用虛擬 IP),這些限制如下文中適當地指出。
- 空的 Azure 函數應用程式 (在取用方案上執行 V3.1 .NET Core 執行階段) 來裝載呼叫為 API
- Azure AD B2C 租用戶,連結至訂用帳戶。
雖然實際上您會在生產工作負載的相同區域中使用資源,但針對本作說明文章,部署區域並不重要。
概觀
以下舉例說明此流程完成之後使用中的元件及其之間的流程。
以下為步驟的快速概觀:
以範圍和授與 API 存取權建立 Azure AD B2C 呼叫 (前端、API 管理) 和 API 應用程式
建立註冊和登入原則,讓使用者使用 Azure AD B2C 登入
使用新的 Azure AD B2C 用戶端識別碼和金鑰來設定 API 管理,在開發人員主控台啟用 OAuth2 使用者授權
建立函式 API
設定函式 API 以新的 Azure AD B2C 用戶端識別碼和金鑰來啟用 EasyAuth,並鎖定 APIM VIP
在 API 管理中建立 API 定義
設定 API 管理 API 組態的 OAuth2
設定 CORS 原則和新增 validate-jwt 原則,以驗證每個傳入要求的 OAuth 權杖
組建呼叫端應用程式以取用 API
上傳 JS SPA 範例
使用新的 Azure AD B2C 用戶端識別碼和金鑰來設定範例 JS 用戶端應用程式
測試用戶端應用程式
提示
我們將獲取大量資訊和金鑰等。在閱讀此文件時,您可能會發現開啟文本編輯器來暫時儲存以下設定專案會非常方便。
B2C 後端用戶端標識符:B2C 後端用戶端秘密密鑰:B2C 後端 API 範圍 URI:B2C 前端用戶端標識符:B2C 使用者流程端點 URI:B2C WELL-KNOWN OPENID 端點:B2C 原則名稱:Frontendapp_signupandsignin函式 URL:APIM API 基底 URL:記憶體主要端點 URL:
設定後端應用程式
在入口網站中開啟 Azure AD B2C 刀鋒視窗,然後執行下列步驟。
選取 [應用程式註冊] 索引標籤
選取 [新增註冊] 按鈕。
從 [重新導向 URI] 選取方塊中選擇 [Web]。
現在設定 [顯示名稱],選擇的名稱應該獨特又胋切所建立的服務。 在此範例中,我們使用的名稱是「後端應用程式」。
使用預留位置來表示回覆 URL,例如 'https://jwt.ms' (Microsoft 擁有的權杖解碼網站),稍後會更新這些 URL。
在任何身分識別提供者或組織目錄 (用於使用者流程中驗證使用者) 選項中,務必選取「帳戶」
在此範例中,因為目前不需要 offline_access 權限,取消核取 [授與管理員同意] 方塊。
選取 [註冊]。
記錄後端應用程式用戶端識別碼,供稍後使用 (顯示在 [應用程式 (用戶端) 識別碼] 下)。
選取 [ 憑證和秘密 ] 索引標籤 (在 [管理] 下),然後選取 [新增客戶端密碼] 以產生驗證密鑰(接受預設設定,然後選取 [新增]。
按兩下 [新增] 時,將密鑰 (在 'value' 底下) 複製到安全的地方,以供稍後用來作為「後端用戶端密碼」-請注意,此對話框是您複製此密鑰的唯一機會。
現在,選取 [公開 API] 索引標籤 (在 [管理] 下)。
系統會提示您設定 AppID URI,選取並記錄預設值。
建立並命名函式 API 的範圍 「Hello」,您可以針對所有可輸入的選項使用片語 'Hello',錄製填入的完整範圍值 URI,然後選取 [新增範圍]。
選取入口網站左上方的 [Azure AD B2C] 階層連結,返回 Azure AD B2C 刀鋒視窗的根目錄。
注意
Azure AD B2C 範圍實際上是 API 內的權限,可供其他應用程式從其應用程式透過 API 存取刀鋒視窗來要求存取,事實上您只是為呼叫的 API 建立應用程式權限。
設定前端應用程式
- 選取 [應用程式註冊] 索引標籤
- 選取 [新增註冊] 按鈕。
- 從 [重新導向 URI] 選取方塊中選擇 [單頁應用程式 (SPA)]。
- 現在設定 [顯示名稱] 和 [AppID URI],選擇的值應該獨特又貼近將使用此 Azure Active Directory B2C 應用程式註冊的前端應用程式。 在此範例中,您可以使用「前端應用程式」
- 如同第一次應用程式註冊,將支援的帳戶類型選擇保持預設 (在使用者流程中驗證使用者)
- 使用預留位置來表示回覆 URL,例如 'https://jwt.ms' (Microsoft 擁有的權杖解碼網站),稍後會更新這些 URL。
- 保持勾選 [授與管理員同意] 方塊
- 選取 [註冊]。
- 記錄前端應用程式用戶端識別碼,供稍後使用 (顯示在 [應用程式 (用戶端) 識別碼] 下)。
- 切換至 [API 權限] 索引標籤。
- 點擊 [新增許可權],然後點擊 [我的 API],選取 [後端應用程式],選取 [許可權],選取您在上一節中建立的範圍,然後選取 [新增許可權]。
- 選取 [為 {tenant} 授與管理員同意],然後從快顯對話框中選取 [是]。 此快顯同意「前端應用程式」使用稍早建立的「後端應用程式」中定義的權限 "hello"。
- 現在,應用程式的所有權限在 [狀態] 欄下應該都顯示為綠色勾號
建立「註冊和登入」使用者流程
選取 Azure AD B2C 階層連結,返回 B2C 刀鋒視窗的根目錄。
切換至 [使用者流程] 索引標籤 (在 [原則] 下)。
選取 [新增使用者流程]
選擇 [註冊和登入] 使用者流程類型,選取 [建議] 及 [建立]
命名原則並記錄名稱,供稍後使用。 在此範例中,您可以使用 “Frontendapp_signupandsignin”,請注意,這會加上前綴 “B2C_1_”,使其成為 “B2C_1_Frontendapp_signupandsignin”。
在 [識別提供者] 和 [本機帳戶] 底下,檢查 [電子郵件註冊] (或 [使用者標識符註冊],視 B2C 租使用者的設定而定),然後選取 [確定]。 這樣設定是因為我們要註冊本地 B2C 帳戶,而不是交給另一個身分識別提供者 (例如社交識別提供者) 採用使用者現有的社交媒體帳戶。
將 MFA 和條件式存取設定保持預設。
在 [使用者屬性和宣告] 底下,選取 [顯示更多...]然後選擇您希望使用者輸入並在令牌中傳回的宣告選項。 檢查並確保至少收集「顯示名稱」和單數形式的「電子郵件地址」,並設定為傳回「顯示名稱」和複數形式的「電子郵件地址」(請注意此區分)。選取「確定」後,再選取「建立」。
選取您在清單中建立的使用者流程,然後選取 [執行使用者流程] 按鈕。
此動作會開啟 [執行使用者流程] 刀鋒視窗、選取前端應用程式、複製使用者流程端點,並儲存以供稍後使用。
複製並儲存頂端的連結,記錄為「已知 openid 設定端點」供稍後使用。
注意
B2C 原則可讓您公開 Azure AD B2C 登入端點,而能夠擷取不同的資料元件並以不同方式讓使用者登入。
在此案例中,我們已設定註冊或登入流程 (原則)。 這也公開已知的設定端點,在這兩種情況下,URL 中以 "p=" 查詢字串參數識別我們建立的原則。
完成後,您現在有可運作的企業對消費者身分識別平台,可讓使用者登入多個應用程式。
建立函式 API
切換回 Azure 入口網站中的標準 Microsoft Entra 租用戶,讓我們再次於訂用帳戶中設定項目。
移至 Azure 入口網站的 [函式應用程式] 刀鋒視窗,開啟您的空白函式應用程式,然後選取 [函式],然後選取 [新增]。
在隨即出現的彈出視窗中,選擇 [在入口網站中開發],在 [選取範本] 底下,選擇 [HTTP 觸發程式],然後在 [範本詳細資料] 中命名為 'hello',授權層級設定為 [Function],最後選取 [新增]。
切換至 [程式碼 + 測試] 刀鋒視窗,將下方的範例程式碼複製貼上,以「覆蓋現有的程式碼」。
選取 [儲存]。
using System.Net; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; public static async Task<IActionResult> Run(HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); return (ActionResult)new OkObjectResult($"Hello World, time and date are {DateTime.Now.ToString()}"); }提示
您剛才貼上的 C# 指令碼函式程式碼只是將一行記錄到函式記錄,然後傳回 "Hello World" 文字,還有一些動態資料 (日期和時間)。
從左側刀鋒視窗中選取 [整合],然後選取 [觸發程式] 方塊內的 HTTP (req) 連結。
從 [選取的 HTTP 方法] 下拉式清單中,取消核取 HTTP POST 方法,只選取 [GET],然後選取 [儲存]。
切換回 [程序代碼 + 測試] 索引標籤,選取 [取得函式 URL],然後複製出現的 URL,以供稍後儲存。
注意
您剛才建立的繫結只是告訴 Functions,針對您剛才複製的 URL (
https://yourfunctionappname.azurewebsites.net/api/hello?code=secretkey) 回應匿名 HTTP GET 要求。 現在,我們有可調整的無伺服器 HTTPs API,能夠傳回簡單的承載。現在可以使用您剛才在上方複製並儲存的 URL 版本,從網頁瀏覽器測試呼叫此 API。 您也可以移除 URL 的查詢字串參數 「?code=secretkey」 部分,然後再次測試,以證明 Azure Functions 會傳回 401 錯誤。
設定和保護函式 API
需要設定函式應用程式中的兩個額外區域 (授權和網路限制)。
首先,讓我們設定驗證/授權,請透過階層連結巡覽回函式應用程式的根目錄刀鋒視窗。
接下來選取 [驗證] (在 [設定] 下)。
選取 [新增識別提供者]
在 [識別提供者] 下拉式清單中選取 [Microsoft]
針對 [應用程式註冊],選取 [提供現有應用程式註冊的詳細資料]
將後端應用程式的用戶端識別碼 (從 Azure AD B2C) 貼到 [應用程式 (用戶端) 識別碼] 方塊中 (我們稍早已記錄此設定)。
從註冊和登入原則中,將已知 open-id 設定端點貼到 [簽發者 URL] 方塊中 (我們稍早已記錄此設定)。
將後端應用程式的用戶端密碼貼到適當方塊中 (我們稍早已記錄此設定)。
針對 [未驗證的要求],選取 [HTTP 401 未經授權:建議用於 API]
選取 [儲存] (刀鋒視窗左上方)。
重要
現在,您的函式 API 已部署,如果未提供正確的 JWT 作為 Authorization: Bearer 標頭,應該會擲回 401 回應,如果存在有效的要求,應該會傳回資料。 您已在 EasyAuth 中設定 [使用 Microsoft Entra ID 登入] 選項來處理未經驗證的要求,增加額外的深度防禦安全性。
我們仍未套用 IP 安全性,如果您具備有效的金鑰和 OAuth2 權杖,則可供任何人從任何地方呼叫 - 我們最好強制所有要求都透過 API 管理到來。
如果您使用 API 管理取用、基本 v2、標準 v2 和進階 v2 層,則 沒有專門的 Azure API 管理虛擬 IP 可以加入函式存取限制的允許清單。 在 Azure API 管理 傳統(專用)層中,VIP 是單一租使用者,且資源存留期。 針對共用基礎結構上執行的層,可透過共用秘密函式金鑰 (位於上方所複製的 URI 部分中) 來鎖定 API 呼叫。 此外,這些層級不適用以下的步驟 12-17。
從 App Service / Azure Functions 入口網站關閉 [驗證] 刀鋒視窗。
開啟「入口網站的 API 管理刀鋒視窗」,然後開啟「您的執行個體」。
記錄 [概觀] 索引標籤上顯示的私人 VIP。
返回「入口網站的 Azure Functions 刀鋒視窗」,然後再次開啟「您的執行個體」。
選取 [網路],然後選取 [設定存取限制]
選取 [新增規則],然後輸入上述步驟 3 中複製的 VIP,格式為 xx.xx.xx.xx/32。
如果您想要繼續與函式入口網站互動,並執行下列選擇性步驟,則也應該在這裡新增您自己的公用 IP 位址或 CIDR 範圍。
一旦清單中有允許項目,Azure 會新增隱含拒絕規則來封鎖其他所有位址。
您必須將 CIDR 格式化的位址區塊新增至 IP 限制面板。 需要新增單一位址時,例如 API 管理 VIP,您必須以 xx.xx.xx.xx/32 格式新增。
注意
現在,您的函式 API 不應該從任何位置呼叫,除非是透過 API 管理或您的位址。
開啟「API 管理刀鋒視窗」,然後開啟「您的執行個體」。
選取 [API] 刀鋒視窗 (在 [API] 下)。
從 [新增 API] 窗格中,選擇 [函數應用程式],然後從快顯視窗頂端選取 [完整]。
按一下 [瀏覽],選擇內已裝載 API 的函數應用程式,然後按一下 [選取]。 接著按一下 [選取]。
為 API 提供名稱和描述,供 API 管理內部使用,並新增至「無限制」產品。
複製並記錄 API 的 「基底 URL」,然後選取 [建立]。
選取 [設定] 索引標籤,然後在 [訂閱] 選項下,取消選取 [需要訂閱] 複選框,因為在此情況下,我們會使用 OAuth JWT 來設定速率限制。 請注意,如果您使用取用層,則實際執行環境中仍需要如此。
提示
如果使用 APIM 的取用層,則沒有現成的無限制產品可用。 相反地,流覽至 [API] 底下的 [產品],然後按 [新增]。輸入 “Unlimited” 作為產品名稱和描述,然後從畫面左下方的 “+” API 圖說文字中選取您剛才新增的 API。 選取 [已發行] 核取方塊。 其餘項目都保持預設。 最後,按 [建立] 按鈕。 這樣會建立「無限制」產品並指派給您的 API。 稍後可以自訂您的新產品。
設定和擷取正確的儲存體端點設定
在 Azure 入口網站中開啟儲存體帳戶刀鋒視窗
選取您建立的帳戶,然後從 [設定] 區段中選取 [靜態網站] 刀鋒視窗 (如果沒看到 [靜態網站] 選項,請檢查您是否已建立 V2 帳戶)。
將靜態 Web 主控功能設定為 [已啟用],並將索引檔名稱設定為 『index.html』,然後選取 [儲存]。
記下 [主要端點] 的內容供稍後使用,因為前端網站將裝載於此位置。
提示
您可以使用 Azure Blob 儲存體 + CDN 重寫,或 Azure App Service 來裝載 SPA,但 Blob 儲存體的靜態網站裝載功能提供預設容器,可從 Azure 儲存體供應靜態 Web 內容 / html / js / css,並為我們推斷一個免處理的預設頁面。
設定 CORS 和 validate-jwt 原則
不論使用哪個 APIM 層,請一律遵循下列各節。 儲存體帳戶 URL 來自您在本文開頭的必要條件中提供的儲存體帳戶。
切換至入口網站的 API 管理刀鋒視窗,然後開啟您的執行個體。
選取 [API],然後選取 [所有 API]。
在 [輸入處理] 下,選取程式代碼檢視按鈕 “</>” 以顯示原則編輯器。
編輯輸入區段,將下列 xml 貼上,變成如下所示。
在原則中取代下列參數
{PrimaryStorageEndpoint} (您在上一節複製的「主要儲存體端點」) {b2cpolicy-known-openid} (您稍早複製的「已知 openid 設定端點」) 和 {backend-api-application-client-id} (後端 API的 B2C 應用程式/用戶端識別碼) 換成先前儲存的正確值。
如果使用 APIM 的取用層,則應該移除這兩個 rate-limit-by-key 原則,因為使用 Azure APIM 的取用層時沒有此原則可用。
<inbound> <cors allow-credentials="true"> <allowed-origins> <origin>{PrimaryStorageEndpoint}</origin> </allowed-origins> <allowed-methods preflight-result-max-age="120"> <method>GET</method> </allowed-methods> <allowed-headers> <header>*</header> </allowed-headers> <expose-headers> <header>*</header> </expose-headers> </cors> <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid." require-expiration-time="true" require-signed-tokens="true" clock-skew="300"> <openid-config url="{b2cpolicy-well-known-openid}" /> <required-claims> <claim name="aud"> <value>{backend-api-application-client-id}</value> </claim> </required-claims> </validate-jwt> <rate-limit-by-key calls="300" renewal-period="120" counter-key="@(context.Request.IpAddress)" /> <rate-limit-by-key calls="15" renewal-period="60" counter-key="@(context.Request.Headers.GetValueOrDefault("Authorization","").AsJwt()?.Subject)" /> </inbound>注意
現在,Azure API 管理能夠回應來自 JavaScript SPA 應用程式的跨原始來源要求,並且會在將要求轉送至函式 API 之前,先執行節流、速率限制和 JWT 驗證令牌的預先驗證。
恭喜您,您現在有 Azure AD B2C、API 管理和 Azure Functions 共同發佈、保護及取用 API!
提示
如果使用 APIM 取用層,您可以依呼叫率配額來限制 (請參閱此處),而非依 JWT 主體或傳入 IP 位址來限制速率 (「取用」層目前不支援依金鑰限制呼叫率原則)。 由於此範例是 JavaScript 單頁應用程式,我們只針對速率限制和計費呼叫來使用 API 管理金鑰。 實際的授權和驗證由 Azure AD B2C 負責,並封裝在 JWT 中,所以驗證兩次,一次是由 API 管理,另一次是由後端 Azure 函式。
將 JavaScript SPA 範例上傳至靜態儲存體
仍在儲存帳戶刀鋒視窗中,從 [Blob 服務] 區段中選取 [容器] 刀鋒視窗,然後選取出現在右側窗格中的 $web 容器。
在本機電腦上將下列程式碼儲存為 index.html 檔案,然後將 index.html 檔案上傳至 $web 容器。
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous"> <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.11.1/js/msal-browser.min.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-12"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <div class="container-fluid"> <a class="navbar-brand" href="#">Azure Active Directory B2C with Azure API Management</a> <div class="navbar-nav"> <button class="btn btn-success" id="signinbtn" onClick="login()">Sign In</a> </div> </div> </nav> </div> </div> <div class="row"> <div class="col-md-12"> <div class="card" > <div id="cardheader" class="card-header"> <div class="card-text"id="message">Please sign in to continue</div> </div> <div class="card-body"> <button class="btn btn-warning" id="callapibtn" onClick="getAPIData()">Call API</a> <div id="progress" class="spinner-border" role="status"> <span class="visually-hidden">Loading...</span> </div> </div> </div> </div> </div> </div> <script lang="javascript"> // Just change the values in this config object ONLY. var config = { msal: { auth: { clientId: "{CLIENTID}", // This is the client ID of your FRONTEND application that you registered with the SPA type in Azure Active Directory B2C authority: "{YOURAUTHORITYB2C}", // Formatted as https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantguid or full tenant name including onmicrosoft.com}/{signuporinpolicyname} redirectUri: "{StoragePrimaryEndpoint}", // The storage hosting address of the SPA, a web-enabled v2 storage account - recorded earlier as the Primary Endpoint. knownAuthorities: ["{B2CTENANTDOMAIN}"] // {b2ctenantname}.b2clogin.com }, cache: { cacheLocation: "sessionStorage", storeAuthStateInCookie: false } }, api: { scopes: ["{BACKENDAPISCOPE}"], // The scope that we request for the API from B2C, this should be the backend API scope, with the full URI. backend: "{APIBASEURL}/hello" // The location that we'll call for the backend api, this should be hosted in API Management, suffixed with the name of the API operation (in the sample this is '/hello'). } } document.getElementById("callapibtn").hidden = true; document.getElementById("progress").hidden = true; const myMSALObj = new msal.PublicClientApplication(config.msal); myMSALObj.handleRedirectPromise().then((tokenResponse) => { if(tokenResponse !== null){ console.log(tokenResponse.account); document.getElementById("message").innerHTML = "Welcome, " + tokenResponse.account.name; document.getElementById("signinbtn").hidden = true; document.getElementById("callapibtn").hidden = false; }}).catch((error) => {console.log("Error Signing in:" + error); }); function login() { try { myMSALObj.loginRedirect({scopes: config.api.scopes}); } catch (err) {console.log(err);} } function getAPIData() { document.getElementById("progress").hidden = false; document.getElementById("message").innerHTML = "Calling backend ... " document.getElementById("cardheader").classList.remove('bg-success','bg-warning','bg-danger'); myMSALObj.acquireTokenSilent({scopes: config.api.scopes, account: getAccount()}).then(tokenResponse => { const headers = new Headers(); headers.append("Authorization", `Bearer ${tokenResponse.accessToken}`); fetch(config.api.backend, {method: "GET", headers: headers}) .then(async (response) => { if (!response.ok) { document.getElementById("message").innerHTML = "Error: " + response.status + " " + JSON.parse(await response.text()).message; document.getElementById("cardheader").classList.add('bg-warning'); } else { document.getElementById("cardheader").classList.add('bg-success'); document.getElementById("message").innerHTML = await response.text(); } }).catch(async (error) => { document.getElementById("cardheader").classList.add('bg-danger'); document.getElementById("message").innerHTML = "Error: " + error; }); }).catch(error => {console.log("Error Acquiring Token Silently: " + error); return myMSALObj.acquireTokenRedirect({scopes: config.api.scopes, forceRefresh: false}) }); document.getElementById("progress").hidden = true; } function getAccount() { var accounts = myMSALObj.getAllAccounts(); if (!accounts || accounts.length === 0) { return null; } else { return accounts[0]; } } </script> </body> </html>瀏覽至您先前在上一節儲存的靜態網站主要端點。
注意
恭喜,您剛才已將 JavaScript 單頁應用程式部署至 Azure 儲存體靜態內容裝載。 由於尚未以您的 Azure AD B2C 詳細資料來設定 JS 應用程式,頁面開啟時沒有作用。
設定適用於 Azure AD B2C 的 JavaScript SPA
- 現在我們已完全了解:我們可以使用適當的 API 管理 API 位址和正確的 Azure AD B2C 應用程式/用戶端識別碼來設定 SPA。
- 返回 Azure 入口網站儲存體刀鋒視窗
- 選取 [容器] (在 [設定] 下)
- 從清單中選取 '$web' 容器
- 從清單中選取 index.html Blob
- 選取 [編輯]
- 將 MSAL config 區段中的 auth 值更新為符合您稍早在 B2C 中註冊的「前端」應用程式。 參考程式碼註解中的提示,以了解 config 值的模樣。 authority 值的格式必須為 https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantname}.onmicrosoft.com}/{signupandsigninpolicyname},如果您已使用我們的範例名稱,而且 b2c 租用戶稱為 'contoso',則 authority 應該是 'https://contoso.b2clogin.com/tfp/contoso.onmicrosoft.com/Frontendapp_signupandsignin'。
- 設定 API 值以符合您的後端位址(您稍早記錄的 API 基底 URL,以及先前針對 後端應用程式記錄 'b2cScopes' 值)。
- 選取 [儲存]。
設定 Azure AD B2C 前端應用程式的重新導向 URI
開啟 Azure AD B2C 刀鋒視窗,然後巡覽至 JavaScript 前端應用程式的應用程式註冊。
選擇 [重新導向 URI],並刪除我們之前輸入的佔位符 'https://jwt.ms'。
新增主要 (儲存體) 端點的新 URI (去掉尾端斜線)。
注意
此設定可讓前端應用程式的用戶端從 B2C Azure AD 收到具有適當宣告的存取權杖。 SPA 能夠在呼叫後端 API 時,在 https 標頭中將此權杖新增為持有人權杖。
在將要求傳遞至接收端 Azure 函式 API 的要求、新增函式安全性金鑰之前,API 管理會依 Azure 識別碼 (使用者) 發出的 JWT 主體,並依呼叫端的 IP 位址 (視 API 管理的服務層級而定,見上述附註),預先驗證權杖、限制對端點的呼叫速率。 SPA 會在瀏覽器中呈現回應。
恭喜,您已設定 Azure AD B2C、Azure API 管理、Azure Functions、Azure App Service 授權來完美協調運作!
現在,我們有一個簡單的應用程式和簡單的受保護 API,接著來測試。
測試用戶端應用程式
- 開啟您從稍早建立的儲存體帳戶中記下的應用程式範例 URL。
- 選取右上角的 [登入],此動作將會顯示您的 Azure AD B2C 註冊或登入頁面。
- 應用程式應該會以 B2C 設定檔名稱來歡迎您。
- 現在選取 [呼叫 API],頁面應該會以從安全 API 傳回的值進行更新。
- 如果您 重複 選取 [呼叫 API] 按鈕,而您使用的是 API 管理的開發人員層或更高版本,您應該注意您的解決方案會開始限制 API 使用速率,應在應用程式中顯示適當的訊息來報告此功能。
大功告成!
您可以調整和編輯上述步驟,以採取許多不同方式來使用 API 管理與 Azure AD B2C。
相關內容
- 深入了解 Microsoft Entra ID 和 OAuth2.0。
- 請參閱 API 管理 的詳細資訊 。
- 如需其他保護後端服務的方式,請參閱相互憑證驗證。
- 建立 API 管理服務執行個體。
- 管理第一個 API。