Which type of control is based on the identity of the requestor and the access rules state what a requestor can or Cannot do?

Skip to main content

This browser is no longer supported.

Show

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

ASP.NET Core Blazor authentication and authorization

  • Article
  • 09/30/2022
  • 49 minutes to read

In this article

This article describes ASP.NET Core's support for the configuration and management of security in Blazor apps.

Security scenarios differ between Blazor Server and Blazor WebAssembly apps. Because Blazor Server apps run 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.

Blazor WebAssembly apps run on the client. Authorization is only used to determine which UI options to show. Since client-side checks can be modified or bypassed by a user, a Blazor WebAssembly app can't enforce authorization access rules.

Razor Pages authorization conventions don't apply to routable Razor components. If a non-routable Razor component is embedded in a page, the page's authorization conventions indirectly affect the Razor component along with the rest of the page's content.

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.

ASP.NET Core abstractions, such as SignInManager<TUser> and UserManager<TUser>, 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 Blazor Server app.

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, Blazor WebAssembly or Blazor Server.

Blazor WebAssembly authentication

In Blazor WebAssembly apps, 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 or native apps for any operating system.

Add the following:

  • A package reference for Microsoft.AspNetCore.Components.Authorization.

  • The Microsoft.AspNetCore.Components.Authorization namespace to the app's _Imports.razor file.

To handle authentication, use of a built-in or custom AuthenticationStateProvider service is covered in the following sections.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor WebAssembly.

Blazor Server authentication

Blazor Server apps operate over a real-time connection that's created using SignalR. Authentication in SignalR-based apps is handled when the connection is established. Authentication can be based on a cookie or some other bearer token.

The built-in AuthenticationStateProvider service for Blazor Server apps obtains authentication state data from ASP.NET Core's HttpContext.User. This is how authentication state integrates with existing ASP.NET Core authentication mechanisms.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor Server apps.

AuthenticationStateProvider service

AuthenticationStateProvider is the underlying service used by the AuthorizeView component and CascadingAuthenticationState component to get the authentication state.

You don't typically use AuthenticationStateProvider directly. Use the AuthorizeView component or Task<AuthenticationState> approaches described later in this article. The main drawback to using AuthenticationStateProvider directly is that the component isn't notified automatically if the underlying authentication state data changes.

The AuthenticationStateProvider service can provide the current user's ClaimsPrincipal data, as shown in the following example:

@page "/"
@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

<h3>ClaimsPrincipal Data</h3>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

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

<p>@surnameMessage</p>

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

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surnameMessage = 
                $"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true and because the user is a ClaimsPrincipal, claims can be enumerated and membership in roles evaluated.

For more information on dependency injection (DI) and services, see ASP.NET Core Blazor dependency injection and Dependency injection in ASP.NET Core. For information on how to implement a custom AuthenticationStateProvider in Blazor Server apps, see Secure ASP.NET Core Blazor Server apps.

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 of type Task<AuthenticationState>:

@page "/"

<button @onclick="LogUsername">Log username</button>

<p>@authMessage</p>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private string authMessage;

    private async Task LogUsername()
    {
        var authState = await authenticationStateTask;
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true, claims can be enumerated and membership in roles evaluated.

Set up the Task<AuthenticationState> cascading parameter using the AuthorizeRouteView and CascadingAuthenticationState components in the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="@routeData" 
                DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

In a Blazor WebAssembly App, add services for options and authorization to Program.cs:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

In a Blazor Server app, services for options and authorization are already present, so no further action is 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.

AuthorizeView component

The AuthorizeView 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 AuthenticationState, which you can use to access information about the signed-in user:

<AuthorizeView>
    <h2>Hello, @context.User.Identity.Name!</h2>
    <p>You can only see this content if you're authenticated.</p>
</AuthorizeView>

You can also supply different content for display if the user isn't authorized:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authorized.</p>
        <button @onclick="SecureMethod">Authorized Only Button</button>
    </Authorized>
    <NotAuthorized>
        <h2>Authentication Failure!</h2>
        <p>You're not signed in.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void SecureMethod() { ... }
}

The content of <Authorized> and <NotAuthorized> tags can include arbitrary items, such as other interactive components.

A default event handler for an authorized element, such as the SecureMethod method for the <button> element in the preceding example, can only be invoked by an authorized user.

Authorization conditions, such as roles or policies that control UI options or access, are covered in the Authorization section.

If authorization conditions aren't specified, AuthorizeView uses a default policy and treats:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

The AuthorizeView component can be used in the NavMenu component (Shared/NavMenu.razor) to display a NavLink component (NavLink), but note that this approach only removes the list item from the rendered output. It doesn't prevent the user from navigating to the component.

Apps created from a Blazor project template that include authentication use a LoginDisplay component that depends on an AuthorizeView component. The AuthorizeView component selectively displays content to users for Identity-related work. The following example is from the Blazor WebAssembly project template.

Shared/LoginDisplay.razor:

@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager

<AuthorizeView>
    <Authorized>
        Hello, @context.User.Identity.Name!
        <button class="nav-link btn btn-link" @onclick="BeginLogout">Log out</button>
    </Authorized>
    <NotAuthorized>
        <a href="authentication/login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

@code{
    private async Task BeginLogout(MouseEventArgs args)
    {
        await SignOutManager.SetSignOutState();
        Navigation.NavigateTo("authentication/logout");
    }
}

The following example is from the Blazor Server project template and uses ASP.NET Core Identity endpoints in the Identity area of the app to process Identity-related work.

Shared/LoginDisplay.razor:

<AuthorizeView>
    <Authorized>
        <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
        <form method="post" action="Identity/Account/LogOut">
            <button type="submit" class="nav-link btn btn-link">Log out</button>
        </form>
    </Authorized>
    <NotAuthorized>
        <a href="Identity/Account/Register">Register</a>
        <a href="Identity/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

Role-based and policy-based authorization

The AuthorizeView component supports role-based or policy-based authorization.

For role-based authorization, use the Roles parameter:

<AuthorizeView Roles="admin, superuser">
    <p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

For more information, including configuration guidance, see Role-based authorization in ASP.NET Core.

For policy-based authorization, use the Policy parameter:

<AuthorizeView Policy="content-editor">
    <p>You can only see this if you satisfy the "content-editor" policy.</p>
</AuthorizeView>

Claims-based authorization is a special case of policy-based authorization. For example, you can define a policy that requires users to have a certain claim. For more information, see Policy-based authorization in ASP.NET Core.

These APIs can be used in either Blazor Server or Blazor WebAssembly apps.

If neither Roles nor Policy is specified, AuthorizeView uses the default policy.

Content displayed during asynchronous authentication

Blazor allows for authentication state to be determined asynchronously. The primary scenario for this approach is in Blazor WebAssembly apps that make a request to an external endpoint for authentication.

While authentication is in progress, AuthorizeView displays no content by default. To display content while authentication occurs, use the <Authorizing> tag:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authenticated.</p>
    </Authorized>
    <Authorizing>
        <h2>Authentication in progress</h2>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

This approach isn't normally applicable to Blazor Server apps. Blazor Server apps know the authentication state as soon as the state is established. Authorizing content can be provided in a Blazor Server app's AuthorizeView component, but the content is never displayed.

[Authorize] attribute

The [Authorize] attribute can be used in Razor components:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Important

Only use [Authorize] on @page components reached via the Blazor Router. Authorization is only performed as an aspect of routing and not for child components rendered within a page. To authorize the display of specific parts within a page, use AuthorizeView instead.

The [Authorize] attribute also supports role-based or policy-based authorization. For role-based authorization, use the Roles parameter:

@page "/"
@attribute [Authorize(Roles = "admin, superuser")]

<p>You can only see this if you're in the 'admin' or 'superuser' role.</p>

For policy-based authorization, use the Policy parameter:

@page "/"
@attribute [Authorize(Policy = "content-editor")]

<p>You can only see this if you satisfy the 'content-editor' policy.</p>

If neither Roles nor Policy is specified, [Authorize] uses the default policy, which by default is to treat:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

Resource authorization

To authorize users for resources, pass the request's route data to the Resource parameter of AuthorizeRouteView.

In the Router.Found content for a requested route in the App component (App.razor):

<AuthorizeRouteView Resource="@routeData" RouteData="@routeData" 
    DefaultLayout="@typeof(MainLayout)" />

For more information on how authorization state data is passed and used in procedural logic, see the Expose the authentication state as a cascading parameter section.

When the AuthorizeRouteView receives the route data for the resource, authorization policies have access to RouteData.PageType and RouteData.RouteValues that permit custom logic to make authorization decisions.

In the following example, an EditUser policy is created in AuthorizationOptions for the app's authorization service configuration (AddAuthorizationCore) with the following logic:

  • Determine if a route value exists with a key of id. If the key exists, the route value is stored in value.
  • In a variable named id, store value as a string or set an empty string value (string.Empty).
  • If id isn't an empty string, assert that the policy is satisfied (return true) if the string's value starts with EMP. Otherwise, assert that the policy fails (return false).

In either Program.cs or Startup.cs (depending on the hosting model and framework version):

  • Add namespaces for Microsoft.AspNetCore.Components and System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Add the policy:

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

The preceding example is an oversimplified authorization policy, merely used to demonstrate the concept with a working example. For more information on creating and configuring authorization policies, see Policy-based authorization in ASP.NET Core.

In the following EditUser component, the resource at /users/{id}/edit has a route parameter for the user's identifier ({id}). The component uses the preceding EditUser authorization policy to determine if the route value for id starts with EMP. If id starts with EMP, the policy succeeds and access to the component is authorized. If id starts with a value other than EMP or if id is an empty string, the policy fails, and the component doesn't load.

Pages/EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h2>Edit User</h2>

<p>The 'EditUser' policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string Id { get; set; }
}

Customize unauthorized content with the Router component

The Router component, in conjunction with the AuthorizeRouteView component, allows the app to specify custom content if:

  • The user fails an [Authorize] condition applied to the component. The markup of the <NotAuthorized> element is displayed. The [Authorize] attribute is covered in the [Authorize] attribute section.
  • Asynchronous authorization is in progress, which usually means that the process of authenticating the user is in progress. The markup of the <Authorizing> element is displayed.
  • Content isn't found. The markup of the <NotFound> element is displayed.

In the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

The content of <NotFound>, <NotAuthorized>, and <Authorizing> tags can include arbitrary items, such as other interactive components.

If the <NotAuthorized> tag isn't specified, the AuthorizeRouteView uses the following fallback message:

Not authorized.

Procedural logic

If the app is required to check authorization rules as part of procedural logic, use a cascaded parameter of type Task<AuthenticationState> to obtain the user's ClaimsPrincipal. Task<AuthenticationState> can be combined with other services, such as IAuthorizationService, to evaluate policies.

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private async Task DoSomething()
    {
        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated)
        {
            // Perform an action only available to authenticated (signed-in) users.
        }

        if (user.IsInRole("admin"))
        {
            // Perform an action only available to users in the 'admin' role.
        }

        if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
            .Succeeded)
        {
            // Perform an action only available to users satisfying the 
            // 'content-editor' policy.
        }
    }
}

Troubleshoot errors

Common errors:

  • Authorization requires a cascading parameter of type Task<AuthenticationState>. Consider using CascadingAuthenticationState to supply this.

  • null value is received for authenticationStateTask

It's likely that the project wasn't created using a Blazor Server template with authentication enabled. Wrap a <CascadingAuthenticationState> around some part of the UI tree, for example in the App component (App.razor) as follows:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

The CascadingAuthenticationState supplies the Task<AuthenticationState> cascading parameter, which in turn it receives from the underlying AuthenticationStateProvider DI service.

Additional resources

  • Microsoft identity platform documentation
    • Overview
    • OAuth 2.0 and OpenID Connect protocols on the Microsoft identity platform
    • Microsoft identity platform and OAuth 2.0 authorization code flow
    • Microsoft identity platform ID tokens
    • Microsoft identity platform access tokens
  • ASP.NET Core security topics
  • Configure Windows Authentication in ASP.NET Core
  • Build a custom version of the Authentication.MSAL JavaScript library
  • ASP.NET Core Blazor Hybrid authentication and authorization
  • Awesome Blazor: Authentication community sample links

Security scenarios differ between Blazor Server and Blazor WebAssembly apps. Because Blazor Server apps run 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.

Blazor WebAssembly apps run on the client. Authorization is only used to determine which UI options to show. Since client-side checks can be modified or bypassed by a user, a Blazor WebAssembly app can't enforce authorization access rules.

Razor Pages authorization conventions don't apply to routable Razor components. If a non-routable Razor component is embedded in a page, the page's authorization conventions indirectly affect the Razor component along with the rest of the page's content.

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.

ASP.NET Core abstractions, such as SignInManager<TUser> and UserManager<TUser>, 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 Blazor Server app.

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, Blazor WebAssembly or Blazor Server.

Blazor WebAssembly authentication

In Blazor WebAssembly apps, 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 or native apps for any operating system.

Add the following:

  • A package reference for Microsoft.AspNetCore.Components.Authorization.

  • The Microsoft.AspNetCore.Components.Authorization namespace to the app's _Imports.razor file.

To handle authentication, use of a built-in or custom AuthenticationStateProvider service is covered in the following sections.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor WebAssembly.

Blazor Server authentication

Blazor Server apps operate over a real-time connection that's created using SignalR. Authentication in SignalR-based apps is handled when the connection is established. Authentication can be based on a cookie or some other bearer token.

The built-in AuthenticationStateProvider service for Blazor Server apps obtains authentication state data from ASP.NET Core's HttpContext.User. This is how authentication state integrates with existing ASP.NET Core authentication mechanisms.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor Server apps.

AuthenticationStateProvider service

AuthenticationStateProvider is the underlying service used by the AuthorizeView component and CascadingAuthenticationState component to get the authentication state.

You don't typically use AuthenticationStateProvider directly. Use the AuthorizeView component or Task<AuthenticationState> approaches described later in this article. The main drawback to using AuthenticationStateProvider directly is that the component isn't notified automatically if the underlying authentication state data changes.

The AuthenticationStateProvider service can provide the current user's ClaimsPrincipal data, as shown in the following example:

@page "/"
@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

<h3>ClaimsPrincipal Data</h3>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

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

<p>@surnameMessage</p>

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

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surnameMessage = 
                $"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true and because the user is a ClaimsPrincipal, claims can be enumerated and membership in roles evaluated.

For more information on dependency injection (DI) and services, see ASP.NET Core Blazor dependency injection and Dependency injection in ASP.NET Core. For information on how to implement a custom AuthenticationStateProvider in Blazor Server apps, see Secure ASP.NET Core Blazor Server apps.

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 of type Task<AuthenticationState>:

@page "/"

<button @onclick="LogUsername">Log username</button>

<p>@authMessage</p>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private string authMessage;

    private async Task LogUsername()
    {
        var authState = await authenticationStateTask;
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true, claims can be enumerated and membership in roles evaluated.

Set up the Task<AuthenticationState> cascading parameter using the AuthorizeRouteView and CascadingAuthenticationState components in the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="@routeData" 
                DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

Note

With the release of ASP.NET Core 5.0.1 and for any additional 5.x releases, the Router component includes the PreferExactMatches parameter set to @true. For more information, see Migrate from ASP.NET Core 3.1 to 5.0.

In a Blazor WebAssembly App, add services for options and authorization to Program.cs:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

In a Blazor Server app, services for options and authorization are already present, so no further action is 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.

AuthorizeView component

The AuthorizeView 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 AuthenticationState, which you can use to access information about the signed-in user:

<AuthorizeView>
    <h2>Hello, @context.User.Identity.Name!</h2>
    <p>You can only see this content if you're authenticated.</p>
</AuthorizeView>

You can also supply different content for display if the user isn't authorized:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authorized.</p>
        <button @onclick="SecureMethod">Authorized Only Button</button>
    </Authorized>
    <NotAuthorized>
        <h2>Authentication Failure!</h2>
        <p>You're not signed in.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void SecureMethod() { ... }
}

The content of <Authorized> and <NotAuthorized> tags can include arbitrary items, such as other interactive components.

A default event handler for an authorized element, such as the SecureMethod method for the <button> element in the preceding example, can only be invoked by an authorized user.

Authorization conditions, such as roles or policies that control UI options or access, are covered in the Authorization section.

If authorization conditions aren't specified, AuthorizeView uses a default policy and treats:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

The AuthorizeView component can be used in the NavMenu component (Shared/NavMenu.razor) to display a NavLink component (NavLink), but note that this approach only removes the list item from the rendered output. It doesn't prevent the user from navigating to the component.

Apps created from a Blazor project template that include authentication use a LoginDisplay component that depends on an AuthorizeView component. The AuthorizeView component selectively displays content to users for Identity-related work. The following example is from the Blazor WebAssembly project template.

Shared/LoginDisplay.razor:

@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager

<AuthorizeView>
    <Authorized>
        Hello, @context.User.Identity.Name!
        <button class="nav-link btn btn-link" @onclick="BeginLogout">Log out</button>
    </Authorized>
    <NotAuthorized>
        <a href="authentication/login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

@code{
    private async Task BeginLogout(MouseEventArgs args)
    {
        await SignOutManager.SetSignOutState();
        Navigation.NavigateTo("authentication/logout");
    }
}

The following example is from the Blazor Server project template and uses ASP.NET Core Identity endpoints in the Identity area of the app to process Identity-related work.

Shared/LoginDisplay.razor:

<AuthorizeView>
    <Authorized>
        <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
        <form method="post" action="Identity/Account/LogOut">
            <button type="submit" class="nav-link btn btn-link">Log out</button>
        </form>
    </Authorized>
    <NotAuthorized>
        <a href="Identity/Account/Register">Register</a>
        <a href="Identity/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

Role-based and policy-based authorization

The AuthorizeView component supports role-based or policy-based authorization.

For role-based authorization, use the Roles parameter:

<AuthorizeView Roles="admin, superuser">
    <p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

For more information, including configuration guidance, see Role-based authorization in ASP.NET Core.

For policy-based authorization, use the Policy parameter:

<AuthorizeView Policy="content-editor">
    <p>You can only see this if you satisfy the "content-editor" policy.</p>
</AuthorizeView>

Claims-based authorization is a special case of policy-based authorization. For example, you can define a policy that requires users to have a certain claim. For more information, see Policy-based authorization in ASP.NET Core.

These APIs can be used in either Blazor Server or Blazor WebAssembly apps.

If neither Roles nor Policy is specified, AuthorizeView uses the default policy.

Content displayed during asynchronous authentication

Blazor allows for authentication state to be determined asynchronously. The primary scenario for this approach is in Blazor WebAssembly apps that make a request to an external endpoint for authentication.

While authentication is in progress, AuthorizeView displays no content by default. To display content while authentication occurs, use the <Authorizing> tag:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authenticated.</p>
    </Authorized>
    <Authorizing>
        <h2>Authentication in progress</h2>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

This approach isn't normally applicable to Blazor Server apps. Blazor Server apps know the authentication state as soon as the state is established. Authorizing content can be provided in a Blazor Server app's AuthorizeView component, but the content is never displayed.

[Authorize] attribute

The [Authorize] attribute can be used in Razor components:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Important

Only use [Authorize] on @page components reached via the Blazor Router. Authorization is only performed as an aspect of routing and not for child components rendered within a page. To authorize the display of specific parts within a page, use AuthorizeView instead.

The [Authorize] attribute also supports role-based or policy-based authorization. For role-based authorization, use the Roles parameter:

@page "/"
@attribute [Authorize(Roles = "admin, superuser")]

<p>You can only see this if you're in the 'admin' or 'superuser' role.</p>

For policy-based authorization, use the Policy parameter:

@page "/"
@attribute [Authorize(Policy = "content-editor")]

<p>You can only see this if you satisfy the 'content-editor' policy.</p>

If neither Roles nor Policy is specified, [Authorize] uses the default policy, which by default is to treat:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

Resource authorization

To authorize users for resources, pass the request's route data to the Resource parameter of AuthorizeRouteView.

In the Router.Found content for a requested route in the App component (App.razor):

<AuthorizeRouteView Resource="@routeData" RouteData="@routeData" 
    DefaultLayout="@typeof(MainLayout)" />

For more information on how authorization state data is passed and used in procedural logic, see the Expose the authentication state as a cascading parameter section.

When the AuthorizeRouteView receives the route data for the resource, authorization policies have access to RouteData.PageType and RouteData.RouteValues that permit custom logic to make authorization decisions.

In the following example, an EditUser policy is created in AuthorizationOptions for the app's authorization service configuration (AddAuthorizationCore) with the following logic:

  • Determine if a route value exists with a key of id. If the key exists, the route value is stored in value.
  • In a variable named id, store value as a string or set an empty string value (string.Empty).
  • If id isn't an empty string, assert that the policy is satisfied (return true) if the string's value starts with EMP. Otherwise, assert that the policy fails (return false).

In either Program.cs or Startup.cs (depending on the hosting model and framework version):

  • Add namespaces for Microsoft.AspNetCore.Components and System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Add the policy:

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

The preceding example is an oversimplified authorization policy, merely used to demonstrate the concept with a working example. For more information on creating and configuring authorization policies, see Policy-based authorization in ASP.NET Core.

In the following EditUser component, the resource at /users/{id}/edit has a route parameter for the user's identifier ({id}). The component uses the preceding EditUser authorization policy to determine if the route value for id starts with EMP. If id starts with EMP, the policy succeeds and access to the component is authorized. If id starts with a value other than EMP or if id is an empty string, the policy fails, and the component doesn't load.

Pages/EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h2>Edit User</h2>

<p>The 'EditUser' policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string Id { get; set; }
}

Customize unauthorized content with the Router component

The Router component, in conjunction with the AuthorizeRouteView component, allows the app to specify custom content if:

  • The user fails an [Authorize] condition applied to the component. The markup of the <NotAuthorized> element is displayed. The [Authorize] attribute is covered in the [Authorize] attribute section.
  • Asynchronous authorization is in progress, which usually means that the process of authenticating the user is in progress. The markup of the <Authorizing> element is displayed.
  • Content isn't found. The markup of the <NotFound> element is displayed.

In the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

Note

With the release of ASP.NET Core 5.0.1 and for any additional 5.x releases, the Router component includes the PreferExactMatches parameter set to @true. For more information, see Migrate from ASP.NET Core 3.1 to 5.0.

The content of <NotFound>, <NotAuthorized>, and <Authorizing> tags can include arbitrary items, such as other interactive components.

If the <NotAuthorized> tag isn't specified, the AuthorizeRouteView uses the following fallback message:

Not authorized.

Procedural logic

If the app is required to check authorization rules as part of procedural logic, use a cascaded parameter of type Task<AuthenticationState> to obtain the user's ClaimsPrincipal. Task<AuthenticationState> can be combined with other services, such as IAuthorizationService, to evaluate policies.

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private async Task DoSomething()
    {
        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated)
        {
            // Perform an action only available to authenticated (signed-in) users.
        }

        if (user.IsInRole("admin"))
        {
            // Perform an action only available to users in the 'admin' role.
        }

        if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
            .Succeeded)
        {
            // Perform an action only available to users satisfying the 
            // 'content-editor' policy.
        }
    }
}

Troubleshoot errors

Common errors:

  • Authorization requires a cascading parameter of type Task<AuthenticationState>. Consider using CascadingAuthenticationState to supply this.

  • null value is received for authenticationStateTask

It's likely that the project wasn't created using a Blazor Server template with authentication enabled. Wrap a <CascadingAuthenticationState> around some part of the UI tree, for example in the App component (App.razor) as follows:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

Note

With the release of ASP.NET Core 5.0.1 and for any additional 5.x releases, the Router component includes the PreferExactMatches parameter set to @true. For more information, see Migrate from ASP.NET Core 3.1 to 5.0.

The CascadingAuthenticationState supplies the Task<AuthenticationState> cascading parameter, which in turn it receives from the underlying AuthenticationStateProvider DI service.

Additional resources

  • Microsoft identity platform documentation
    • Overview
    • OAuth 2.0 and OpenID Connect protocols on the Microsoft identity platform
    • Microsoft identity platform and OAuth 2.0 authorization code flow
    • Microsoft identity platform ID tokens
    • Microsoft identity platform access tokens
  • ASP.NET Core security topics
  • Configure Windows Authentication in ASP.NET Core
  • Build a custom version of the Authentication.MSAL JavaScript library
  • Awesome Blazor: Authentication community sample links

Security scenarios differ between Blazor Server and Blazor WebAssembly apps. Because Blazor Server apps run 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.

Blazor WebAssembly apps run on the client. Authorization is only used to determine which UI options to show. Since client-side checks can be modified or bypassed by a user, a Blazor WebAssembly app can't enforce authorization access rules.

Razor Pages authorization conventions don't apply to routable Razor components. If a non-routable Razor component is embedded in a page, the page's authorization conventions indirectly affect the Razor component along with the rest of the page's content.

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.

ASP.NET Core abstractions, such as SignInManager<TUser> and UserManager<TUser>, 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 Blazor Server app.

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, Blazor WebAssembly or Blazor Server.

Blazor WebAssembly authentication

In Blazor WebAssembly apps, 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 or native apps for any operating system.

Add the following:

  • A package reference for Microsoft.AspNetCore.Components.Authorization.

  • The Microsoft.AspNetCore.Components.Authorization namespace to the app's _Imports.razor file.

To handle authentication, use of a built-in or custom AuthenticationStateProvider service is covered in the following sections.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor WebAssembly.

Blazor Server authentication

Blazor Server apps operate over a real-time connection that's created using SignalR. Authentication in SignalR-based apps is handled when the connection is established. Authentication can be based on a cookie or some other bearer token.

The built-in AuthenticationStateProvider service for Blazor Server apps obtains authentication state data from ASP.NET Core's HttpContext.User. This is how authentication state integrates with existing ASP.NET Core authentication mechanisms.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor Server apps.

AuthenticationStateProvider service

AuthenticationStateProvider is the underlying service used by the AuthorizeView component and CascadingAuthenticationState component to get the authentication state.

You don't typically use AuthenticationStateProvider directly. Use the AuthorizeView component or Task<AuthenticationState> approaches described later in this article. The main drawback to using AuthenticationStateProvider directly is that the component isn't notified automatically if the underlying authentication state data changes.

The AuthenticationStateProvider service can provide the current user's ClaimsPrincipal data, as shown in the following example:

@page "/"
@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

<h3>ClaimsPrincipal Data</h3>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

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

<p>@surnameMessage</p>

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

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surnameMessage = 
                $"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true and because the user is a ClaimsPrincipal, claims can be enumerated and membership in roles evaluated.

For more information on dependency injection (DI) and services, see ASP.NET Core Blazor dependency injection and Dependency injection in ASP.NET Core. For information on how to implement a custom AuthenticationStateProvider in Blazor Server apps, see Secure ASP.NET Core Blazor Server apps.

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 of type Task<AuthenticationState>:

@page "/"

<button @onclick="LogUsername">Log username</button>

<p>@authMessage</p>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private string authMessage;

    private async Task LogUsername()
    {
        var authState = await authenticationStateTask;
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true, claims can be enumerated and membership in roles evaluated.

Set up the Task<AuthenticationState> cascading parameter using the AuthorizeRouteView and CascadingAuthenticationState components in the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="@routeData" 
                DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

In a Blazor WebAssembly App, add services for options and authorization to Program.cs:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

In a Blazor Server app, services for options and authorization are already present, so no further action is 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.

AuthorizeView component

The AuthorizeView 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 AuthenticationState, which you can use to access information about the signed-in user:

<AuthorizeView>
    <h2>Hello, @context.User.Identity.Name!</h2>
    <p>You can only see this content if you're authenticated.</p>
</AuthorizeView>

You can also supply different content for display if the user isn't authorized:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authorized.</p>
        <button @onclick="SecureMethod">Authorized Only Button</button>
    </Authorized>
    <NotAuthorized>
        <h2>Authentication Failure!</h2>
        <p>You're not signed in.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void SecureMethod() { ... }
}

The content of <Authorized> and <NotAuthorized> tags can include arbitrary items, such as other interactive components.

A default event handler for an authorized element, such as the SecureMethod method for the <button> element in the preceding example, can only be invoked by an authorized user.

Authorization conditions, such as roles or policies that control UI options or access, are covered in the Authorization section.

If authorization conditions aren't specified, AuthorizeView uses a default policy and treats:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

The AuthorizeView component can be used in the NavMenu component (Shared/NavMenu.razor) to display a NavLink component (NavLink), but note that this approach only removes the list item from the rendered output. It doesn't prevent the user from navigating to the component.

Apps created from a Blazor project template that include authentication use a LoginDisplay component that depends on an AuthorizeView component. The AuthorizeView component selectively displays content to users for Identity-related work. The following example is from the Blazor WebAssembly project template.

Shared/LoginDisplay.razor:

@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager

<AuthorizeView>
    <Authorized>
        Hello, @context.User.Identity.Name!
        <button class="nav-link btn btn-link" @onclick="BeginLogout">Log out</button>
    </Authorized>
    <NotAuthorized>
        <a href="authentication/login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

@code{
    private async Task BeginLogout(MouseEventArgs args)
    {
        await SignOutManager.SetSignOutState();
        Navigation.NavigateTo("authentication/logout");
    }
}

The following example is from the Blazor Server project template and uses ASP.NET Core Identity endpoints in the Identity area of the app to process Identity-related work.

Shared/LoginDisplay.razor:

<AuthorizeView>
    <Authorized>
        <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
        <form method="post" action="Identity/Account/LogOut">
            <button type="submit" class="nav-link btn btn-link">Log out</button>
        </form>
    </Authorized>
    <NotAuthorized>
        <a href="Identity/Account/Register">Register</a>
        <a href="Identity/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

Role-based and policy-based authorization

The AuthorizeView component supports role-based or policy-based authorization.

For role-based authorization, use the Roles parameter:

<AuthorizeView Roles="admin, superuser">
    <p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

For more information, including configuration guidance, see Role-based authorization in ASP.NET Core.

For policy-based authorization, use the Policy parameter:

<AuthorizeView Policy="content-editor">
    <p>You can only see this if you satisfy the "content-editor" policy.</p>
</AuthorizeView>

Claims-based authorization is a special case of policy-based authorization. For example, you can define a policy that requires users to have a certain claim. For more information, see Policy-based authorization in ASP.NET Core.

These APIs can be used in either Blazor Server or Blazor WebAssembly apps.

If neither Roles nor Policy is specified, AuthorizeView uses the default policy.

Content displayed during asynchronous authentication

Blazor allows for authentication state to be determined asynchronously. The primary scenario for this approach is in Blazor WebAssembly apps that make a request to an external endpoint for authentication.

While authentication is in progress, AuthorizeView displays no content by default. To display content while authentication occurs, use the <Authorizing> tag:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authenticated.</p>
    </Authorized>
    <Authorizing>
        <h2>Authentication in progress</h2>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

This approach isn't normally applicable to Blazor Server apps. Blazor Server apps know the authentication state as soon as the state is established. Authorizing content can be provided in a Blazor Server app's AuthorizeView component, but the content is never displayed.

[Authorize] attribute

The [Authorize] attribute can be used in Razor components:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Important

Only use [Authorize] on @page components reached via the Blazor Router. Authorization is only performed as an aspect of routing and not for child components rendered within a page. To authorize the display of specific parts within a page, use AuthorizeView instead.

The [Authorize] attribute also supports role-based or policy-based authorization. For role-based authorization, use the Roles parameter:

@page "/"
@attribute [Authorize(Roles = "admin, superuser")]

<p>You can only see this if you're in the 'admin' or 'superuser' role.</p>

For policy-based authorization, use the Policy parameter:

@page "/"
@attribute [Authorize(Policy = "content-editor")]

<p>You can only see this if you satisfy the 'content-editor' policy.</p>

If neither Roles nor Policy is specified, [Authorize] uses the default policy, which by default is to treat:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

Customize unauthorized content with the Router component

The Router component, in conjunction with the AuthorizeRouteView component, allows the app to specify custom content if:

  • The user fails an [Authorize] condition applied to the component. The markup of the <NotAuthorized> element is displayed. The [Authorize] attribute is covered in the [Authorize] attribute section.
  • Asynchronous authorization is in progress, which usually means that the process of authenticating the user is in progress. The markup of the <Authorizing> element is displayed.
  • Content isn't found. The markup of the <NotFound> element is displayed.

In the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

The content of <NotFound>, <NotAuthorized>, and <Authorizing> tags can include arbitrary items, such as other interactive components.

If the <NotAuthorized> tag isn't specified, the AuthorizeRouteView uses the following fallback message:

Not authorized.

Procedural logic

If the app is required to check authorization rules as part of procedural logic, use a cascaded parameter of type Task<AuthenticationState> to obtain the user's ClaimsPrincipal. Task<AuthenticationState> can be combined with other services, such as IAuthorizationService, to evaluate policies.

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private async Task DoSomething()
    {
        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated)
        {
            // Perform an action only available to authenticated (signed-in) users.
        }

        if (user.IsInRole("admin"))
        {
            // Perform an action only available to users in the 'admin' role.
        }

        if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
            .Succeeded)
        {
            // Perform an action only available to users satisfying the 
            // 'content-editor' policy.
        }
    }
}

Troubleshoot errors

Common errors:

  • Authorization requires a cascading parameter of type Task<AuthenticationState>. Consider using CascadingAuthenticationState to supply this.

  • null value is received for authenticationStateTask

It's likely that the project wasn't created using a Blazor Server template with authentication enabled. Wrap a <CascadingAuthenticationState> around some part of the UI tree, for example in the App component (App.razor) as follows:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

The CascadingAuthenticationState supplies the Task<AuthenticationState> cascading parameter, which in turn it receives from the underlying AuthenticationStateProvider DI service.

Additional resources

  • Microsoft identity platform documentation
  • ASP.NET Core security topics
  • Configure Windows Authentication in ASP.NET Core
  • Build a custom version of the Authentication.MSAL JavaScript library
  • Awesome Blazor: Authentication community sample links

Security scenarios differ between Blazor Server and Blazor WebAssembly apps. Because Blazor Server apps run 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.

Blazor WebAssembly apps run on the client. Authorization is only used to determine which UI options to show. Since client-side checks can be modified or bypassed by a user, a Blazor WebAssembly app can't enforce authorization access rules.

Razor Pages authorization conventions don't apply to routable Razor components. If a non-routable Razor component is embedded in a page, the page's authorization conventions indirectly affect the Razor component along with the rest of the page's content.

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.

ASP.NET Core abstractions, such as SignInManager<TUser> and UserManager<TUser>, 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 Blazor Server app.

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, Blazor WebAssembly or Blazor Server.

Blazor WebAssembly authentication

In Blazor WebAssembly apps, 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 or native apps for any operating system.

Add the following:

  • A package reference for Microsoft.AspNetCore.Components.Authorization.

  • The Microsoft.AspNetCore.Components.Authorization namespace to the app's _Imports.razor file.

To handle authentication, use of a built-in or custom AuthenticationStateProvider service is covered in the following sections.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor WebAssembly.

Blazor Server authentication

Blazor Server apps operate over a real-time connection that's created using SignalR. Authentication in SignalR-based apps is handled when the connection is established. Authentication can be based on a cookie or some other bearer token.

The built-in AuthenticationStateProvider service for Blazor Server apps obtains authentication state data from ASP.NET Core's HttpContext.User. This is how authentication state integrates with existing ASP.NET Core authentication mechanisms.

For more information on creating apps and configuration, see Secure ASP.NET Core Blazor Server apps.

AuthenticationStateProvider service

AuthenticationStateProvider is the underlying service used by the AuthorizeView component and CascadingAuthenticationState component to get the authentication state.

You don't typically use AuthenticationStateProvider directly. Use the AuthorizeView component or Task<AuthenticationState> approaches described later in this article. The main drawback to using AuthenticationStateProvider directly is that the component isn't notified automatically if the underlying authentication state data changes.

The AuthenticationStateProvider service can provide the current user's ClaimsPrincipal data, as shown in the following example:

@page "/"
@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

<h3>ClaimsPrincipal Data</h3>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

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

<p>@surnameMessage</p>

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

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surnameMessage = 
                $"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true and because the user is a ClaimsPrincipal, claims can be enumerated and membership in roles evaluated.

For more information on dependency injection (DI) and services, see ASP.NET Core Blazor dependency injection and Dependency injection in ASP.NET Core. For information on how to implement a custom AuthenticationStateProvider in Blazor Server apps, see Secure ASP.NET Core Blazor Server apps.

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 of type Task<AuthenticationState>:

@page "/"

<button @onclick="LogUsername">Log username</button>

<p>@authMessage</p>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private string authMessage;

    private async Task LogUsername()
    {
        var authState = await authenticationStateTask;
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

If user.Identity.IsAuthenticated is true, claims can be enumerated and membership in roles evaluated.

Set up the Task<AuthenticationState> cascading parameter using the AuthorizeRouteView and CascadingAuthenticationState components in the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="@routeData" 
                DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

In a Blazor WebAssembly App, add services for options and authorization to Program.cs:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

In a Blazor Server app, services for options and authorization are already present, so no further action is 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.

AuthorizeView component

The AuthorizeView 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 AuthenticationState, which you can use to access information about the signed-in user:

<AuthorizeView>
    <h2>Hello, @context.User.Identity.Name!</h2>
    <p>You can only see this content if you're authenticated.</p>
</AuthorizeView>

You can also supply different content for display if the user isn't authorized:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authorized.</p>
        <button @onclick="SecureMethod">Authorized Only Button</button>
    </Authorized>
    <NotAuthorized>
        <h2>Authentication Failure!</h2>
        <p>You're not signed in.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void SecureMethod() { ... }
}

The content of <Authorized> and <NotAuthorized> tags can include arbitrary items, such as other interactive components.

A default event handler for an authorized element, such as the SecureMethod method for the <button> element in the preceding example, can only be invoked by an authorized user.

Authorization conditions, such as roles or policies that control UI options or access, are covered in the Authorization section.

If authorization conditions aren't specified, AuthorizeView uses a default policy and treats:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

The AuthorizeView component can be used in the NavMenu component (Shared/NavMenu.razor) to display a NavLink component (NavLink), but note that this approach only removes the list item from the rendered output. It doesn't prevent the user from navigating to the component.

Apps created from a Blazor project template that include authentication use a LoginDisplay component that depends on an AuthorizeView component. The AuthorizeView component selectively displays content to users for Identity-related work. The following example is from the Blazor WebAssembly project template.

Shared/LoginDisplay.razor:

@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation

<AuthorizeView>
    <Authorized>
        Hello, @context.User.Identity?.Name!
        <button class="nav-link btn btn-link" @onclick="BeginLogOut">Log out</button>
    </Authorized>
    <NotAuthorized>
        <a href="authentication/login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

@code{
    public void BeginLogOut()
    {
        Navigation.NavigateToLogout("authentication/logout");
    }
}

The following example is from the Blazor Server project template and uses ASP.NET Core Identity endpoints in the Identity area of the app to process Identity-related work.

Shared/LoginDisplay.razor:

<AuthorizeView>
    <Authorized>
        <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
        <form method="post" action="Identity/Account/LogOut">
            <button type="submit" class="nav-link btn btn-link">Log out</button>
        </form>
    </Authorized>
    <NotAuthorized>
        <a href="Identity/Account/Register">Register</a>
        <a href="Identity/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

Role-based and policy-based authorization

The AuthorizeView component supports role-based or policy-based authorization.

For role-based authorization, use the Roles parameter:

<AuthorizeView Roles="admin, superuser">
    <p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

For more information, including configuration guidance, see Role-based authorization in ASP.NET Core.

For policy-based authorization, use the Policy parameter:

<AuthorizeView Policy="content-editor">
    <p>You can only see this if you satisfy the "content-editor" policy.</p>
</AuthorizeView>

Claims-based authorization is a special case of policy-based authorization. For example, you can define a policy that requires users to have a certain claim. For more information, see Policy-based authorization in ASP.NET Core.

These APIs can be used in either Blazor Server or Blazor WebAssembly apps.

If neither Roles nor Policy is specified, AuthorizeView uses the default policy.

Content displayed during asynchronous authentication

Blazor allows for authentication state to be determined asynchronously. The primary scenario for this approach is in Blazor WebAssembly apps that make a request to an external endpoint for authentication.

While authentication is in progress, AuthorizeView displays no content by default. To display content while authentication occurs, use the <Authorizing> tag:

<AuthorizeView>
    <Authorized>
        <h2>Hello, @context.User.Identity.Name!</h2>
        <p>You can only see this content if you're authenticated.</p>
    </Authorized>
    <Authorizing>
        <h2>Authentication in progress</h2>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

This approach isn't normally applicable to Blazor Server apps. Blazor Server apps know the authentication state as soon as the state is established. Authorizing content can be provided in a Blazor Server app's AuthorizeView component, but the content is never displayed.

[Authorize] attribute

The [Authorize] attribute can be used in Razor components:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Important

Only use [Authorize] on @page components reached via the Blazor Router. Authorization is only performed as an aspect of routing and not for child components rendered within a page. To authorize the display of specific parts within a page, use AuthorizeView instead.

The [Authorize] attribute also supports role-based or policy-based authorization. For role-based authorization, use the Roles parameter:

@page "/"
@attribute [Authorize(Roles = "admin, superuser")]

<p>You can only see this if you're in the 'admin' or 'superuser' role.</p>

For policy-based authorization, use the Policy parameter:

@page "/"
@attribute [Authorize(Policy = "content-editor")]

<p>You can only see this if you satisfy the 'content-editor' policy.</p>

If neither Roles nor Policy is specified, [Authorize] uses the default policy, which by default is to treat:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

Resource authorization

To authorize users for resources, pass the request's route data to the Resource parameter of AuthorizeRouteView.

In the Router.Found content for a requested route in the App component (App.razor):

<AuthorizeRouteView Resource="@routeData" RouteData="@routeData" 
    DefaultLayout="@typeof(MainLayout)" />

For more information on how authorization state data is passed and used in procedural logic, see the Expose the authentication state as a cascading parameter section.

When the AuthorizeRouteView receives the route data for the resource, authorization policies have access to RouteData.PageType and RouteData.RouteValues that permit custom logic to make authorization decisions.

In the following example, an EditUser policy is created in AuthorizationOptions for the app's authorization service configuration (AddAuthorizationCore) with the following logic:

  • Determine if a route value exists with a key of id. If the key exists, the route value is stored in value.
  • In a variable named id, store value as a string or set an empty string value (string.Empty).
  • If id isn't an empty string, assert that the policy is satisfied (return true) if the string's value starts with EMP. Otherwise, assert that the policy fails (return false).

In either Program.cs or Startup.cs (depending on the hosting model and framework version):

  • Add namespaces for Microsoft.AspNetCore.Components and System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Add the policy:

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

The preceding example is an oversimplified authorization policy, merely used to demonstrate the concept with a working example. For more information on creating and configuring authorization policies, see Policy-based authorization in ASP.NET Core.

In the following EditUser component, the resource at /users/{id}/edit has a route parameter for the user's identifier ({id}). The component uses the preceding EditUser authorization policy to determine if the route value for id starts with EMP. If id starts with EMP, the policy succeeds and access to the component is authorized. If id starts with a value other than EMP or if id is an empty string, the policy fails, and the component doesn't load.

Pages/EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h2>Edit User</h2>

<p>The 'EditUser' policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string Id { get; set; }
}

Customize unauthorized content with the Router component

The Router component, in conjunction with the AuthorizeRouteView component, allows the app to specify custom content if:

  • The user fails an [Authorize] condition applied to the component. The markup of the <NotAuthorized> element is displayed. The [Authorize] attribute is covered in the [Authorize] attribute section.
  • Asynchronous authorization is in progress, which usually means that the process of authenticating the user is in progress. The markup of the <Authorizing> element is displayed.
  • Content isn't found. The markup of the <NotFound> element is displayed.

In the App component (App.razor):

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView ...>
                ...
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

The content of <NotFound>, <NotAuthorized>, and <Authorizing> tags can include arbitrary items, such as other interactive components.

If the <NotAuthorized> tag isn't specified, the AuthorizeRouteView uses the following fallback message:

Not authorized.

Procedural logic

If the app is required to check authorization rules as part of procedural logic, use a cascaded parameter of type Task<AuthenticationState> to obtain the user's ClaimsPrincipal. Task<AuthenticationState> can be combined with other services, such as IAuthorizationService, to evaluate policies.

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private async Task DoSomething()
    {
        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated)
        {
            // Perform an action only available to authenticated (signed-in) users.
        }

        if (user.IsInRole("admin"))
        {
            // Perform an action only available to users in the 'admin' role.
        }

        if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
            .Succeeded)
        {
            // Perform an action only available to users satisfying the 
            // 'content-editor' policy.
        }
    }
}

Troubleshoot errors

Common errors:

  • Authorization requires a cascading parameter of type Task<AuthenticationState>. Consider using CascadingAuthenticationState to supply this.

  • null value is received for authenticationStateTask

It's likely that the project wasn't created using a Blazor Server template with authentication enabled. Wrap a <CascadingAuthenticationState> around some part of the UI tree, for example in the App component (App.razor) as follows:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

The CascadingAuthenticationState supplies the Task<AuthenticationState> cascading parameter, which in turn it receives from the underlying AuthenticationStateProvider DI service.

Additional resources

  • Microsoft identity platform documentation
    • Overview
    • OAuth 2.0 and OpenID Connect protocols on the Microsoft identity platform
    • Microsoft identity platform and OAuth 2.0 authorization code flow
    • Microsoft identity platform ID tokens
    • Microsoft identity platform access tokens
  • ASP.NET Core security topics
  • Configure Windows Authentication in ASP.NET Core
  • Build a custom version of the Authentication.MSAL JavaScript library
  • ASP.NET Core Blazor Hybrid authentication and authorization
  • Awesome Blazor: Authentication community sample links

Feedback

Submit and view feedback for

What are the 3 types of access control?

There are three core types of IP access control: discretionary, managed, and role-based. Discretionary access control is extremely flexible and nonrestrictive compared to its alternatives. This is because access rights are specified by users.

What access control method is based on an identity?

Identity-Based Access Control (IBAC) IBAC is a simplified security method that dictates whether the person using is permitted or denied to a given electronic resource based on their individual visual or biometric identity.

What is access control and types of access control?

Access control is a security technique that regulates who or what can view or use resources in a computing environment. It is a fundamental concept in security that minimizes risk to the business or organization. There are two types of access control: physical and logical.

What are the four 4 main access control model?

Currently, there are four primary types of access control models: mandatory access control (MAC), role-based access control (RBAC), discretionary access control (DAC), and rule-based access control (RBAC).

In which type of access control system would access to data be determined by a subject clearance?

Mandatory Access Control (MAC) is system-enforced access control based on a subject's clearance and an object's labels.

Which type of access controls can be role

The answer is non- discretionary. Role-based access control and task-based access control are known Mandatory Access controls (or non-discretionary controls), which match information to roles or tasks, not individual users.