Search code examples
c#openid-connectidentityserver4infinite-loop.net-8.0

.NET 8 upgrade: OIDC correlation failure with IdentityServer4 on HTTP when using machine name instead of localhost


We’re running an older Identity server on .NET Framework 4.6.2 with IdentityServer4, which we plan to replace early next year. In the meantime, though, we’ve had to upgrade our primary application to .NET 8 to stay current with LTS support. Since making the upgrade, we’re seeing an issue: the app works perfectly over both HTTP and HTTPS when accessed via localhost or 127.0.0.1, but when we use the machine name (e.g., http://machine-name) over HTTP, it fails.

Specifically, when accessing the app with the machine name over HTTP, the OIDC flow immediately goes to AddOpenIdConnect -> Events -> OnRemoteFailure. We’re seeing missing cookies, with the error message "Correlation failed," and it just loops back to / endlessly. Switching to HTTPS solves the issue, but due to current limitations, we really need this to work over HTTP.

Here’s what I’ve tried so far:

Setting SameSite=None for cookies in multiple locations (CorrelationCookie.SameSite, Cookie.SameSite, etc.). Explicitly setting AllowedHosts for our machine name in Program.cs. Adjusting cookie configurations like Cookie.Domain and Cookie.SecurePolicy for both the main app and IdentityServer. Making sure CORS policies allow the machine name over HTTP.

Given this setup, has anyone run into similar cookie or OIDC issues specifically tied to .NET 8 changes? Are there new settings or behaviors in .NET 8 that would affect HTTP cookie transfers between apps on the same machine when using different hostnames?

Any insights on unexpected changes in OIDC handling or cookie policies that might help us get this working without HTTPS would be greatly appreciated!


Solution

  • I ended up solving this by adding SecurePolicy None and SameSite Lax to the nonce and correlation cookies from my main application if the instance is running http. Answer can be seen below:

    var authority = Configuration["Authority"];
    var authorityUri = new Uri(authority);        
    
    services.AddAuthentication(c =>
    {
        c.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        c.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
       .AddCookie((cookieSettings) =>
       {
           cookieSettings.AccessDeniedPath = "/StatusCode/401";
           cookieSettings.ExpireTimeSpan = TimeSpan.FromMinutes(appSettings.SessionTimeoutSlidingMinutes ?? 15);
           cookieSettings.SlidingExpiration = true;
           cookieSettings.Cookie.HttpOnly = true;
           cookieSettings.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
       })
       .AddOpenIdConnect((oidcSettings) =>
       {
           if (string.IsNullOrEmpty(authority))
           {
               throw new ArgumentNullException("Authority cannot be null or empty");
           }
    
           if (authorityUri.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase))
           {
               oidcSettings.NonceCookie.SecurePolicy = CookieSecurePolicy.None;
               oidcSettings.NonceCookie.SameSite = SameSiteMode.Lax;
               oidcSettings.CorrelationCookie.SecurePolicy = CookieSecurePolicy.None;
               oidcSettings.CorrelationCookie.SameSite = SameSiteMode.Lax;
           }