Correlation failed in net.core / asp.net identity / openid connect

55,214

Solution 1

I've finally found the solution, I´ll post here just in case somebody have a similar problem.

Looks like the principal problem was that my redirect URI was the same that the CallBackPath:

"CallbackPath": "/Account/SigninOidc"

var authProperties = _signInManager .ConfigureExternalAuthenticationProperties("AzureAD", Url.Action("SigninOidc", "Account", null, Request.Scheme));

Well, here is my corrected Startup.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BPT.PC.IdentityServer.Data;
using BPT.PC.IdentityServer.IdentityStore;
using BPT.PC.IdentityServer.Models;
using BPT.PC.IdentityServer.Web.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

namespace BPT.PC.IdentityServer.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentity<User, Role>()
                .AddUserStore<UserStore>()
                .AddRoleStore<RoleStore>()
                .AddDefaultTokenProviders();

            services.AddMemoryCache();
            services.AddDistributedMemoryCache();
            services.AddDbContext<IdentityServerDb>
                (options => options.UseSqlServer(Configuration.GetConnectionString("IdentityServerDb")));

            services
                .AddMvc();
            services
                .AddAuthentication(auth =>
                {
                    auth.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    auth.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    auth.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
                .AddCookie()
                .AddOpenIdConnect("AzureAD", "AzureAD", options =>
                {
                    Configuration.GetSection("AzureAD").Bind(options); ;
                    options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                    options.RemoteAuthenticationTimeout = TimeSpan.FromSeconds(120);
                    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.RequireHttpsMetadata = false;
                    options.SaveTokens = true;
                });

            services.AddSingleton(Configuration.GetSection("OpenIdConnectProviderConfiguration").Get<OpenIdConnectProviderConfiguration>());

        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Account}/{action=Login}/{id?}");
            });
        }
    }
}

And the finally implementation:

[HttpGet]
public IActionResult CorpLogin()
    {
        var authProperties = _signInManager
            .ConfigureExternalAuthenticationProperties("AzureAD",
            Url.Action("LoggingIn", "Account", null, Request.Scheme));

        return Challenge(authProperties, "AzureAD");
    }

The appsettings.json is the same.

Solution 2

If you're using Chrome against localhost, you may have run into a change in Chrome cookie-handling behaviour.

To verify, navigate to chrome://flags/ and change "Cookies without SameSite must be secure" to "Disabled".

If that change fixes the issue, and you want to fix it permanently (i.e. not rely on the chrome flags fix), this thinktecture post talks about the underlying issue and some fixes that you'll need for old iOS safari versions.

Solution 3

I was hitting this issue when using login with Google using .net Identity in Blazor on chrome. I had a new requirement to get it to work without https, it had been working fine with https.

I read in multiple answers variants of changing to

app.UseCookiePolicy(new CookiePolicyOptions()
{
    MinimumSameSitePolicy = SameSiteMode.None
});

I wish I'd read @dbruning's answer's article sooner. It mentioned in the article which isn't mentioned anywhere else: Please note: The setting SameSite=None will only work if the cookie is also marked as Secure and requires a HTTPS connection. The method's intellisense summary doesn't mention this which I think it definitely should...

So after that I just tried using SameSiteMode.Lax instead and it worked for me again. No other changes required from the default blazor project startup.cs

app.UseCookiePolicy(new CookiePolicyOptions()
{
    MinimumSameSitePolicy = SameSiteMode.Lax
});

Solution 4

I was having a very similar issue and none of the answers posted in this whole thread worked for me. I will describe how I reached the solution, in case it can help anybody else.

In my case, I have a web app with ASP.NET Core 3.1 (migrated from 1.x) and implemented authentication with the following snippet in the ConfigureServices method, from Startup.cs (as described here):

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));

The error thrown, as can be seen here, had a much simpler stack trace that the one described on this thread.

In the end, the problem was that cookies were not being set as secure. To do so, I just added the following code snippet right before the services.AddAuthentication pasted above.

services.Configure<CookiePolicyOptions>(options =>
{
    options.Secure = CookieSecurePolicy.Always;
});

Furthermore, I added a call to app.UseCookiePolicy() right before the call to app.UseRouting() in the Configure() method in Startup.cs.

Solution 5

Just FYI: I met same issue which cost me almost 1 day to investigate on this issue. finally I found that after remove below code from my startup.cs and everything is working: CookiePolicyOptions cookiePolicy = new CookiePolicyOptions() { Secure = CookieSecurePolicy.Always, };

I am following up this with Microsoft support team, will update this back if get got any response.

Share:
55,214
Augusto Diaz
Author by

Augusto Diaz

Updated on July 09, 2022

Comments

  • Augusto Diaz
    Augusto Diaz almost 2 years

    I getting this error when a Azure AD user login (I able to get the user´s claims after), im using a combination of OpenIdConnect, with asp.net Identity core over net.core 2.0

    An unhandled exception occurred while processing the request. Exception: Correlation failed. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+d__12.MoveNext()

    The trace:

    Exception: Correlation failed. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+d__12.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+d__6.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+d__7.MoveNext()

    Correlation Failed

    Here is my Startup.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using BPT.PC.IdentityServer.Data;
    using BPT.PC.IdentityServer.IdentityStore;
    using BPT.PC.IdentityServer.Models;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Authentication.OpenIdConnect;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    
    namespace BPT.PC.IdentityServer.Web
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddIdentity<User, Role>()
                    .AddUserStore<UserStore>()
                    .AddRoleStore<RoleStore>()
                    .AddDefaultTokenProviders();
    
                services.AddMemoryCache();
                services.AddDistributedMemoryCache();
                services.AddDbContext<IdentityServerDb>(options => options.UseSqlServer(Configuration.GetConnectionString("IdentityServerDb")));
    
                services.AddMvc();
                services.AddAuthentication(auth =>
                {
                    auth.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    auth.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    auth.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
                .AddCookie()
                .AddOpenIdConnect("AzureAD", opts =>
                {
                    Configuration.GetSection("OpenIdConnect").Bind(opts);
                    opts.RemoteAuthenticationTimeout = TimeSpan.FromSeconds(120);
                    opts.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
                    opts.CorrelationCookie = new Microsoft.AspNetCore.Http.CookieBuilder
                    {
                        HttpOnly = false,
                        SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None,
                        SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.None,
                        Expiration = TimeSpan.FromMinutes(10)
                    };
    
                    opts.Events = new OpenIdConnectEvents()
                    {
                        OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
                        OnRemoteFailure = OnRemoteFailure,
                        OnAuthorizationCodeReceived = OnAuthorizationCodeReceived
                    };
                    //opts.Events = new OpenIdConnectEvents
                    //{
                    //    OnAuthorizationCodeReceived = ctx =>
                    //    {
                    //        return Task.CompletedTask;
                    //    }
                    //};
                });
    
                //services.ConfigureApplicationCookie(options =>
                //{
                //    // Cookie settings
                //    options.Cookie.HttpOnly = true;
                //    options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
                //    options.SlidingExpiration = true;
                //});
            }
    
            private Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext arg)
            {
                return Task.FromResult(0);
            }
    
            private Task OnRemoteFailure(RemoteFailureContext arg)
            {
                return Task.FromResult(0);
            }
    
            private Task OnRedirectToIdentityProvider(RedirectContext arg)
            {
                return Task.FromResult(0);
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseBrowserLink();
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                }
    
                app.UseStaticFiles();
                app.UseAuthentication();
    
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Account}/{action=Login}/{id?}");
                });
            }
        }
    }
    

    My appsettings.json:

    {
      "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
          "Default": "Warning"
        }
      },
    
      "ConnectionStrings": {
        "IdentityServerDb": "Server=localhost;Database=IdentityServer;Trusted_Connection=True;MultipleActiveResultSets=true"
      },
    
      "OpenIdConnect": {
        "ClientId": "xxxxx",
        "Authority": "https://login.microsoftonline.com/xxxxx/",
        "PostLogoutRedirectUri": "/Account/SignoutOidc",
        "CallbackPath": "/Account/SigninOidc",
        "UseTokenLifetime": true,
        "RequireHttpsMetadata": false,
        //"ResponseType": "code id_token",
        "ClientSecret": "xxx",
        "Resource": "https://graph.microsoft.com/"
      }
    }
    

    And the implementation:

    [HttpGet]
    public IActionResult CorpLogin()
    {
      var authProperties = _signInManager
                    .ConfigureExternalAuthenticationProperties("AzureAD",
         Url.Action("SigninOidc", "Account", null, Request.Scheme));
    
       return Challenge(authProperties, "AzureAD");
    }
    
    [HttpPost]
    public IActionResult SigninOidc([FromForm]object data)
    {
    //this never runs
       return Ok();
    }
    
  • hbulens
    hbulens over 3 years
    So did you get a response from MS?
  • joe
    joe over 3 years
    Thanks, this combined with Riyaz's answer solved it for me: I switched to a secure local endpoint, and Chrome properly forwarded the cookies.
  • Charles d'Avernas
    Charles d'Avernas over 3 years
    You rule, man, many thanks. Was fighting that one for a couple of hours until I found your answer!
  • Timo Hermans
    Timo Hermans over 3 years
    This fixed it for me. Because I'm not exposing my identity server (keycloak) to the outside world, I don't want to set up HTTPS for nothing. Thanks @James!
  • Jess
    Jess over 3 years
    Can you provide the solution from thinktecture? I think this is somewhat of a link-only answer.
  • Pieterjan
    Pieterjan almost 3 years
    Where exactly in your middleware pipeline did you put this? I'm asking since the order of middleware registration is important.
  • James
    James almost 3 years
    My configure method looks like this: app.UseHsts(); app.UseStaticFiles(); app.UseRouting(); app.UseCookiePolicy(new CookiePolicyOptions() { MinimumSameSitePolicy = SameSiteMode.Lax }); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(....)
  • Ibrahim ULUDAG
    Ibrahim ULUDAG over 2 years
    For me, "Enable removing SameSite=None cookies" Enabled fixed my problem
  • Angelo Bernardi
    Angelo Bernardi over 2 years
    not quite the answer I needed, but got me to realize that I wasn't using HTTPS
  • Bukk94
    Bukk94 over 2 years
    This! This answer right here! I spent couple hours trying to fix this Correlation failed problem and nothing worked. But this solution, with pretty nice and straightforward step-by-step guide solved it for me. Thank you!
  • Admin
    Admin over 2 years
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
  • Aoguye
    Aoguye about 2 years
    You rock! This was my exact issue. Spent about a day trying to figure this out.
  • mfsumption
    mfsumption about 2 years
    This worked for me in Configure(), but not at first because I originally had this option set up in ConfigureServices like services.Configure<CookiePolicyOptions>(options => { options.MinimumSameSitePolicy = SameSiteMode.None; }); which was not working when testing dev with localhost.