--- title: ASP.NET Core Blazor authentication and authorization author: guardrex description: Learn about Blazor authentication and authorization scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: riande ms.custom: mvc ms.date: 02/09/2024 uid: blazor/security/index --- # ASP.NET Core Blazor authentication and authorization [!INCLUDE[](~/includes/not-latest-version.md)] This article describes ASP.NET Core's support for the configuration and management of security in Blazor apps. Security scenarios differ between server-side and client-side Blazor apps. Because a server-side app runs on the server, authorization checks are able to determine: * The UI options presented to a user (for example, which menu entries are available to a user). * Access rules for areas of the app and components. For a client-side app, authorization is *only* used to determine which UI options to show. Since client-side checks can be modified or bypassed by a user, a client-side app can't enforce authorization access rules. :::moniker range=">= aspnetcore-8.0" [Razor Pages authorization conventions](xref:security/authorization/razor-pages-authorization) don't apply to routable Razor components. If a non-routable Razor component is [embedded in a page of a Razor Pages app](xref:blazor/components/integration), the page's authorization conventions indirectly affect the Razor component along with the rest of the page's content. :::moniker-end :::moniker range="< aspnetcore-8.0" [Razor Pages authorization conventions](xref:security/authorization/razor-pages-authorization) don't apply to routable Razor components. If a non-routable Razor component is [embedded in a page of a Razor Pages app](xref:blazor/components/prerendering-and-integration), the page's authorization conventions indirectly affect the Razor component along with the rest of the page's content. :::moniker-end :::moniker range="< aspnetcore-8.0" ASP.NET Core Identity is designed to work in the context of HTTP request and response communication, which generally isn't the Blazor app client-server communication model. ASP.NET Core apps that use ASP.NET Core Identity for user management should use Razor Pages instead of Razor components for Identity-related UI, such as user registration, login, logout, and other user management tasks. Building Razor components that directly handle Identity tasks is possible for several scenarios but isn't recommended or supported by Microsoft. ASP.NET Core abstractions, such as and , aren't supported in Razor components. For more information on using ASP.NET Core Identity with Blazor, see [Scaffold ASP.NET Core Identity into a server-side Blazor app](xref:security/authentication/scaffold-identity#scaffold-identity-into-a-server-side-blazor-app). :::moniker-end > [!NOTE] > The code examples in this article adopt [nullable reference types (NRTs) and .NET compiler null-state static analysis](xref:migration/50-to-60#nullable-reference-types-nrts-and-net-compiler-null-state-static-analysis), which are supported in ASP.NET Core in .NET 6 or later. When targeting ASP.NET Core 5.0 or earlier, remove the null type designation (`?`) from examples in this article. :::moniker range=">= aspnetcore-8.0" ## Antiforgery support The Blazor template adds Antiforgery Middleware and requires endpoint [antiforgery protection](xref:security/anti-request-forgery) by default to mitigate the threats of Cross-Site Request Forgery (CSRF/XSRF). The component renders an antiforgery token as a hidden field, and this component is automatically added to form () instances. For more information, see . The service provides access to an antiforgery token associated with the current session. Inject the service and call its method to obtain the current . For more information, see . Blazor stores request tokens in component state, which guarantees that antiforgery tokens are available to interactive components, even when they don't have access to the request. > [!NOTE] > [Antiforgery mitigation](xref:security/anti-request-forgery) is only required when submitting form data to the server encoded as `application/x-www-form-urlencoded`, `multipart/form-data`, or `text/plain` since these are the [only valid form enctypes](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fs-enctype). For more information, see . :::moniker-end ## Authentication Blazor uses the existing ASP.NET Core authentication mechanisms to establish the user's identity. The exact mechanism depends on how the Blazor app is hosted, server-side or client-side. ### Server-side Blazor authentication Interactively-rendered server-side Blazor operates over a SignalR connection with the client. [Authentication in SignalR-based apps](xref:signalr/authn-and-authz) is handled when the connection is established. Authentication can be based on a cookie or some other bearer token, but authentication is managed via the SignalR hub and entirely within the [circuit](xref:blazor/hosting-models#blazor-server). The built-in service obtains authentication state data from ASP.NET Core's . This is how authentication state integrates with existing ASP.NET Core authentication mechanisms. #### `IHttpContextAccessor`/`HttpContext` in Razor components [!INCLUDE[](~/blazor/security/includes/httpcontext.md)] #### Shared state [!INCLUDE[](~/blazor/security/includes/shared-state.md)] ### Client-side Blazor authentication In client-side Blazor apps, client-side authentication checks can be bypassed because all client-side code can be modified by users. The same is true for all client-side app technologies, including JavaScript SPA frameworks and native apps for any operating system. Add the following: * A package reference for the [`Microsoft.AspNetCore.Components.Authorization`](https://www.nuget.org/packages/Microsoft.AspNetCore.Components.Authorization) NuGet package. [!INCLUDE[](~/includes/package-reference.md)] * The namespace to the app's `_Imports.razor` file. To handle authentication, use of the built-in or custom service is covered in the following sections. For more information, see . ## `AuthenticationStateProvider` service :::moniker range=">= aspnetcore-8.0" is the underlying service used by the component and cascading authentication services to obtain the authentication state for a user. :::moniker-end :::moniker range="< aspnetcore-8.0" is the underlying service used by the component and component to obtain the authentication state for a user. :::moniker-end You don't typically use directly. Use the [`AuthorizeView` component](#authorizeview-component) or [`Task`](#expose-the-authentication-state-as-a-cascading-parameter) approaches described later in this article. The main drawback to using directly is that the component isn't notified automatically if the underlying authentication state data changes. > [!NOTE] > To implement a custom , see . The service can provide the current user's data, as shown in the following example. `ClaimsPrincipalData.razor`: :::moniker range=">= aspnetcore-8.0" ```razor @page "/claims-principle-data" @using System.Security.Claims @inject AuthenticationStateProvider AuthenticationStateProvider

ClaimsPrincipal Data

@authMessage

@if (claims.Count() > 0) {
    @foreach (var claim in claims) {
  • @claim.Type: @claim.Value
  • }
}

@surname

@code { private string? authMessage; private string? surname; private IEnumerable claims = Enumerable.Empty(); private async Task GetClaimsPrincipalData() { var authState = await AuthenticationStateProvider .GetAuthenticationStateAsync(); var user = authState.User; if (user.Identity is not null && user.Identity.IsAuthenticated) { authMessage = $"{user.Identity.Name} is authenticated."; claims = user.Claims; surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value; } else { authMessage = "The user is NOT authenticated."; } } } ``` In the preceding example: * returns the user's claims (`claims`) for display in the UI. * The line that obtains the user's surname (`surname`) calls with a predicate to filter the user's claims. :::moniker-end :::moniker range="< aspnetcore-8.0" ```razor @page "/claims-principle-data" @using System.Security.Claims @inject AuthenticationStateProvider AuthenticationStateProvider

ClaimsPrincipal Data

@authMessage

@if (claims.Count() > 0) {
    @foreach (var claim in claims) {
  • @claim.Type: @claim.Value
  • }
}

@surname

@code { private string? authMessage; private string? surname; private IEnumerable claims = Enumerable.Empty(); private async Task GetClaimsPrincipalData() { var authState = await AuthenticationStateProvider .GetAuthenticationStateAsync(); var user = authState.User; if (user.Identity is not null && user.Identity.IsAuthenticated) { authMessage = $"{user.Identity.Name} is authenticated."; claims = user.Claims; surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value; } else { authMessage = "The user is NOT authenticated."; } } } ``` :::moniker-end If `user.Identity.IsAuthenticated` is `true` and because the user is a , claims can be enumerated and membership in roles evaluated. For more information on dependency injection (DI) and services, see and . For information on how to implement a custom in server-side Blazor apps, see . ## Expose the authentication state as a cascading parameter If authentication state data is required for procedural logic, such as when performing an action triggered by the user, obtain the authentication state data by defining a [cascading parameter](xref:blazor/components/cascading-values-and-parameters) of type `Task<``>`, as the following example demonstrates. `CascadeAuthState.razor`: :::moniker range=">= aspnetcore-8.0" ```razor @page "/cascade-auth-state"

Cascade Auth State

@authMessage

@code { private string authMessage = "The user is NOT authenticated."; [CascadingParameter] private Task? authenticationState { get; set; } protected override async Task OnInitializedAsync() { if (authenticationState is not null) { var authState = await authenticationState; var user = authState?.User; if (user?.Identity is not null && user.Identity.IsAuthenticated) { authMessage = $"{user.Identity.Name} is authenticated."; } } } } ``` :::moniker-end :::moniker range="< aspnetcore-8.0" ```razor @page "/cascade-auth-state"

Cascade Auth State

@authMessage

@code { private string authMessage = "The user is NOT authenticated."; [CascadingParameter] private Task? authenticationState { get; set; } protected override async Task OnInitializedAsync() { if (authenticationState is not null) { var authState = await authenticationState; var user = authState?.User; if (user?.Identity is not null && user.Identity.IsAuthenticated) { authMessage = $"{user.Identity.Name} is authenticated."; } } } } ``` :::moniker-end If `user.Identity.IsAuthenticated` is `true`, claims can be enumerated and membership in roles evaluated. :::moniker range=">= aspnetcore-8.0" Set up the `Task<``>` [cascading parameter](xref:blazor/components/cascading-values-and-parameters) using the and cascading authentication state services. When you create a Blazor app from one of the Blazor project templates with authentication enabled, the app includes the and the call to shown in the following example. A client-side Blazor app includes the required service registrations as well. Additional information is presented in the [Customize unauthorized content with the Router component](#customize-unauthorized-content-with-the-router-component) section. ```razor ... ``` In the `Program` file, register cascading authentication state services: ```csharp builder.Services.AddCascadingAuthenticationState(); ``` :::moniker-end :::moniker range="< aspnetcore-8.0" Set up the `Task<``>` [cascading parameter](xref:blazor/components/cascading-values-and-parameters) using the and components. When you create a Blazor app from one of the Blazor project templates with authentication enabled, the app includes the and components shown in the following example. A client-side Blazor app includes the required service registrations as well. Additional information is presented in the [Customize unauthorized content with the Router component](#customize-unauthorized-content-with-the-router-component) section. ```razor ... ``` :::moniker-end :::moniker range="= aspnetcore-5.0" [!INCLUDE[](~/blazor/includes/prefer-exact-matches.md)] :::moniker-end In a client-side Blazor app, add services for options and authorization to the `Program` file: ```csharp builder.Services.AddOptions(); builder.Services.AddAuthorizationCore(); ``` In a server-side Blazor app, services for options and authorization are already present, so no further steps are required. ## Authorization After a user is authenticated, *authorization* rules are applied to control what the user can do. Access is typically granted or denied based on whether: * A user is authenticated (signed in). * A user is in a *role*. * A user has a *claim*. * A *policy* is satisfied. Each of these concepts is the same as in an ASP.NET Core MVC or Razor Pages app. For more information on ASP.NET Core security, see the articles under [ASP.NET Core Security and Identity](xref:security/index). ## `AuthorizeView` component The component selectively displays UI content depending on whether the user is authorized. This approach is useful when you only need to *display* data for the user and don't need to use the user's identity in procedural logic. The component exposes a `context` variable of type (`@context` in Razor syntax), which you can use to access information about the signed-in user: ```razor

Hello, @context.User.Identity?.Name!

``` You can also supply different content for display if the user isn't authorized with a combination of the and parameters: ```razor

Hello, @context.User.Identity?.Name!

You're not authorized.

@code { private void SecureMethod() { ... } } ``` A default event handler for an authorized element, such as the `SecureMethod` method for the ` @code { [CascadingParameter] private Task? authenticationState { get; set; } private async Task DoSomething() { if (authenticationState is not null) { var authState = await authenticationState; var user = authState?.User; if (user is not null) { if (user.Identity is not null && user.Identity.IsAuthenticated) { // ... } if (user.IsInRole("Admin")) { // ... } if ((await AuthorizationService.AuthorizeAsync(user, "content-editor")) .Succeeded) { // ... } } } } } ``` :::moniker-end :::moniker range="< aspnetcore-8.0" ```razor @page "/procedural-logic" @inject IAuthorizationService AuthorizationService

Procedural Logic Example

@code { [CascadingParameter] private Task? authenticationState { get; set; } private async Task DoSomething() { if (authenticationState is not null) { var authState = await authenticationState; var user = authState?.User; if (user is not null) { if (user.Identity is not null && user.Identity.IsAuthenticated) { // ... } if (user.IsInRole("Admin")) { // ... } if ((await AuthorizationService.AuthorizeAsync(user, "content-editor")) .Succeeded) { // ... } } } } } ``` :::moniker-end ## Troubleshoot errors Common errors: * **Authorization requires a cascading parameter of type `Task`. Consider using `CascadingAuthenticationState` to supply this.** * **`null` value is received for `authenticationStateTask`** It's likely that the project wasn't created using a server-side Blazor template with authentication enabled. In .NET 7 or earlier, wrap a `` around some part of the UI tree, for example around the Blazor router: ```razor ... ``` In .NET 8 or later, don't use the component: ```diff - ... - ``` Instead, add cascading authentication state services to the service collection in the `Program` file: ```csharp builder.Services.AddCascadingAuthenticationState(); ``` The component (.NET 7 or earlier) or services provided by (.NET 8 or later) supplies the `Task<``>` cascading parameter, which in turn it receives from the underlying dependency injection service. ## Personally Identifiable Information (PII) Microsoft uses the [GDPR definition for 'personal data' (GDPR 4.1)](https://gdpr-text.com/read/article-4/) when documentation discusses Personally Identifiable Information (PII). PII refers any information relating to an identified or identifiable natural person. An identifiable natural person is one who can be identified, directly or indirectly, with any of the following: * Name * Identification number * Location coordinates * Online identifier * Other specific factors * Physical * Physiological * Genetic * Mental (psychological) * Economic * Cultural * Social identity ## Additional resources :::moniker range=">= aspnetcore-6.0" * Microsoft identity platform documentation * [Overview](/entra/identity-platform/) * [OAuth 2.0 and OpenID Connect protocols on the Microsoft identity platform](/entra/identity-platform/v2-protocols) * [Microsoft identity platform and OAuth 2.0 authorization code flow](/entra/identity-platform/v2-oauth2-auth-code-flow) * [Microsoft identity platform ID tokens](/entra/identity-platform/id-tokens) * [Microsoft identity platform access tokens](/entra/identity-platform/access-tokens) * * * [Build a custom version of the Authentication.MSAL JavaScript library](xref:blazor/security/webassembly/additional-scenarios#build-a-custom-version-of-the-authenticationmsal-javascript-library) * [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links * :::moniker-end :::moniker range="< aspnetcore-6.0" * Microsoft identity platform documentation * [Overview](/entra/identity-platform/) * [OAuth 2.0 and OpenID Connect protocols on the Microsoft identity platform](/entra/identity-platform/v2-protocols) * [Microsoft identity platform and OAuth 2.0 authorization code flow](/entra/identity-platform/v2-oauth2-auth-code-flow) * [Microsoft identity platform ID tokens](/entra/identity-platform/id-tokens) * [Microsoft identity platform access tokens](/entra/identity-platform/access-tokens) * * * [Build a custom version of the Authentication.MSAL JavaScript library](xref:blazor/security/webassembly/additional-scenarios#build-a-custom-version-of-the-authenticationmsal-javascript-library) * [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links :::moniker-end