共用方式為


使用 OpenID Connect (OIDC) 保護 ASP.NET Core Blazor Web App

注意

這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前的版本,請參閱 本文的 .NET 9 版本。

本文說明如何使用 dotnet/blazor-samples GitHub 存放庫 (.NET 8 或更新版本) (如何下載) 中的應用程式範例,使用 OpenID Connect (OIDC) 保護 Blazor Web App 。

這個版本的發行項包含不採用前端的後端 (BFF) 模式實作 OIDC。 BFF 模式適用於對外部服務提出已驗證的要求。 如果應用程式的規格要求採用 BFF 模式,請將發行項版本選取器變更為使用 BFF 的 OIDC 模式

涵蓋下列規格:

  • Blazor Web App 使用 自動轉譯模式搭配全域互動功能
  • 伺服器和用戶端應用程式使用自訂驗證狀態提供者服務擷取使用者的驗證狀態,並在伺服器與客戶端之間流動。
  • 這個應用程式是任何 OIDC 驗證流程的起點。 OIDC 在應用程式手動設定,且不採用 Microsoft Entra IDMicrosoft Identity Web 套件,應用程式範例也不需要 Microsoft Azure 裝載。 不過,應用程式範例可與 Entra、Microsoft Identity Web 搭配使用,並且裝載於 Azure。
  • 自動非互動式權杖重新整理。
  • 在伺服器專案安全呼叫 (web) API 以取得資料。

範例應用程式

這個應用程式範例包含二個專案:

  • BlazorWebAppOidc: Blazor Web App的伺服器端專案,包含天氣資料的 最小 API 端點範例。
  • BlazorWebAppOidc.Client: Blazor Web App的用戶端專案。

請使用下列連結,透過存放庫根目錄中的最新版本資料夾存取應用程式範例。 專案位於 .NET 8 或更新版本的 BlazorWebAppOidc 資料夾。

檢視或下載範例程式碼 \(英文\) (如何下載)

伺服器端 Blazor Web App 專案 (BlazorWebAppOidc)

BlazorWebAppOidc 專案是 Blazor Web App的伺服器端專案。

BlazorWebAppOidc.http 檔案可用於測試天氣資料要求。 請注意,BlazorWebAppOidc 專案必須執行才能測試端點,而且端點會硬式編碼到檔案中。 如需詳細資訊,請參閱在 Visual Studio 2022 中使用 .http 檔案

注意

伺服器專案會使用 IHttpContextAccessor/HttpContext,但絕不會用於互動式轉譯的元件。 如需詳細資訊,請參閱 ASP.NET Core Blazor 互動式伺服器端轉譯的威脅風險降低指導

組態

本節說明如何設定應用程式範例。

注意

針對 Microsoft Entra ID 或 Azure AD B2C,您可以從 Microsoft Identity Web 使用AddMicrosoftIdentityWebAppMicrosoft.Identity.WebNuGet 套件API 檔),這會將 OIDC 和Cookie驗證處理程式新增為適當的預設值。 本節中的應用程式範例和指導不使用 Microsoft Identity Web。 這份指導示範如何為任何 OIDC 提供者手動設定 OIDC 處理常式。 如需實作 Microsoft Identity Web 的詳細資訊,請參閱連結的資源。

建立客戶端密碼

警告

請勿在用戶端程式代碼中儲存應用程式秘密、連接字串、認證、密碼、個人標識碼 (PIN)、私人 C#/.NET 程式代碼或私鑰/令牌,這一律不安全。 在測試/預備和生產環境中,伺服器端 Blazor 程序代碼和 Web API 應該使用安全驗證流程,以避免在專案程式代碼或組態檔內維護認證。 在本機開發測試之外,建議您避免使用環境變數來儲存敏感數據,因為環境變數不是最安全的方法。 針對本機開發測試, 建議使用秘密管理員工具 來保護敏感數據。 如需詳細資訊,請參閱 安全地維護敏感數據和認證

若要進行本機開發測試,請使用 秘密管理員工具 ,將伺服器應用程式的用戶端密碼儲存在組態密鑰 Authentication:Schemes:MicrosoftOidc:ClientSecret之下。

注意

如果應用程式使用 Microsoft Entra ID 或 Azure AD B2C,請在 Entra 或 Azure 入口網站 的應用程式中註冊中建立用戶端密碼(管理>憑證和秘密>新用戶端密碼)。 在下列指引中使用新秘密的值

尚未 初始化秘密管理員工具的範例應用程式 。 使用命令殼層,例如 Visual Studio 中的開發人員 PowerShell 命令殼層,執行下列命令。 在執行命令之前,請將 目錄與 cd 命令變更為伺服器項目的目錄。 命令會建立使用者密碼識別碼(<UserSecretsId> 在伺服器應用程式的項目檔中):

dotnet user-secrets init

執行下列命令來設定客戶端密碼。 佔 {SECRET} 位元是從應用程式註冊取得的客戶端密碼:

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

如果使用 Visual Studio,您可以用滑鼠右鍵按兩下 方案總管 中的伺服器專案,然後選取 [管理用戶密碼],以確認秘密已設定。

設定應用程式

呼叫 AddOpenIdConnect 時,在專案的 Program 檔案找到下列 OpenIdConnectOptions設定:

  • SignInScheme:設定對應到中介軟體的驗證配置,此中介軟體在成功驗證後負責保存使用者的 identity 。 OIDC 處理常式必須使用能夠跨要求保存使用者認證的登入配置。 下方這一行字僅供示範之用。 如果省略,則會使用 DefaultSignInScheme 做為備用值。

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • openidprofile (Scope) 的範圍 (選擇性):預設也會設定 openidprofile 範圍,因為 OIDC 處理常式需要它們才能運作,但如果 Authentication:Schemes:MicrosoftOidc:Scope 設定包含範圍,則可能必須重新新增這些範圍。 如需一般設定指導,請參閱 ASP.NET Core 中的設定ASP.NET Core Blazor 設定

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens:定義了在成功授權之後,是否應該將存取和重新整理權杖儲存在 AuthenticationProperties 中。 這個屬性被設為 false,以減少最終驗證 cookie 的大小。

    oidcOptions.SaveTokens = false;
    
  • 離線存取的範圍 (Scope):重新整理權杖需要 offline_access 範圍。

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • AuthorityClientId:設定 OIDC 呼叫的授權單位和用戶端識別碼。

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    範例:

    • 授權單位 ({AUTHORITY}):https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ (使用租用戶標識碼 aaaabbbb-0000-cccc-1111-dddd2222eeee)
    • 用戶端識別碼 ({CLIENT ID}):00001111-aaaa-2222-bbbb-3333cccc4444
    oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
    

    Microsoft Azure「通用」授權單位的範例:

    「通用」授權單位應該用於多租用戶應用程式。 您也可以針對單一租用戶應用程式使用「通用」授權單位,但需要有自訂的 IssuerValidator,如本節稍後所示。

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ResponseType:將 OIDC 處理常式設定為只執行授權碼流程。 在這個模式中,不需要隱含授與和混合式流程。

    在 Entra 或 Azure 入口網站的隱含授與和混合式流程應用程式註冊設定中,請勿選取授權端點的核取方塊,以傳回 存取權杖識別碼權杖。 OIDC 處理常式使用從授權端點傳回的程式碼,自動要求適當的權杖。

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaimsNameClaimTypeRoleClaimType 的設定:許多 OIDC 伺服器在 ClaimTypes 使用 “name” 和 “role”,而不是使用 SOAP/WS-Fed 預設值。 當 MapInboundClaims 設定為 false時,處理常式不會執行宣告對應,而且應用程式會直接使用 JWT 的宣告名稱。 下列範例會將角色宣告類型設定為「roles」,這適用於 Microsoft Entra ID (ME-ID)。 請參閱 identity 提供者的文件以取得詳細資訊。

    注意

    針對多數 OIDC 提供者,MapInboundClaims 必須設定為 false,以防重新命名宣告。

    oidcOptions.MapInboundClaims = false;
    oidcOptions.TokenValidationParameters.NameClaimType = "name";
    oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
    
  • 路徑設定:路徑必須符合向 OIDC 提供者註冊應用程式時設定的重新導向 URI (登入回呼路徑),以及登出後重新導向 (登出回呼路徑)。 在 Azure 入口網站,路徑是在應用程式註冊的驗證刀鋒視窗設定。 登入和登出路徑都必須註冊為重新導向 URI。 預設值是 /signin-oidc/signout-callback-oidc

    • CallbackPath:應用程式基本路徑中傳回 user-agent 的要求路徑。

      在 Entra 或 Azure 入口網站,設定 Web 平台設定之重新導向 URI 的路徑:

      https://localhost/signin-oidc

      注意

      使用 Microsoft Entra ID 時,localhost 位址不需要連接埠。 其他 OIDC 提供者多半都需要正確的連接埠。

    • SignedOutCallbackPath:應用程式基本路徑中的要求路徑,在應用程式基本路徑中,於登出 identity 提供者後,傳回使用者代理程式。

      在 Entra 或 Azure 入口網站,設定 Web 平台設定之重新導向 URI 的路徑:

      https://localhost/signout-callback-oidc

      注意

      使用 Microsoft Entra ID 時,localhost 位址不需要連接埠。 其他 OIDC 提供者多半都需要正確的連接埠。

      注意

      如果使用 Microsoft Identity Web,則提供者目前只會在使用 microsoftonline.com 授權單位 (https://login.microsoftonline.com/{TENANT ID}/v2.0/) 時重新導向回 SignedOutCallbackPath。 如果您可以搭配 Microsoft Identity Web 使用「通用」授權單位,則不存在這項限制。 如需詳細資訊,請參閱授權單位 url 包含租用戶識別碼 (AzureAD/microsoft-authentication-library-for-js #5783) 時 postLogoutRedirectUri 無法運作

    • RemoteSignOutPath:在這個路徑收到的要求導致處理常式使用登出配置叫用登出。

      在 Entra 或 Azure 入口網站,設定 Front-channel 登出 URL

      https://localhost/signout-oidc

      注意

      使用 Microsoft Entra ID 時,localhost 位址不需要連接埠。 其他 OIDC 提供者多半都需要正確的連接埠。

      oidcOptions.CallbackPath = new PathString("{PATH}");
      oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
      oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
      

      範例 (預設值):

      oidcOptions.CallbackPath = new PathString("/signin-oidc");
      oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
      oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
      
  • (Microsoft Azure 僅使用「通用」端點) TokenValidationParameters.IssuerValidator:許多 OIDC 提供者會使用預設憑證簽發者驗證程式,但我們必須考慮以 https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration 傳回之租用戶標識碼 ({TENANT ID}) 參數化的憑證簽發者。 如需詳細資訊,請參閱 使用 OpenID Connect 與 Azure AD「通用」端點 (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731) 的 SecurityTokenInvalidIssuerException

    僅適用於使用 Microsoft Entra ID 或 Azure AD B2C 搭配「通用」端點的應用程式:

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

應用程式範例的程式碼

檢查應用程式範例是否有下列功能:

  • 透過自訂 cookie 重新整理程式 (CookieOidcRefresher.cs) 協助的自動非互動式權杖重新整理。
  • 伺服器專案會呼叫 AddAuthenticationStateSerialization ,以新增伺服器端驗證狀態提供者,以用來 PersistentComponentState 將驗證狀態流向用戶端。 用戶端會呼叫 AddAuthenticationStateDeserialization 來還原串行化,並使用伺服器所傳遞的驗證狀態。 該驗證狀態已針對 WebAssembly 應用程式的存留期修正。
  • Program 檔案 (Program.cs) 中的最小 API 端點 (/weather-forecast) 會處理 Blazor Web App 的天氣資料範例要求。 端點需要藉由呼叫 RequireAuthorization 來進行授權。 針對您新增至專案的任何控制器,請將 [Authorize] 屬性 新增至控制器或動作。
  • 這個應用程式在伺服器專案安全呼叫 (web) API 取得天氣資料:
    • 在伺服器轉譯 Weather 元件時,元件會使用伺服器上的 ServerWeatherForecaster 直接取得天氣資料 (而不是透過 Web API 呼叫)。
    • 在用戶端轉譯元件時,元件會使用 ClientWeatherForecaster 服務實作,它會使用預先設定的 HttpClient (位於用戶端專案的 Program 檔案) 對伺服器專案進行 Web API 呼叫。 伺服器專案 Program 檔案定義的最小 API 端點 (/weather-forecast),會從 ServerWeatherForecaster 取得天氣資料,並將資料傳回用戶端。
  • 透過自訂 cookie 重新整理程式 (CookieOidcRefresher.cs) 協助的自動非互動式權杖重新整理。
  • PersistingAuthenticationStateProvider 類別 (PersistingAuthenticationStateProvider.cs) 是伺服器端 AuthenticationStateProvider,使用 PersistentComponentState 將驗證狀態流向用戶端,接著針對 WebAssembly 應用程式的存留期加以修正。
  • Program 檔案 (Program.cs) 中的最小 API 端點 (/weather-forecast) 會處理 Blazor Web App 的天氣資料範例要求。 端點需要藉由呼叫 RequireAuthorization 來進行授權。 針對您新增至專案的任何控制器,請將 [Authorize] 屬性 新增至控制器或動作。
  • 這個應用程式在伺服器專案安全呼叫 (web) API 取得天氣資料:
    • 在伺服器轉譯 Weather 元件時,元件會使用伺服器上的 ServerWeatherForecaster 直接取得天氣資料 (而不是透過 Web API 呼叫)。
    • 在用戶端轉譯元件時,元件會使用 ClientWeatherForecaster 服務實作,它會使用預先設定的 HttpClient (位於用戶端專案的 Program 檔案) 對伺服器專案進行 Web API 呼叫。 伺服器專案 Program 檔案定義的最小 API 端點 (/weather-forecast),會從 ServerWeatherForecaster 取得天氣資料,並將資料傳回用戶端。

如需在 Blazor Web App使用服務抽象概念的 (web) API 呼叫詳細資訊,請參閱 從 ASP.NET Core Blazor 應用程式呼叫 Web API

Blazor Web App 用戶端專案 (BlazorWebAppOidc.Client

BlazorWebAppOidc.Client 專案是 Blazor Web App的用戶端專案。

用戶端會呼叫 AddAuthenticationStateDeserialization 來還原串行化,並使用伺服器所傳遞的驗證狀態。 該驗證狀態已針對 WebAssembly 應用程式的存留期修正。

PersistentAuthenticationStateProvider 類別 (PersistentAuthenticationStateProvider.cs) 是用戶端 AuthenticationStateProvider,藉由尋找在伺服器上轉譯時保存在頁面中的資料,判斷使用者的驗證狀態。 該驗證狀態已針對 WebAssembly 應用程式的存留期修正。

如果使用者需要登入或登出,則需要完整頁面重新載入。

應用程式範例提供使用者名稱和電子郵件僅供顯示之用。 不包含在提出後續要求時向伺服器驗證的權杖,而且是透過使用對伺服器提出之 HttpClient 要求中包含的 cookie 個別運作。

這個版本的發行項包含採用前端的後端 (BFF) 模式實作 OIDC。 如果應用程式的規格不要求採用 BFF 模式,請將發行項版本選取器變更為不使用 BFF 的 OIDC 模式

涵蓋下列規格:

  • Blazor Web App 使用 自動轉譯模式搭配全域互動功能
  • 伺服器和用戶端應用程式使用自訂驗證狀態提供者服務擷取使用者的驗證狀態,並在伺服器與客戶端之間流動。
  • 這個應用程式是任何 OIDC 驗證流程的起點。 OIDC 在應用程式手動設定,且不採用 Microsoft Entra IDMicrosoft Identity Web 套件,應用程式範例也不需要 Microsoft Azure 裝載。 不過,應用程式範例可與 Entra、Microsoft Identity Web 搭配使用,並且裝載於 Azure。
  • 自動非互動式權杖重新整理。
  • 採用前端的後端 (BFF) 模式,針對服務探索使用 .NET Aspire,而針對求在後端應用程式對天氣預報端點提出通過 Proxy 處理要求則是使用 YARP
    • 後端 Web API 使用 JWT 持有人驗證,驗證登入 cookie中 Blazor Web App 所儲存的 JWT 權杖。
    • Aspire 可改善建置 .NET 雲端原生應用程式的體驗。 它提供一組一致固定的工具和模式,用於建置和執行分散式應用程式。
    • YARP (又一個反向 Proxy) 是用來建立反向 Proxy 伺服器的程式庫。

如需 .NET Aspire 的詳細資訊,請參閱 .NET Aspire 正式發行:簡化 .NET 雲端原生開發(2024 年 5 月)

先決條件

.NET Aspire 需要 Visual Studio 17.10 版或更新版本。

範例應用程式

這個應用程式範例包含五個專案:

  • .NET Aspire:
    • Aspire.AppHost:用來管理應用程式的高階協調流程疑慮。
    • Aspire.ServiceDefaults:包含預設的 .NET Aspire 應用程式設定,該設定可視需要加以擴充及自訂。
  • MinimalApiJwt:後端 Web API,包含天氣資料的最小 API 端點範例。
  • BlazorWebAppOidc: Blazor Web App的伺服器端專案。
  • BlazorWebAppOidc.Client: Blazor Web App的用戶端專案。

請使用下列連結,透過存放庫根目錄中的最新版本資料夾存取應用程式範例。 專案位於 .NET 8 或更新版本的 BlazorWebAppOidcBff 資料夾。

檢視或下載範例程式碼 \(英文\) (如何下載)

.NET Aspire 個專案

如需有關使用 .NET Aspire 的詳細資訊,以及應用程式範例 .AppHost.ServiceDefaults 專案的詳細資料,請參閱 .NET Aspire 文件

確認您已符合 .NET Aspire 的必要條件。 如需詳細資訊,請參閱快速入門必要條件一節:建置您的第一個 .NET Aspire 應用程式

範例應用程式只會設定不安全的 HTTP 啟動設定檔 (http),以在開發測試期間使用。 如需詳細資訊,包括不安全且安全的啟動設定設定檔範例,請參閱允許 .NET Aspire 中不安全的傳輸(.NET Aspire 文件)

伺服器端 Blazor Web App 專案 (BlazorWebAppOidc)

BlazorWebAppOidc 專案是 Blazor Web App的伺服器端專案。 專案會使用 YARP,將要求通過 Proxy 處理至後端 Web API 專案 (MinimalApiJwt) 中的氣象預報端點,並將 access_token 儲存於驗證 cookie 中。

BlazorWebAppOidc.http 檔案可用於測試天氣資料要求。 請注意,BlazorWebAppOidc 專案必須執行才能測試端點,而且端點會硬式編碼到檔案中。 如需詳細資訊,請參閱在 Visual Studio 2022 中使用 .http 檔案

注意

伺服器專案會使用 IHttpContextAccessor/HttpContext,但絕不會用於互動式轉譯的元件。 如需詳細資訊,請參閱 ASP.NET Core Blazor 互動式伺服器端轉譯的威脅風險降低指導

組態

本節說明如何設定應用程式範例。

注意

針對 Microsoft Entra ID 或 Azure AD B2C,您可以從 Microsoft Identity Web 使用AddMicrosoftIdentityWebAppMicrosoft.Identity.WebNuGet 套件API 檔),這會將 OIDC 和Cookie驗證處理程式新增為適當的預設值。 本節中的應用程式範例和指導不使用 Microsoft Identity Web。 這份指導示範如何為任何 OIDC 提供者手動設定 OIDC 處理常式。 如需實作 Microsoft Identity Web 的詳細資訊,請參閱連結的資源。

建立客戶端密碼

警告

請勿在用戶端程式代碼中儲存應用程式密碼、連接字串、認證、密碼、個人標識元(PIN)、私人 C#/.NET 程式代碼或私鑰/令牌,這一律不安全。 在測試/預備和生產環境中,伺服器端 Blazor 程序代碼和 Web API 應該使用安全驗證流程,以避免在專案程式代碼或組態檔內維護認證。 在本機開發測試之外,建議您避免使用環境變數來儲存敏感數據,因為環境變數不是最安全的方法。 針對本機開發測試, 建議使用秘密管理員工具 來保護敏感數據。 如需詳細資訊,請參閱 安全地維護敏感數據和認證

若要進行本機開發測試,請使用 秘密管理員工具 ,將伺服器應用程式的用戶端密碼儲存在組態密鑰 Authentication:Schemes:MicrosoftOidc:ClientSecret之下。

注意

如果應用程式使用 Microsoft Entra ID 或 Azure AD B2C,請在 Entra 或 Azure 入口網站 中的應用程式註冊中建立用戶端密碼(管理>憑證和秘密>新用戶端密碼)。 在下列指引中使用新秘密的值

尚未 初始化秘密管理員工具的範例應用程式 。 使用命令殼層,例如 Visual Studio 中的開發人員 PowerShell 命令殼層,執行下列命令。 在執行命令之前,請將 目錄與 cd 命令變更為伺服器項目的目錄。 命令會建立使用者密碼識別碼(<UserSecretsId> 在伺服器應用程式的項目檔中):

dotnet user-secrets init

執行下列命令來設定客戶端密碼。 佔 {SECRET} 位元是從應用程式註冊取得的客戶端密碼:

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

如果使用 Visual Studio,您可以用滑鼠右鍵按兩下 方案總管 中的伺服器專案,然後選取 [管理用戶密碼],以確認密碼已設定。

設定應用程式

呼叫 AddOpenIdConnect 時,在專案的 Program 檔案找到下列 OpenIdConnectOptions設定:

  • SignInScheme:設定對應到中介軟體的驗證配置,此中介軟體在成功驗證後負責保存使用者的 identity 。 OIDC 處理常式必須使用能夠跨要求保存使用者認證的登入配置。 下方這一行字僅供示範之用。 如果省略,則會使用 DefaultSignInScheme 做為備用值。

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • openidprofile (Scope) 的範圍 (選擇性):預設也會設定 openidprofile 範圍,因為 OIDC 處理常式需要它們才能運作,但如果 Authentication:Schemes:MicrosoftOidc:Scope 設定包含範圍,則可能必須重新新增這些範圍。 如需一般設定指導,請參閱 ASP.NET Core 中的設定ASP.NET Core Blazor 設定

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens:定義了在成功授權之後,是否應該將存取和重新整理權杖儲存在 AuthenticationProperties 中。 值設定為 true,以驗證來自後端 Web API 專案 (MinimalApiJwt) 的天氣資料要求。

    oidcOptions.SaveTokens = true;
    
  • 離線存取的範圍 (Scope):重新整理權杖需要 offline_access 範圍。

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • 從 Web API (Scope) 取得天氣資料的範圍:Weather.Get 範圍是在 Azure 或 Entra 入口網站的公開 API 下方設定。 後端 Web API 專案 (MinimalApiJwt) 必須執行此動作,才能使用持有人 JWT 驗證存取權杖。

    oidcOptions.Scope.Add("{APP ID URI}/{API NAME}");
    

    範例:

    • 應用程式識別碼 URI ({APP ID URI}):https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
      • 目錄名稱 ({DIRECTORY NAME}):contoso
      • 應用程式 (用戶端) 識別碼 ({CLIENT ID}):00001111-aaaa-2222-bbbb-3333cccc4444
    • 針對來自 MinimalApiJwt ({API NAME}) 之天氣資料所設定的範圍:Weather.Get
    oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444/Weather.Get");
    

    上述範例是關於使用 AAD B2C 租用戶類型在租用戶註冊的應用程式。 如果應用程式已在 ME-ID 租用戶註冊,則 App ID URI 不同,因此範圍不同。

    範例:

    • App ID URI ({APP ID URI}):api://{CLIENT ID} 有應用程式 (用戶端) 識別碼 ({CLIENT ID}):00001111-aaaa-2222-bbbb-3333cccc4444
    • 針對來自 MinimalApiJwt ({API NAME}) 之天氣資料所設定的範圍:Weather.Get
    oidcOptions.Scope.Add("api://00001111-aaaa-2222-bbbb-3333cccc4444/Weather.Get");
    
  • AuthorityClientId:設定 OIDC 呼叫的授權單位和用戶端識別碼。

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    範例:

    • 授權單位 ({AUTHORITY}):https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ (使用租用戶標識碼 aaaabbbb-0000-cccc-1111-dddd2222eeee)
    • 用戶端識別碼 ({CLIENT ID}):00001111-aaaa-2222-bbbb-3333cccc4444
    oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
    

    Microsoft Azure「通用」授權單位的範例:

    「通用」授權單位應該用於多租用戶應用程式。 您也可以針對單一租用戶應用程式使用「通用」授權單位,但需要有自訂的 IssuerValidator,如本節稍後所示。

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ResponseType:將 OIDC 處理常式設定為只執行授權碼流程。 在這個模式中,不需要隱含授與和混合式流程。

    在 Entra 或 Azure 入口網站的隱含授與和混合式流程應用程式註冊設定中,請勿選取授權端點的核取方塊,以傳回 存取權杖識別碼權杖。 OIDC 處理常式使用從授權端點傳回的程式碼,自動要求適當的權杖。

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaimsNameClaimTypeRoleClaimType 的設定:許多 OIDC 伺服器在 ClaimTypes 使用 “name” 和 “role”,而不是使用 SOAP/WS-Fed 預設值。 MapInboundClaims 設定為 false 時,處理常式不會執行宣告對應,而且應用程式會直接使用 JWT 的宣告名稱。 下列範例會將角色宣告類型設定為「roles」,這適用於 Microsoft Entra ID (ME-ID)。 請參閱 identity 提供者的文件以取得詳細資訊。

    注意

    針對多數 OIDC 提供者,MapInboundClaims 必須設定為 false,以防重新命名宣告。

    oidcOptions.MapInboundClaims = false;
    oidcOptions.TokenValidationParameters.NameClaimType = "name";
    oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
    
  • 路徑設定:路徑必須符合向 OIDC 提供者註冊應用程式時設定的重新導向 URI (登入回呼路徑),以及登出後重新導向 (登出回呼路徑)。 在 Azure 入口網站,路徑是在應用程式註冊的驗證刀鋒視窗設定。 登入和登出路徑都必須註冊為重新導向 URI。 預設值是 /signin-oidc/signout-callback-oidc

    • CallbackPath:應用程式基本路徑中傳回 user-agent 的要求路徑。

      在 Entra 或 Azure 入口網站,設定 Web 平台設定之重新導向 URI 的路徑:

      https://localhost/signin-oidc

      注意

      localhost 位址不需要連接埠。

    • SignedOutCallbackPath:應用程式基本路徑中的要求路徑,在應用程式基本路徑中,於登出 identity 提供者後,傳回使用者代理程式。

      在 Entra 或 Azure 入口網站,設定 Web 平台設定之重新導向 URI 的路徑:

      https://localhost/signout-callback-oidc

      注意

      localhost 位址不需要連接埠。

      注意

      如果使用 Microsoft Identity Web,則提供者目前只會在使用 microsoftonline.com 授權單位 (https://login.microsoftonline.com/{TENANT ID}/v2.0/) 時重新導向回 SignedOutCallbackPath。 如果您可以搭配 Microsoft Identity Web 使用「通用」授權單位,則不存在這項限制。 如需詳細資訊,請參閱授權單位 url 包含租用戶識別碼 (AzureAD/microsoft-authentication-library-for-js #5783) 時 postLogoutRedirectUri 無法運作

    • RemoteSignOutPath:在這個路徑收到的要求導致處理常式使用登出配置叫用登出。

      在 Entra 或 Azure 入口網站,設定 Front-channel 登出 URL

      https://localhost/signout-oidc

      注意

      localhost 位址不需要連接埠。

      oidcOptions.CallbackPath = new PathString("{PATH}");
      oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
      oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
      

      範例 (預設值):

      oidcOptions.CallbackPath = new PathString("/signin-oidc");
      oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
      oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
      
  • (Microsoft Azure 僅使用「通用」端點) TokenValidationParameters.IssuerValidator:許多 OIDC 提供者會使用預設憑證簽發者驗證程式,但我們必須考慮以 https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration 傳回之租用戶標識碼 ({TENANT ID}) 參數化的憑證簽發者。 如需詳細資訊,請參閱 使用 OpenID Connect 與 Azure AD「通用」端點 (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731) 的 SecurityTokenInvalidIssuerException

    僅適用於使用 Microsoft Entra ID 或 Azure AD B2C 搭配「通用」端點的應用程式:

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

應用程式範例的程式碼

檢查應用程式範例是否有下列功能:

  • 透過自訂 cookie 重新整理程式 (CookieOidcRefresher.cs) 協助的自動非互動式權杖重新整理。
  • 伺服器專案會呼叫 AddAuthenticationStateSerialization ,以新增伺服器端驗證狀態提供者,以用來 PersistentComponentState 將驗證狀態流向用戶端。 用戶端會呼叫 AddAuthenticationStateDeserialization 來還原串行化,並使用伺服器所傳遞的驗證狀態。 該驗證狀態已針對 WebAssembly 應用程式的存留期修正。
  • 對 Blazor Web App 的要求會由 Proxy 處理至後端 Web API 專案 (MinimalApiJwt)。 Program 檔案中的 MapForwarder 使用傳出要求的預設設定、自訂的轉換和預設 HTTP 用戶端,將符合指定模式的 HTTP 要求直接轉送至特定目的地:
    • 在伺服器轉譯 Weather 元件時,元件使用 ServerWeatherForecaster 通過 Proxy 處理天氣資料的要求與使用者的存取權杖。
    • 在用戶端轉譯元件時,元件會使用 ClientWeatherForecaster 服務實作,它會使用預先設定的 HttpClient (位於用戶端專案的 Program 檔案) 對伺服器專案進行 Web API 呼叫。 伺服器專案 Program 檔案中定義的最小 API 端點 (/weather-forecast),使用使用者的存取權杖轉換要求,取得天氣資料。
  • 透過自訂 cookie 重新整理程式 (CookieOidcRefresher.cs) 協助的自動非互動式權杖重新整理。
  • PersistingAuthenticationStateProvider 類別 (PersistingAuthenticationStateProvider.cs) 是伺服器端 AuthenticationStateProvider,使用 PersistentComponentState 將驗證狀態流向用戶端,接著針對 WebAssembly 應用程式的存留期加以修正。
  • 對 Blazor Web App 的要求會由 Proxy 處理至後端 Web API 專案 (MinimalApiJwt)。 Program 檔案中的 MapForwarder 使用傳出要求的預設設定、自訂的轉換和預設 HTTP 用戶端,將符合指定模式的 HTTP 要求直接轉送至特定目的地:
    • 在伺服器轉譯 Weather 元件時,元件使用 ServerWeatherForecaster 通過 Proxy 處理天氣資料的要求與使用者的存取權杖。
    • 在用戶端轉譯元件時,元件會使用 ClientWeatherForecaster 服務實作,它會使用預先設定的 HttpClient (位於用戶端專案的 Program 檔案) 對伺服器專案進行 Web API 呼叫。 伺服器專案 Program 檔案中定義的最小 API 端點 (/weather-forecast),使用使用者的存取權杖轉換要求,取得天氣資料。

如需在 Blazor Web App使用服務抽象概念的 (web) API 呼叫詳細資訊,請參閱 從 ASP.NET Core Blazor 應用程式呼叫 Web API

Blazor Web App 用戶端專案 (BlazorWebAppOidc.Client

BlazorWebAppOidc.Client 專案是 Blazor Web App的用戶端專案。

用戶端會呼叫 AddAuthenticationStateDeserialization 來還原串行化,並使用伺服器所傳遞的驗證狀態。 該驗證狀態已針對 WebAssembly 應用程式的存留期修正。

PersistentAuthenticationStateProvider 類別 (PersistentAuthenticationStateProvider.cs) 是用戶端 AuthenticationStateProvider,藉由尋找在伺服器上轉譯時保存在頁面中的資料,判斷使用者的驗證狀態。 該驗證狀態已針對 WebAssembly 應用程式的存留期修正。

如果使用者需要登入或登出,則需要完整頁面重新載入。

應用程式範例提供使用者名稱和電子郵件僅供顯示之用。 不包含在提出後續要求時向伺服器驗證的權杖,而且是透過使用對伺服器提出之 HttpClient 要求中包含的 cookie 個別運作。

後端 Web API 專案 (MinimalApiJwt)

MinimalApiJwt 專案是多個前端專案的後端 Web API。 專案會為天氣資料設定最小 API 端點。 來自 Blazor Web App 伺服器端專案 (BlazorWebAppOidc) 的要求會通過 Proxy 處理至 MinimalApiJwt 專案。

組態

在專案的 Program 檔案中,於 AddJwtBearer 呼叫的 JwtBearerOptions 設定專案:

  • Audience:設定任何已接收 OpenID Connect 權杖的受眾。

    在 Azure 或 Entra 入口網站:將值與在 [公開 API] 下方新增 Weather.Get 範圍時所設定之應用程式識別碼 URI 的路徑比對:

    jwtOptions.Audience = "{APP ID URI}";
    

    範例:

    應用程式識別碼 URI ({APP ID URI}):https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}

    • 目錄名稱 ({DIRECTORY NAME}):contoso
    • 應用程式 (用戶端) 識別碼 ({CLIENT ID}):00001111-aaaa-2222-bbbb-3333cccc4444
    jwtOptions.Audience = "https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444";
    

    上述範例是關於使用 AAD B2C 租用戶類型在租用戶註冊的應用程式。 如果應用程式已在 ME-ID 租用戶註冊,則 App ID URI 不同,因此受眾不同。

    範例:

    App ID URI ({APP ID URI}):api://{CLIENT ID} 有應用程式 (用戶端) 識別碼 ({CLIENT ID}):00001111-aaaa-2222-bbbb-3333cccc4444

    jwtOptions.Audience = "api://00001111-aaaa-2222-bbbb-3333cccc4444";
    
  • Authority:設定進行 OpenID Connect 呼叫的授權單位。 將值與 BlazorWebAppOidc/Program.cs 中為 OIDC 處理常式設定的授權單位比對:

    jwtOptions.Authority = "{AUTHORITY}";
    

    範例:

    授權單位 ({AUTHORITY}):https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ (使用租用戶標識碼 aaaabbbb-0000-cccc-1111-dddd2222eeee)

    jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    

    上述範例是關於使用 AAD B2C 租用戶類型在租用戶註冊的應用程式。 如果應用程式已在 ME-ID 租用戶註冊,授權單位應該與 identity 提供者所傳回之 JWT 憑證簽發者(iss)相符:

    jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
    

天氣資料的最小 API

保護專案 Program 檔案中的天氣預報資料端點:

app.MapGet("/weather-forecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
}).RequireAuthorization();

RequireAuthorization 擴充方法需要路由定義的授權。 針對您新增至專案的任何控制器,請將 [Authorize] 屬性 新增至控制器或動作。

登出時重新導向至 home 分頁

使用者瀏覽應用程式時,LogInOrOut 元件 (Layout/LogInOrOut.razor) 會將傳回 URL (ReturnUrl) 的隱藏欄位設定為目前 URL (currentURL) 的值。 使用者登出應用程式時, identity 提供者會讓他們返回登出時的頁面。

如果使用者從安全頁面登出,則只有在登出後,才會透過驗證流程返回相同的安全頁面。 使用者需要經常切換帳戶時,這個行為完全沒問題。 不過,替代的應用程式規格可能會要求使用者,在登出後返回應用程式的 home 分頁或其他分頁。 下列範例顯示如何將應用程式的 home 分頁設定為登出作業的返回 URL。

下列範例示範 LogInOrOut 元件的重要變更。 不需要提供設為頁面/的home隱藏字段ReturnUrl,因為這是預設路徑。 已不再實作 IDisposable。 已不再插入 NavigationManager。 已移除整個 @code 區塊。

Layout/LogInOrOut.razor

@using Microsoft.AspNetCore.Authorization

<div class="nav-item px-3">
    <AuthorizeView>
        <Authorized>
            <form action="authentication/logout" method="post">
                <AntiforgeryToken />
                <button type="submit" class="nav-link">
                    <span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
                    </span> Logout @context.User.Identity?.Name
                </button>
            </form>
        </Authorized>
        <NotAuthorized>
            <a class="nav-link" href="authentication/login">
                <span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span> 
                Login
            </a>
        </NotAuthorized>
    </AuthorizeView>
</div>

密碼編譯 nonce

nonce 是字串值,將用戶端的工作階段與識別碼權杖產生關聯,以緩和重新執行攻擊

如果您在驗證開發和測試期間收到 nonce 錯誤,無論對應用程式或測試使用者所做的變更有多小,都請針對每個測試回合使用新的 InPrivate/無痕瀏覽模式瀏覽器工作階段,因為過時的 cookie 資料可能導致 nonce 錯誤。 如需詳細資訊,請參閱 Cookie 與網站資料 一節。

重新整理權杖換取新的存取權杖時,不需要也不會使用 nonce。 在應用程式範例中,CookieOidcRefresher (CookieOidcRefresher.cs) 刻意將 OpenIdConnectProtocolValidator.RequireNonce 設定為 false

未向 Microsoft Entra(ME-ID) 註冊之應用程式的應用程式角色

本章節與未使用 Microsoft Entra ID (ME-ID) 作為 identity 提供者的應用程式有關。 如需使用 ME-ID 註冊的應用程式,請參閱 使用 Microsoft Entra(ME-ID)註冊的應用程式角色 章節。

Program.csOpenIdConnectOptions 中設定角色宣告類型 (TokenValidationParameters.RoleClaimType) :

oidcOptions.TokenValidationParameters.RoleClaimType = "{ROLE CLAIM TYPE}";

對許多 OIDC identity 提供者而言,角色宣告類型為 role。 請檢查您的 identity 提供者文件,以取得正確值。

BlazorWebAppOidc.Client 專案的 UserInfo 類別取代為下列類別。

UserInfo.cs

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;

namespace BlazorWebAppOidc.Client;

// Add properties to this class and update the server and client 
// AuthenticationStateProviders to expose more information about 
// the authenticated user to the client.
public sealed class UserInfo
{
    public required string UserId { get; init; }
    public required string Name { get; init; }
    public required string[] Roles { get; init; }

    public const string UserIdClaimType = "sub";
    public const string NameClaimType = "name";
    private const string RoleClaimType = "role";

    public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
        new()
        {
            UserId = GetRequiredClaim(principal, UserIdClaimType),
            Name = GetRequiredClaim(principal, NameClaimType),
            Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
                .ToArray(),
        };

    public ClaimsPrincipal ToClaimsPrincipal() =>
        new(new ClaimsIdentity(
            Roles.Select(role => new Claim(RoleClaimType, role))
                .Concat([
                    new Claim(UserIdClaimType, UserId),
                    new Claim(NameClaimType, Name),
                ]),
            authenticationType: nameof(UserInfo),
            nameType: NameClaimType,
            roleType: RoleClaimType));

    private static string GetRequiredClaim(ClaimsPrincipal principal,
        string claimType) =>
            principal.FindFirst(claimType)?.Value ??
            throw new InvalidOperationException(
                $"Could not find required '{claimType}' claim.");
}

此時, Razor 元件可以採用 角色型和原則型授權。 應用程式角色會出現在 role 宣告中,每一個角色一個宣告。

向 Microsoft Entra(ME-ID)註冊之應用程式的應用程式角色

使用本章節的指導,針對使用 Microsoft Entra ID (ME-ID) 的應用程式實作應用程式角色、ME-ID 安全群組和 ME-ID 內建系統管理員角色。

本節所述的方法會設定 ME-ID,以在驗證 cookie 標題中傳送群組和角色。 當使用者只是少數安全群組和角色的成員時,下列方法應該適用於大部分裝載平台,而不會發生標題太長的問題,例如,預設標題長度限制為 16 KB 的 IIS 裝載。(MaxRequestBytes) 如果標題長度因群組或角色成員資格較高而造成問題,建議您不要遵循本節中的指導,而是實作 Microsoft Graph,以分別從 ME-ID 取得使用者的群組和角色,此方法不會擴大驗證 cookie 的大小。 如需詳細資訊,請參閱 錯誤要求 - 要求太長 - IIS 伺服器 (dotnet/aspnetcore #57545)

Program.csOpenIdConnectOptions 設定角色宣告類型 (TokenValidationParameters.RoleClaimType) 。 將值設定為 roles

oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

雖然若沒有 ME-ID Premium 帳戶,您無法 將角色指派給群組 ,但您可以將角色指派給使用者,並使用標準 Azure 帳戶接收使用者的角色宣告。 本節中的指引不需要 ME-ID 進階帳戶。

使用預設目錄時,請依照指導將應用程式角色新增至應用程式,在權杖 (ME-ID 文件) 中接收這些角色,並設定和指派角色。 如果您未使用預設目錄,請在 Azure 入口網站 中編輯應用程式的資訊清單,以在資訊清單檔的 appRoles 輸入中,手動建立應用程式的角色。 有關詳細資訊,請參閱 設定角色宣告(ME-ID 文件)。

使用者的 Azure 安全群組抵達 groups 宣告,而使用者的內建 ME-ID 系統管理員角色指派抵達 已知的 ID(wids) 宣告。 這兩個宣告類型的值都是 GUID。 當應用程式收到時,這些宣告可用來建立 角色和原則授權在 Razor 元件中

在 Azure 入口網站應用程式資訊清單中,將 groupMembershipClaims 屬性 設定為 All。 值 All 會導致 ME-ID 傳送登入使用者的所有安全性/通訊群組(groups 宣告)以及角色(wids 宣告): 設定 groupMembershipClaims 屬性:

  1. 開啟 Azure 入口網站應用程式中的註冊。
  2. 選取資訊看板中的 [管理]>[資訊清單]
  3. 尋找 groupMembershipClaims 屬性。
  4. 將值設定為 All ("groupMembershipClaims": "All")。
  5. 選取 [儲存] 按鈕。

BlazorWebAppOidc.Client 專案的 UserInfo 類別取代為下列類別。

UserInfo.cs

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;

namespace BlazorWebAppOidc.Client;

// Add properties to this class and update the server and client 
// AuthenticationStateProviders to expose more information about 
// the authenticated user to the client.
public sealed class UserInfo
{
    public required string UserId { get; init; }
    public required string Name { get; init; }
    public required string[] Roles { get; init; }
    public required string[] Groups { get; init; }
    public required string[] Wids { get; init; }

    public const string UserIdClaimType = "sub";
    public const string NameClaimType = "name";
    private const string RoleClaimType = "roles";
    private const string GroupsClaimType = "groups";
    private const string WidsClaimType = "wids";

    public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
        new()
        {
            UserId = GetRequiredClaim(principal, UserIdClaimType),
            Name = GetRequiredClaim(principal, NameClaimType),
            Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
                .ToArray(),
            Groups = principal.FindAll(GroupsClaimType).Select(c => c.Value)
                .ToArray(),
            Wids = principal.FindAll(WidsClaimType).Select(c => c.Value)
                .ToArray(),
        };

    public ClaimsPrincipal ToClaimsPrincipal() =>
        new(new ClaimsIdentity(
            Roles.Select(role => new Claim(RoleClaimType, role))
                .Concat(Groups.Select(role => new Claim(GroupsClaimType, role)))
                .Concat(Wids.Select(role => new Claim(WidsClaimType, role)))
                .Concat([
                    new Claim(UserIdClaimType, UserId),
                    new Claim(NameClaimType, Name),
                ]),
            authenticationType: nameof(UserInfo),
            nameType: NameClaimType,
            roleType: RoleClaimType));

    private static string GetRequiredClaim(ClaimsPrincipal principal,
        string claimType) =>
            principal.FindFirst(claimType)?.Value ??
            throw new InvalidOperationException(
                $"Could not find required '{claimType}' claim.");
}

此時, Razor 元件可以採用 角色型和原則型授權

  • 應用程式角色會出現在 roles 宣告中 ,每一個角色一個宣告。
  • 安全群組會出現在 groups 宣告中,每一個群組一個宣告。 當建立安全群組時,安全群組 GUID 會出現在 Azure 入口網站,並在選取 Identity>概觀>群組>檢視表
  • 內建 ME-ID 系統管理員角色會出現在 wids 宣告中,每一個角色一個宣告。 wids 宣告具有值 b79fbf4d-3ef9-4689-8143-76b194e85509 一律由租用戶的非來賓帳戶 ME-ID 傳送,且不會參考系統管理員角色。 選取 角色與系統管理員時,系統管理員角色 GUID(角色範本 ID)會出現在 Azure 入口網站中,後面接著省略符號(...) >所列角色的描述 。 角色範本 ID 也會列在 Microsoft Entra 內建角色中(Entra 文件)

疑難排解

記錄

伺服器應用程式是標準 ASP.NET Core 應用程式。 請參閱 ASP.NET Core 記錄指導,在伺服器應用程式啟用較低的記錄層級。

若要啟用 Blazor WebAssembly 驗證的偵錯或追蹤記錄,請參閱 ASP.NET Core Blazor 記錄用戶端驗證記錄一節,並將發行項版本選取器設定為 ASP.NET Core 7.0 或更新版本。

常見錯誤

  • 應用程式或 Identity 提供者 (IP) 的設定錯誤

    最常見的錯誤是由不正確的設定所造成。 以下是一些範例:

    • 視案例的需求而定,遺漏或不正確的授權單位、執行個體、租用戶識別碼、租用戶網域、用戶端識別碼或重新導向 URI 會防止應用程式驗證用戶端。
    • 不正確的要求範圍會防止用戶端存取伺服器 Web API 端點。
    • 不正確或遺漏伺服器 API 權限會防止用戶端存取伺服器 Web API 端點。
    • 在與 IP 應用程式註冊的重新導 URI 中設定的連接埠不同的連接埠上執行應用程式。 請注意,Microsoft Entra ID 和在 localhost 開發測試位址執行的應用程式不需要連接埠,但應用程式的連接埠設定和執行應用程式的連接埠必須與非 localhost 位址相符。

    本文涵蓋的設定,顯示正確設定的範例。 請仔細查看設定,確定應用程式和 IP 是否設定錯誤。

    如果設定顯示正確:

    • 分析應用程式記錄檔。

    • 使用瀏覽器的開發人員工具,檢查用戶端應用程式與 IP 或伺服器應用程式之間的網路流量。 通常,在提出要求之後,IP 或伺服器應用程式會傳回錯誤訊息或有導致問題的線索訊息給用戶端。 下列文章中可找到開發人員工具指導:

    文件小組會回應文章中的文件意見反應和 BUG (從此頁面意見反應區段開啟問題),但是無法提供產品支援。 有數個公用支援論壇可用來協助針對應用程式進行疑難排解。 我們建議下列事項:

    上述論壇並非由 Microsoft 擁有或控制。

    針對非安全性、非敏感性和非機密可重現架構 BUG 報告,向 ASP.NET Core 產品單位提出問題。 在您徹底調查問題的原因而且無法自行解決,並取得公用支援論壇上社群的協助之前,請勿向產品單位提出問題。 產品單位無法針對因簡單設定錯誤或涉及第三方服務的使用案例而中斷的個別應用程式進行疑難排解。 如果報告具有敏感性或機密性質,或描述了攻擊者可能惡意探索的產品中潛在的安全性缺陷,請參閱 報告安全性問題和 BUG (dotnet/aspnetcore GitHub 存放庫)

  • ME-ID 未經授權的用戶端

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. 不符合以下需求: DenyAnonymousAuthorizationRequirement:需要已驗證的使用者。

    ME-ID 的登入回呼錯誤:

    • 錯誤: unauthorized_client
    • 描述:AADB2C90058: The provided application is not configured to allow public clients.

    若要解決此錯誤:

    1. 在 Azure 入口網站中,存取應用程式的資訊清單
    2. allowPublicClient 屬性設定為 nulltrue

Cookie 和網站資料

Cookie 和網站資料可以在應用程式更新之間保存,並可介入測試和疑難排解。 進行應用程式程式碼變更、使用提供者的使用者帳戶變更,或提供者應用程式設定變更時,請清除下列內容:

  • 使用者登入 Cookie
  • 應用程式 Cookie
  • 快取和儲存的網站資料

防止徘徊的 cookie 和網站資料不會因使用測試和疑難排解而介入的一種方法是:

  • 設定瀏覽器
    • 使用瀏覽器進行測試,您可以設定在每次關閉瀏覽器時刪除所有 cookie 和網站資料。
    • 請確定瀏覽器已手動關閉或由 IDE 關閉,以便對應用程式、測試使用者或提供者設定進行任何變更。
  • 使用自訂命令,在 Visual Studio 中以私人模式或無痕模式開啟瀏覽器:
    • 從 Visual Studio 的 [執行] 按鈕開啟 [瀏覽方式] 對話方塊。
    • 選取新增按鈕。
    • 在 [程式] 欄位中提供瀏覽器的路徑。 下列可執行檔路徑是 Windows 10 的一般安裝位置。 如果您的瀏覽器安裝在不同的位置,或您不是使用 Windows 10,請提供瀏覽器可執行檔的路徑。
      • Microsoft Edge:C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome:C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox:C:\Program Files\Mozilla Firefox\firefox.exe
    • 在 [引數] 欄位中,提供瀏覽器用來在私人模式或無痕模式中開啟的命令列選項。 某些瀏覽器需要應用程式的 URL。
      • Microsoft Edge:使用 -inprivate
      • Google Chrome:使用 --incognito --new-window {URL},其中 {URL} 預留位置是要開啟的 URL (例如 https://localhost:5001)。
      • Mozilla Firefox:使用 -private -url {URL},其中 {URL} 預留位置是要開啟的 URL (例如 https://localhost:5001)。
    • 在 [自訂名稱] 欄位中提供名稱。 例如: Firefox Auth Testing
    • 選取確定按鈕。
    • 若要避免針對使用應用程式測試的每個反覆項目選取瀏覽器設定檔,請使用 [設為預設值] 按鈕,將設定檔設定為預設值。
    • 請確定瀏覽器已由 IDE 關閉,以便對應用程式、測試使用者或提供者設定進行任何變更。

應用程式升級

在升級開發電腦上的 .NET Core SDK 或變更應用程式內的套件版本之後,正常運作的應用程式便立即發生失敗。 在某些情況下,執行主要升級時,不一致的套件可能會中斷應用程式。 大多數這些問題都可依照下列指示來進行修正:

  1. 從命令殼層執行 dotnet nuget locals all --clear,以清除本機系統的 NuGet 套件快取。
  2. 刪除專案的 binobj 資料夾。
  3. 還原並重建專案。
  4. 在重新部署應用程式之前,請先刪除伺服器上部署資料夾中的所有檔案。

注意

不支援使用與應用程式目標框架不相容的套件版本。 如需套件的詳細資訊,請使用 NuGet 資源庫FuGet 套件總管

執行伺服器應用程式

測試 Blazor Web App並且進行疑難排解時,請確定您是從伺服器專案執行應用程式。

檢查使用者

下列 UserClaims 元件可以直接在應用程式中使用,或作為進一步自訂的基礎。

UserClaims.razor

@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

<PageTitle>User Claims</PageTitle>

<h1>User Claims</h1>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li><b>@claim.Type:</b> @claim.Value</li>
        }
    </ul>
}

@code {
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    [CascadingParameter]
    private Task<AuthenticationState>? AuthState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (AuthState == null)
        {
            return;
        }

        var authState = await AuthState;
        claims = authState.User.Claims;
    }
}

其他資源