Blazor SPA authenticating with Auth0 fails on callback

柔情痞子 提交于 2020-07-23 08:14:46

问题


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.

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'.

回答1:


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:

  • It's not possible to provide the Audience, this means that you need to apply this work-around : Auth0-why-is-it-necessary-to-pass-the-audience-parameter-to-receive-a-jwt

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



来源:https://stackoverflow.com/questions/58983153/blazor-spa-authenticating-with-auth0-fails-on-callback

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!