Skip to content

Enhance documentation for RevalidatingServerAuthenticationStateProvider in Blazor Apps #36662

@MarvinKlein1508

Description

@MarvinKlein1508

[EDIT by guardrex to add the metadata]

I know that you guys planning on improving the authentification docs for Blazor and I think I've found another bit which needs improvement.

I want to check if my current validation state is still valid and I came accross this docs here:

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-10.0&tabs=visual-studio#additional-security-abstractions

So I implemented my custom AuthenticationStateProvider and inherited from RevalidatingServerAuthenticationStateProvider because I'm using a Blazor Web App with global Server interactivity. Here is my current implementation:

public sealed class HSOnlineAuthenticationStateProvider : RevalidatingServerAuthenticationStateProvider
{
    private readonly IDbConnectionFactory _dbFactory;
    private readonly UserRepository _userRepository;

    public HSOnlineAuthenticationStateProvider(IDbConnectionFactory dbFactory, UserRepository userRepository, ILoggerFactory loggerFactory) : base(loggerFactory)
    {
        _dbFactory = dbFactory;
        _userRepository = userRepository;
    }

    protected override TimeSpan RevalidationInterval => TimeSpan.FromSeconds(5);

    protected override async Task<bool> ValidateAuthenticationStateAsync(AuthenticationState authenticationState, CancellationToken cancellationToken)
    {
        Console.WriteLine("Authentification validation");

        Claim? claim = authenticationState.User.FindFirst("userId");

        if (claim is null)
        {
            // TODO: LOGOUT
            return false;
        }

        var userId = Convert.ToInt32(claim.Value, CultureInfo.InvariantCulture);
        using var connection = await _dbFactory.CreateConnectionAsync(cancellationToken);
        User? result = await _userRepository.GetAsync(userId, connection, cancellationToken: cancellationToken);

        if (result is null)
        {
            // User has been deleted from the database
            // TODO: LOGOUT
            return false;
        }

        if (!result.IsActive)
        {
            // User has been deactivated by an admin
            // TODO: LOGOUT
            return false;
        }

        return true;
    }

    // TODO: CHECK STATE ON FIRST PAGE LOAD IN ORDER TO NOT HAVE TO WAIT FOR RevalidationInterval

}

I login now into my app and set my user to disabled via SQL. After 10 seconds I can indeed see that I'm being redirected to the Account/Login page but when I go back to my auth required page then I see that I'm still logged in and after 10 seconds I get redirected again.

I'm using a cookie based authentifcation like this:

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);

builder.Services.AddScoped<AuthenticationStateProvider, HSOnlineAuthenticationStateProvider>();
builder.Services.AddCascadingAuthenticationState();

/* .... */
app.UseAuthentication();
app.UseAuthorization();

/* ... */
var accountGroup = app.MapGroup("/Account");

accountGroup.MapGet("/Logout", async (HttpContext context) =>
{
    await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    return Results.LocalRedirect("/Account/Login");
});

My main question know is how can I handle the TODOs from my HSOnlineAuthenticationStateProvider. Should the Logout be handled by the login page or is there any way todo this via the HSOnlineAuthenticationStateProvider. And how can I check if the authentification is still valid when the user first loads the page so I don't have to wait for my TimeSpan to kick in?

And lastly if it's valid how can I reseed the claims in case something has been changed within my user e.g. the roles without the need to logout and log in again?

CC: @guardrex @danroth27 @javiercn


Document Details

Do not edit this section. It is required for learn.microsoft.com ➟ GitHub issue linking.

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Triage

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions