How to get the current user in Blazor C#

This blog post will firstly outline how to determine if the user is logged in to a Blazor Server C# application. If so, we will then look at how to get the details of the user that is logged in, including the user Id, user email, user name and all other fields of the default IdentityUser implementation. Finally, we will look at securing the page so that only users that are logged in may see it. Users that are not logged in will be redirected to the login page. 

How to check if the user is authenticated in a Blazor Server application

Blazor Server apps have a built-in AuthenticationStateProvider service which obtains information of the current authentication state from HttpContext.User. However, this service does not get notified immediately should the authentication state change. It is for this reason we do not interact with this service directly. We can instead expose the authentication state by using Task<AuthenticationState>

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

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

    protected override async Task OnInitializedAsync()
    {
        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated)
        {
            // User is logged in
        }
        else
        {
            // User is not logged in
        }
    }

    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

How to get the current user in a Blazor Server application

Now that we have obtained the authentication state data, we can use this ClaimsPrincipal in order to get the current user. We will do this through the UserManager service. We must first add a using statement for the namespace of this service which is Microsoft.AspNetCore.Identity. I am using the default implementation of IdentityUser so UserManager is injected of this type. We then pass the authentication state data into GetUserAsync which retrieves the current user, from which we can access any of its properties. 

@page "/counter"
@using Microsoft.AspNetCore.Identity 

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

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

    [Inject]
    UserManager<IdentityUser> userManager { get; set; }

    protected override async Task OnInitializedAsync()
    {
        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated)
        {
            var currentUser = await userManager.GetUserAsync(user);
            var currentUserId = currentUser.Id;
            var currentUserEmail = currentUser.Email;
            var currentUserPhone = currentUser.PhoneNumber;
            var currentUserEmailConfirmed = currentUser.EmailConfirmed;
        }
        else
        {
            // User is not logged in
        }
    }

    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

How to redirect the user to the login page if they are not authenticated in a Blazor Server application

We must first secure the page from users that are not authenticated. This can be done by using the [Authorize] attribute. Note that this attribute should only be used on @page components. For child components, you can authorize certain parts of a component by using the <AuthorizeView> component.

@attribute [Authorize]

Whilst the result certainly stops unauthenticated users from accessing the page, the result certainly leaves a lot to the imagination. 

We can change the text shown to unauthorized users by going to the App component and modifying the <NotFound> content within <AuthorizeRouteView>.

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

We can modify the App component further and instead of displaying a piece of text to unauthorized users, instead we can redirect them to the login page. We need to inject NavigationManager in order to do this. Don’t forget to set forceLoad as true in order to bypass the client-side routing otherwise you may end up with a 404. 

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    @{ NavigationManager.NavigateTo("identity/account/login", true); }
                </NotAuthorized>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

@code{
    [Inject]
    NavigationManager NavigationManager { get; set; }
}
Scroll to Top