AspNetCore.Docs/aspnetcore/blazor/security/index.md

548 lines
25 KiB
Markdown
Raw Normal View History

2019-06-27 02:58:38 +08:00
---
title: ASP.NET Core Blazor authentication and authorization
author: guardrex
description: Learn about Blazor authentication and authorization scenarios.
monikerRange: '>= aspnetcore-3.1'
2019-06-27 02:58:38 +08:00
ms.author: riande
ms.custom: mvc
2020-05-19 22:47:19 +08:00
ms.date: 05/19/2020
no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
2020-06-19 21:24:40 +08:00
uid: blazor/security/index
2019-06-27 02:58:38 +08:00
---
# ASP.NET Core Blazor authentication and authorization
ASP.NET Core supports 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:
2019-06-27 02:58:38 +08:00
* 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.
2019-06-27 02:58:38 +08:00
[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](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.
> [!NOTE]
> <xref:Microsoft.AspNetCore.Identity.SignInManager%601> and <xref:Microsoft.AspNetCore.Identity.UserManager%601> aren't supported in Razor components.
2019-06-27 02:58:38 +08:00
## Authentication
2019-06-27 02:58:38 +08:00
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.
2019-06-27 02:58:38 +08:00
### Blazor WebAssembly authentication
2019-06-27 02:58:38 +08:00
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.
2019-06-27 02:58:38 +08:00
Add the following:
2019-06-27 02:58:38 +08:00
* A package reference for [`Microsoft.AspNetCore.Components.Authorization`](https://www.nuget.org/packages/Microsoft.AspNetCore.Components.Authorization) to the app's project file.
2020-06-23 19:34:40 +08:00
* The `Microsoft.AspNetCore.Components.Authorization` namespace to the app's `_Imports.razor` file.
2019-06-27 02:58:38 +08:00
To handle authentication, use of a built-in or custom <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> service is covered in the following sections.
2019-06-27 02:58:38 +08:00
2020-06-19 21:24:40 +08:00
For more information on creating apps and configuration, see <xref:blazor/security/webassembly/index>.
2019-06-27 02:58:38 +08:00
### Blazor Server authentication
2019-06-27 02:58:38 +08:00
Blazor Server apps operate over a real-time connection that's created using SignalR. [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.
The built-in <xref:Microsoft.AspNetCore.Components.Authorization.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.
2020-06-19 21:24:40 +08:00
For more information on creating apps and configuration, see <xref:blazor/security/server/index>.
2019-06-27 02:58:38 +08:00
## AuthenticationStateProvider service
2020-05-26 23:19:36 +08:00
<xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> is the underlying service used by the <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> component and <xref:Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState> component to get the authentication state.
2019-06-27 02:58:38 +08:00
2020-06-23 19:34:40 +08:00
You don't typically use <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> directly. Use the [`AuthorizeView` component](#authorizeview-component) or [`Task<AuthenticationState>`](#expose-the-authentication-state-as-a-cascading-parameter) approaches described later in this article. The main drawback to using <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> directly is that the component isn't notified automatically if the underlying authentication state data changes.
2019-06-27 02:58:38 +08:00
2020-05-26 23:19:36 +08:00
The <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> service can provide the current user's <xref:System.Security.Claims.ClaimsPrincipal> data, as shown in the following example:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
@page "/"
@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
2019-06-27 02:58:38 +08:00
@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>
2019-06-27 02:58:38 +08:00
@code {
private string _authMessage;
private string _surnameMessage;
private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
2019-06-27 02:58:38 +08:00
{
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}";
2019-06-27 02:58:38 +08:00
}
else
{
_authMessage = "The user is NOT authenticated.";
2019-06-27 02:58:38 +08:00
}
}
}
```
If `user.Identity.IsAuthenticated` is `true` and because the user is a <xref:System.Security.Claims.ClaimsPrincipal>, claims can be enumerated and membership in roles evaluated.
2020-06-19 21:24:40 +08:00
For more information on dependency injection (DI) and services, see <xref:blazor/fundamentals/dependency-injection> and <xref:fundamentals/dependency-injection>.
2019-06-27 02:58:38 +08:00
## Implement a custom AuthenticationStateProvider
2020-05-26 23:19:36 +08:00
If the app requires a custom provider, implement <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> and override `GetAuthenticationStateAsync`:
2019-06-27 02:58:38 +08:00
```csharp
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;
public class CustomAuthStateProvider : AuthenticationStateProvider
2019-06-27 02:58:38 +08:00
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
2019-06-27 02:58:38 +08:00
{
var identity = new ClaimsIdentity(new[]
2019-06-27 02:58:38 +08:00
{
new Claim(ClaimTypes.Name, "mrfibuli"),
}, "Fake authentication type");
2019-06-27 02:58:38 +08:00
var user = new ClaimsPrincipal(identity);
2019-06-27 02:58:38 +08:00
return Task.FromResult(new AuthenticationState(user));
2019-06-27 02:58:38 +08:00
}
}
```
2020-06-23 19:34:40 +08:00
In a Blazor WebAssembly app, the `CustomAuthStateProvider` service is registered in `Main` of `Program.cs`:
2019-06-27 02:58:38 +08:00
```csharp
2020-01-30 03:36:27 +08:00
using Microsoft.AspNetCore.Components.Authorization;
...
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
2019-06-27 02:58:38 +08:00
```
In a Blazor Server app, the `CustomAuthStateProvider` service is registered in `Startup.ConfigureServices`:
```csharp
using Microsoft.AspNetCore.Components.Authorization;
...
services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
```
Using the `CustomAuthStateProvider` in the preceding example, all users are authenticated with the username `mrfibuli`.
2019-06-27 02:58:38 +08:00
## Expose the authentication state as a cascading parameter
2020-05-26 23:19:36 +08:00
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<`<xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationState>`>`:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
@page "/"
<button @onclick="LogUsername">Log username</button>
2019-06-27 02:58:38 +08:00
<p>@_authMessage</p>
2019-06-27 02:58:38 +08:00
@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
private string _authMessage;
2019-06-27 02:58:38 +08:00
private async Task LogUsername()
{
var authState = await authenticationStateTask;
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
_authMessage = $"{user.Identity.Name} is authenticated.";
2019-06-27 02:58:38 +08:00
}
else
{
_authMessage = "The user is NOT authenticated.";
2019-06-27 02:58:38 +08:00
}
}
}
```
If `user.Identity.IsAuthenticated` is `true`, claims can be enumerated and membership in roles evaluated.
2020-06-23 19:34:40 +08:00
Set up the `Task<`<xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationState>`>` cascading parameter using the <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeRouteView> and <xref:Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState> components in the `App` component (`App.razor`):
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData"
DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
2019-09-03 18:12:11 +08:00
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
2019-06-27 02:58:38 +08:00
```
[!INCLUDE[](~/blazor/includes/prefer-exact-matches.md)]
In a Blazor WebAssembly App, add services for options and authorization to `Program.Main`:
```csharp
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.
2019-06-27 02:58:38 +08:00
## 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 <xref:Microsoft.AspNetCore.Components.Authorization.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.
2019-06-27 02:58:38 +08:00
2020-05-26 23:19:36 +08:00
The component exposes a `context` variable of type <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationState>, which you can use to access information about the signed-in user:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
<AuthorizeView>
<h1>Hello, @context.User.Identity.Name!</h1>
<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:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
<AuthorizeView>
<Authorized>
<h1>Hello, @context.User.Identity.Name!</h1>
<p>You can only see this content if you're authorized.</p>
<button @onclick="SecureMethod">Authorized Only Button</button>
2019-06-27 02:58:38 +08:00
</Authorized>
<NotAuthorized>
<h1>Authentication Failure!</h1>
<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.
2019-06-27 02:58:38 +08:00
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.
2019-06-27 02:58:38 +08:00
Authorization conditions, such as roles or policies that control UI options or access, are covered in the [Authorization](#authorization) section.
2020-05-26 23:19:36 +08:00
If authorization conditions aren't specified, <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> uses a default policy and treats:
2019-06-27 02:58:38 +08:00
* Authenticated (signed-in) users as authorized.
* Unauthenticated (signed-out) users as unauthorized.
2021-01-23 08:30:52 +08:00
The <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> component can be used in the `NavMenu` component (`Shared/NavMenu.razor`) to display a list item (`<li>...</li>`) for a [`NavLink` component](xref:blazor/fundamentals/routing#navlink-and-navmenu-components) (<xref:Microsoft.AspNetCore.Components.Routing.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.
2021-03-06 21:30:02 +08:00
Apps created from a [Blazor project template](xref:blazor/project-structure) 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](xref:blazor/project-structure).
`Shared/LoginDisplay.razor`:
```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");
}
}
```
2021-03-06 21:30:02 +08:00
The following example is from the [Blazor Server project template](xref:blazor/project-structure) and uses ASP.NET Core Identity endpoints in the `Identity` area of the app to process Identity-related work.
`Shared/LoginDisplay.razor`:
```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>
```
2019-06-27 02:58:38 +08:00
### Role-based and policy-based authorization
2020-05-26 23:19:36 +08:00
The <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> component supports *role-based* or *policy-based* authorization.
2019-06-27 02:58:38 +08:00
2020-05-26 23:19:36 +08:00
For role-based authorization, use the <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Roles> parameter:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
<AuthorizeView Roles="admin, superuser">
<p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>
```
For more information, see <xref:security/authorization/roles>.
2020-05-26 23:19:36 +08:00
For policy-based authorization, use the <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Policy> parameter:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
<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 <xref:security/authorization/policies>.
These APIs can be used in either Blazor Server or Blazor WebAssembly apps.
2019-06-27 02:58:38 +08:00
2020-05-26 23:19:36 +08:00
If neither <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Roles> nor <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView.Policy> is specified, <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> uses the default policy.
2019-06-27 02:58:38 +08:00
### 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.
2019-06-27 02:58:38 +08:00
While authentication is in progress, <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> displays no content by default. To display content while authentication occurs, use the `<Authorizing>` tag:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
<AuthorizeView>
<Authorized>
<h1>Hello, @context.User.Identity.Name!</h1>
<p>You can only see this content if you're authenticated.</p>
</Authorized>
<Authorizing>
<h1>Authentication in progress</h1>
<p>You can only see this content while authentication is in progress.</p>
</Authorizing>
</AuthorizeView>
```
2020-05-26 23:19:36 +08:00
This approach isn't normally applicable to Blazor Server apps. Blazor Server apps know the authentication state as soon as the state is established. <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeViewCore.Authorizing> content can be provided in a Blazor Server app's <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> component, but the content is never displayed.
2019-06-27 02:58:38 +08:00
## [Authorize] attribute
The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) can be used in Razor components:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
@page "/"
@attribute [Authorize]
You can only see this if you're signed in.
```
> [!IMPORTANT]
2020-05-26 23:19:36 +08:00
> Only use [`[Authorize]`](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) 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 <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView> instead.
2019-06-27 02:58:38 +08:00
The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) also supports role-based or policy-based authorization. For role-based authorization, use the <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Roles> parameter:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
@page "/"
@attribute [Authorize(Roles = "admin, superuser")]
<p>You can only see this if you're in the 'admin' or 'superuser' role.</p>
```
2020-05-26 23:19:36 +08:00
For policy-based authorization, use the <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Policy> parameter:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
@page "/"
@attribute [Authorize(Policy = "content-editor")]
<p>You can only see this if you satisfy the 'content-editor' policy.</p>
```
2020-05-26 23:19:36 +08:00
If neither <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Roles> nor <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Policy> is specified, [`[Authorize]`](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) uses the default policy, which by default is to treat:
2019-06-27 02:58:38 +08:00
* Authenticated (signed-in) users as authorized.
* Unauthenticated (signed-out) users as unauthorized.
## Customize unauthorized content with the Router component
2020-05-26 23:19:36 +08:00
The <xref:Microsoft.AspNetCore.Components.Routing.Router> component, in conjunction with the <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeRouteView> component, allows the app to specify custom content if:
2019-06-27 02:58:38 +08:00
2021-01-31 20:53:05 +08:00
* The user fails an [`[Authorize]`](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) condition applied to the component. The markup of the [`<NotAuthorized>`](xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeRouteView.NotAuthorized?displayProperty=nameWithType) element is displayed. The [`[Authorize]`](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) attribute is covered in the [`[Authorize]` attribute](#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>`](xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeRouteView.Authorizing?displayProperty=nameWithType) element is displayed.
* Content isn't found. The markup of the [`<NotFound>`](xref:Microsoft.AspNetCore.Components.Routing.Router.NotFound?displayProperty=nameWithType) element is displayed.
2019-06-27 02:58:38 +08:00
2021-03-06 21:30:02 +08:00
In the default [Blazor Server project template](xref:blazor/project-structure), the `App` component (`App.razor`) demonstrates how to set custom content:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData"
DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<h1>Sorry</h1>
<p>You're not authorized to reach this page.</p>
<p>You may need to log in as a different user.</p>
</NotAuthorized>
<Authorizing>
<h1>Authorization in progress</h1>
<p>Only visible while authorization is in progress.</p>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
2019-09-03 18:12:11 +08:00
<LayoutView Layout="@typeof(MainLayout)">
<h1>Sorry</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
2019-06-27 02:58:38 +08:00
```
[!INCLUDE[](~/blazor/includes/prefer-exact-matches.md)]
The content of `<NotFound>`, `<NotAuthorized>`, and `<Authorizing>` tags can include arbitrary items, such as other interactive components.
2019-06-27 02:58:38 +08:00
If the `<NotAuthorized>` tag isn't specified, the <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeRouteView> uses the following fallback message:
2019-06-27 02:58:38 +08:00
```html
Not authorized.
```
## Notification about authentication state changes
2020-06-23 19:34:40 +08:00
If the app determines that the underlying authentication state data has changed (for example, because the user signed out or another user has changed their roles), a [custom `AuthenticationStateProvider`](#implement-a-custom-authenticationstateprovider) can optionally invoke the method <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider.NotifyAuthenticationStateChanged%2A> on the <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> base class. This notifies consumers of the authentication state data (for example, <xref:Microsoft.AspNetCore.Components.Authorization.AuthorizeView>) to rerender using the new data.
2019-06-27 02:58:38 +08:00
## Procedural logic
2020-05-26 23:19:36 +08:00
If the app is required to check authorization rules as part of procedural logic, use a cascaded parameter of type `Task<`<xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationState>`>` to obtain the user's <xref:System.Security.Claims.ClaimsPrincipal>. `Task<`<xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationState>`>` can be combined with other services, such as `IAuthorizationService`, to evaluate policies.
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
@using Microsoft.AspNetCore.Authorization
2019-06-27 02:58:38 +08:00
@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.
}
}
}
```
> [!NOTE]
2020-05-26 23:19:36 +08:00
> In a Blazor WebAssembly app component, add the <xref:Microsoft.AspNetCore.Authorization> and <xref:Microsoft.AspNetCore.Components.Authorization> namespaces:
>
2019-12-10 00:06:00 +08:00
> ```razor
> @using Microsoft.AspNetCore.Authorization
> @using Microsoft.AspNetCore.Components.Authorization
> ```
>
2020-06-23 19:34:40 +08:00
> These namespaces can be provided globally by adding them to the app's `_Imports.razor` file.
2019-06-27 02:58:38 +08:00
## Troubleshoot errors
Common errors:
2020-06-23 19:34:40 +08:00
* **Authorization requires a cascading parameter of type `Task\<AuthenticationState>`. Consider using `CascadingAuthenticationState` to supply this.**
2019-06-27 02:58:38 +08:00
* **`null` value is received for `authenticationStateTask`**
2020-06-23 19:34:40 +08:00
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:
2019-06-27 02:58:38 +08:00
2019-12-10 00:06:00 +08:00
```razor
2019-06-27 02:58:38 +08:00
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
2019-06-27 02:58:38 +08:00
...
</Router>
</CascadingAuthenticationState>
```
[!INCLUDE[](~/blazor/includes/prefer-exact-matches.md)]
2020-05-26 23:19:36 +08:00
The <xref:Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState> supplies the `Task<`<xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationState>`>` cascading parameter, which in turn it receives from the underlying <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider> DI service.
2019-06-27 02:58:38 +08:00
## Additional resources
* [Microsoft identity platform documentation](/azure/active-directory/develop/)
2019-06-27 02:58:38 +08:00
* <xref:security/index>
* <xref:security/authentication/windowsauth>
* [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