简体   繁体   中英

Blazor SPA authenticating with Auth0 fails on callback

I'm writing a basic Blazor app following this blog post and I've struck difficulty with the /callback redirect in the actual Blazor application. The error I'm seeing is

OpenIdConnectProtocolException: Message contains error: 'invalid_grant', error_description: 'Invalid authorization code', error_uri: 'error_uri is null'

at the /callback URL.

ASP.Net Core 异常屏幕

If I check the logs, I can see there are three events happening at the Auth0 end:

  • Successful login
  • Authorization Code for Access Token
  • Invalid authorization code

Each straight after the other. I can see those authorization codes do match between the “Success Exchange” and the “Failed Exchange” entries.

I can see Auth0 authentication has actually taken place, and if I browse to other pages in my app, I can see I have logged in successfully, but that initial callback to the /callback URL stops things in their tracks. Is there something missing in the middleware / Startup.cs code, or are there additional things to check for the Auth0 application settings?

For the avoidance of doubt, I've copied the blog post code exactly and can confirm the application does authenticate and log me in. Here's the code in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddHttpContextAccessor();
    services.AddSingleton<WeatherForecastService>();
    services.AddSingleton<ClubInformationService>();

    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    // Add authentication services
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect("Auth0", options =>
    {
        // Set the authority to your Auth0 domain
        options.Authority = $"https://{Configuration["Auth0:Domain"]}";

        // Configure the Auth0 Client ID and Client Secret
        options.ClientId = Configuration["Auth0:ClientId"];
        options.ClientSecret = Configuration["Auth0:ClientSecret"];

        // Set response type to code
        options.ResponseType = "code";

        // Configure the scope
        options.Scope.Clear();
        options.Scope.Add("openid");

        // Set the callback path, so Auth0 will call back to http://localhost:3000/callback
        // Also ensure that you have added the URL as an Allowed Callback URL in your Auth0 dashboard
        options.CallbackPath = new PathString("/callback");

        // Configure the Claims Issuer to be Auth0
        options.ClaimsIssuer = "Auth0";

        options.Events = new OpenIdConnectEvents
        {
        // handle the logout redirection
        OnRedirectToIdentityProviderForSignOut = (context) =>
            {
            var logoutUri = $"https://{Configuration["Auth0:Domain"]}/v2/logout?client_id={Configuration["Auth0:ClientId"]}";

            var postLogoutUri = context.Properties.RedirectUri;
            if (!string.IsNullOrEmpty(postLogoutUri))
            {
                if (postLogoutUri.StartsWith("/"))
                {
                // transform to absolute
                var request = context.Request;
                postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
                }
                logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri)}";
            }

            context.Response.Redirect(logoutUri);
            context.HandleResponse();

            return Task.CompletedTask;
        } //... etc.

Not sure that it adds a lot to the problem, but the diagnostics leading up to the exception being thrown look like the following:

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 POST https://localhost:5001/callback application/x-www-form-urlencoded 396
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[10]
      AuthenticationScheme: Cookies signed in.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 634.9692ms 302
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 POST https://localhost:5001/callback application/x-www-form-urlencoded 396
fail: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[52]
      Message contains error: 'invalid_grant', error_description: 'Invalid authorization code', error_uri: 'error_uri is null', status code '403'.
fail: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[17]
      Exception occurred while processing message.
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_grant', error_description: 'Invalid authorization code', error_uri: 'error_uri is null'.
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RedeemAuthorizationCodeAsync(OpenIdConnectMessage tokenEndpointRequest)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
info: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[4]
      Error from RemoteAuthentication: Message contains error: 'invalid_grant', error_description: 'Invalid authorization code', error_uri: 'error_uri is null'..
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
System.Exception: An error was encountered while handling the remote login.
 ---> Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_grant', error_description: 'Invalid authorization code', error_uri: 'error_uri 
is null'.

In case you want to add Auth0 in a Blazor WebAssembly project, you could just use the documentation from Microsoft.

However when using this for Auth0, there is one catch:

Or you can use my NuGet package:WebAssembly.Authentication.Auth0 which does support the Audience parameter.

More details van be found here: https://github.com/StefH/Blazor.WebAssembly.Authentication.Auth0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM