Blazor authentication and authorisation - redirect to login
Blazor uses ASP.NET Core authentication to allow you to control access to areas within your site. A common scenario is to redirect unauthenticated users to the login page.
Authentication and authorisation
Blazor uses the existing ASP.NET Core authentication mechanisms. The scope of this article isn’t to go through all this in detail as it is well documented in the docs and various blog posts. The case we are going to look at is redirecting an unauthenticated user to the login page.
Handling unauthorised
When you create a new Blazor project with authentication your App.razor
will look something like this.
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>
A couple of things here, firstly, CascadingAuthenticationState
. This provides a cascading parameter to all descendant components. The parameter supplied is Task<AuthenticationState>
. From this you can get access to the user (ClaimsPrincipal
) and do things like checking if the user is authenticated.
[CascadingParameter]
protected Task<AuthenticationState> AuthState { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
ClaimsPrincipal user = (await AuthState).User;
if (user.Identity.IsAuthenticated)
{
Console.WriteLine($"{user.Identity.Name} is authenticated.");
}
}
Second is the AuthorizeRouteView
component. This behaves the same as the RouteView
, displaying pages that match the specified route. Additionally, it will only display pages that the user is authorised to see. The AuthorizeRouteView
also contains the same CascadingParameter
as the CascadingAuthenticationState
component.
The AuthorizeRouteView
has two tags in which you can add content to, NotAuthorized
and Authorizing
. They are used like this.
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<p>Hey! You're not allowed in here.</p>
</NotAuthorized>
<Authorizing>
<p>Just checking with the boss you can come in.</p>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>
On page load, whilst checking the user is authorised to view the page, the Authorizing
content will be shown. If the user is not authorised then the NotAuthorized
content will be shown. If you do not add any content to either of these tags then default content will be shown. "Authorizing..." and "Not authorized".
The final piece is to use the [Authorize]
attribute on pages which you need to restrict access. This attribute can only be used on components that have the @page
directive. This is because they are the only components that the router knows about.
e.g.
@page "/user-profile"
@attribute [Authorize]
Roles
or Policy
can also be used with the [Authorize]
attribute.
e.g.
@page "/accounts"
@attribute [Authorize(Roles = "finance")]
or
@page "/membership/requests"
@attribute [Authorize(Policy = "moderator")]
How to redirect
In the example above, we put html directly into the tags, however components are also allowed. This means we can create a component to redirect to the login page, or any page we wish. First, create a component to do the redirect.
RedirectToLogin.cs
public class RedirectToLogin : ComponentBase
{
[Inject]
protected NavigationManager NavigationManager { get; set; }
protected override void OnInitialized()
{
NavigationManager.NavigateTo("login");
}
}
Then add the component to the NotAuthorized
tag.
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
<Authorizing>
<p>Just checking with the boss you can come in.</p>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>
Finally, add the [Authorize]
attribute to pages which require authentication.
Now, if you browse to a page and you have not logged in you are automatically redirected to the login page!
Summary
In this post we have shown how to use the authentication and authorisation mechanisms in Blazor to restrict pages and how to redirect unauthenticated users to the login page.