Search code examples
asp.netblazorauth0blazor-client-side

Login prompt after logout using Auth0 in ASP.NET Blazor Web Assembly client-side app


I've just begun constructing a simple web assembly ASP.NET client-side web app with authentication powered by Auth0.

There are a few articles I've found walking you through the steps needed to do this, like this one: https://auth0.com/blog/what-is-blazor-tutorial-on-building-webapp-with-authentication/

Unfortunately since many of them were written it seems that Blazor client-side projects were ported from targeting .NET Core to .NET Standard and as a result it's not possible to install the NuGet Package needed: Microsoft.AspNetCore.Authentication.OpenIdConnect

Instead I found a tutorial from Microsoft that uses Microsoft.AspNetCore.Components.WebAssembly.Authentication which wraps some Javascript code needed to handle the authentication flow: https://learn.microsoft.com/en-us/aspnet/core/security/blazor/webassembly/standalone-with-authentication-library?view=aspnetcore-3.1

I managed to get it working but when I log out and go to log in again the app automatically authenticates without taking me to the Auth0 login page. According to the OpenID Connect specification I need to send an optional prompt parameter set to login to force the showing of a login screen (what I would expect as a user after logging out).

The aforementioned Microsoft.AspNetCore.Authentication.OpenIdConnect library has the ability to set this parameter: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.openidconnect.openidconnectoptions.prompt?view=aspnetcore-3.0

The WebAssembly library from what I can tell does not: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.webassembly.authentication.oidcprovideroptions?view=aspnetcore-3.1

Does anyone know a workaround?

My Program.cs is as follows:

public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");

            builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

            builder.Services.AddOidcAuthentication(options =>
            {
                options.ProviderOptions.Authority = $"https://{builder.Configuration["Auth0:Domain"]}";
                options.ProviderOptions.ClientId = builder.Configuration["Auth0:ClientId"];
                options.ProviderOptions.ResponseType = builder.Configuration["Auth0:ResponseType"];
                options.ProviderOptions.PostLogoutRedirectUri = "/";
            });

            await builder.Build().RunAsync();
        }
    }

Solution

  • I found that I need to explicitly call the logout endpoint: https://auth0.com/docs/api/authentication?javascript#logout

    For now I have created a Logout component and added the logic inside - I hope there is a better way (e.g. configuring this as part of AddOidcAuthentication but I couldn't figure it out).

    @inject NavigationManager Navigation
    @inject SignOutSessionStateManager SignOutManager
    @inject BaseAddress BaseAddress
    @inject Auth0Config Auth0Config
    
    <AuthorizeView>
        <Authorized>
            <button class=@($"{CssClass} btn btn-link") @onclick=BeginSignOut>Log out</button>
        </Authorized>
    </AuthorizeView>
    
    @code {
        
        [Parameter]
        public string CssClass { get; set; }
    
        private async Task BeginSignOut()
        {
            await SignOutManager.SetSignOutState();
            Navigation.NavigateTo($"{Auth0Config.Authority}/v2/logout?client_id={Auth0Config.ClientId}&returnTo={BaseAddress.Url}authentication/logout");
        }
    }