Blazor - Redirect non-authenticated user to login page

Blazor is a fantastic free and open-source framework for creating client web application / SPA using C#. There is two versions / hosting modes currently available : client-side and server-side. I won't make a complete Blazor presentation in this post, so you should check the official documentation for more information.

The goal is to redirect a non-authenticated user to a login page automatically. The code works for both client-side and server-side. For this we are going to create a component that will check the authentication state on each (protected) page.

First step is to create the component. I named it RedirectToLogin.razor, below is the code:

@inject NavigationManager Navigation

@code {

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

    protected override async Task OnInitializedAsync()
    {
        var authenticationState = await AuthenticationStateTask;

        if (authenticationState?.User?.Identity is null || !authenticationState.User.Identity.IsAuthenticated)
        {
            var returnUrl = Navigation.ToBaseRelativePath(Navigation.Uri);

            if (string.IsNullOrWhiteSpace(returnUrl))
                Navigation.NavigateTo("auth/login", true);
            else
                Navigation.NavigateTo($"auth/login?returnUrl={returnUrl}", true);
        }
    }

}

The component uses the AuthenticationState, so you'll need to implement your own AuthenticationStateProvider or use an existing one. The code only checks the user authentication (not any authorization check). If the user is not authenticated, it redirects him to the "auth/login" page or "auth/login?returnUrl=xxx" if the user tried to access a specific page.

The next step is to modify the App.razor file in order to load the component when the user isn't authorized:

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="routeData" DefaultLayout="@typeof(MainLayout)">
            <NotAuthorized>
                <RedirectToLogin></RedirectToLogin>
            </NotAuthorized>
        </AuthorizeRouteView>
    </Found>
    <NotFound>
        <CascadingAuthenticationState>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </CascadingAuthenticationState>
    </NotFound>
</Router>

Now if you try to access a protected page (using the Authorize attribute) without being authenticated, you should be redirected to the login page automatically!

P.S. This actual implementation doesn't prevent open redirect attacks, I suggest you to visit this documentation to learn about it: https://docs.microsoft.com/en-us/aspnet/core/security/preventing-open-redirects

Hope you guys enjoyed it! Please comment if you have any question or suggestion.