Search code examples
c#angularidentityserver4openid-connect

Angular login "Exception: Correlation failed. Unknown location"


My application is composed of 2 elements: IdentityServer4 host (Asp.NET Core 2.2 application with Asp.NET identity) listening on http://localhost:5000 Angular client app (Angular v.7.2.12) listening on http://localhost:5002

I want the angular client to authenticate against IS4: the login form id the one hosted in IS4 pages. After successful login, the user should be redirected back to the angular page. For angular oidc integration, I followed the project: https://github.com/elanderson/Angular-Core-IdentityServer

The login actually works well (I see the correct token returned by IS4 and no errors in IS4 logs), but redirect URI doesn’t work. Instead of returning to the original angular page (http://localhost/5002) I have the exception “Correlation failed. Unknown location”

I tried to do the same login with another ASP.NET Core test application and it works, so it seems to be related to the angular integration.

Exception Stack

Exception Headers

IS4 in-memory angular client configuration

new Client
            {
                ClientId = "gekoo.webSPA",
                ClientName = "MVC SPA Client",
                AllowedGrantTypes = GrantTypes.Implicit,
                AllowAccessTokensViaBrowser = true,

                RedirectUris = { "http://localhost:5002/signin-oidc" },                    
                PostLogoutRedirectUris = { "http://localhost:5002" },},

                AllowedCorsOrigins = { "http://localhost:5002" },

                AllowedScopes = new List<string>
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "api1"
                },

                AlwaysIncludeUserClaimsInIdToken = true,

                RequireConsent = false,
            },

Aspnet core client app configuration in Startup.cs ConfigureServices

services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            //options.DefaultChallengeScheme = "oidc";
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
            .AddCookie()
            .AddOpenIdConnect(options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ResponseType = "code id_token";
                options.Scope.Add("gekoo.webSPA");
                options.Scope.Add("offline_access");
                options.ClientId = "gekoo.webSPA";

                options.ClaimActions.Remove("auth_type");
                options.GetClaimsFromUserInfoEndpoint = true;
                options.SaveTokens = true;
            });

Angular client oidc configuration:

const openIdImplicitFlowConfiguration = new OpenIDImplicitFlowConfiguration();
openIdImplicitFlowConfiguration.stsServer = authUrl;

openIdImplicitFlowConfiguration.redirect_url = originUrl + '/signin-oidc';
console.log('redirect_url=' + openIdImplicitFlowConfiguration.redirect_url);

openIdImplicitFlowConfiguration.client_id = 'gekoo.webSPA';
openIdImplicitFlowConfiguration.response_type = 'id_token token';
openIdImplicitFlowConfiguration.scope = 'openid profile api1';

openIdImplicitFlowConfiguration.post_logout_redirect_uri = originUrl + '/home';
console.log('post_logout_redirect_uri=' + openIdImplicitFlowConfiguration.post_logout_redirect_uri);

openIdImplicitFlowConfiguration.forbidden_route = '/forbidden';
openIdImplicitFlowConfiguration.unauthorized_route = '/unauthorized';
openIdImplicitFlowConfiguration.auto_userinfo = true;
openIdImplicitFlowConfiguration.log_console_warning_active = true;
openIdImplicitFlowConfiguration.log_console_debug_active = true;
openIdImplicitFlowConfiguration.max_id_token_iat_offset_allowed_in_seconds = 10;

const authWellKnownEndpoints = new AuthWellKnownEndpoints();
//authWellKnownEndpoints.setWellKnownEndpoints(
authWellKnownEndpoints.issuer = authUrl;

authWellKnownEndpoints.jwks_uri = authUrl + '/.well-known/openid-configuration/jwks';
authWellKnownEndpoints.authorization_endpoint = authUrl + '/connect/authorize';
authWellKnownEndpoints.token_endpoint = authUrl + '/connect/token';
authWellKnownEndpoints.userinfo_endpoint = authUrl + '/connect/userinfo';
authWellKnownEndpoints.end_session_endpoint = authUrl + '/connect/endsession';
authWellKnownEndpoints.check_session_iframe = authUrl + '/connect/checksession';
authWellKnownEndpoints.revocation_endpoint = authUrl + '/connect/revocation';
authWellKnownEndpoints.introspection_endpoint = authUrl + '/connect/introspect';
authWellKnownEndpoints.introspection_endpoint = authUrl + '/connect/introspect';

Solution

  • You mixed up two different approaches: registered "gekoo.webSPA" client with "GrantTypes.Implicit" in IdSrv (and Angular), but also created another (ASP.NET MVC) client app, having the same name, but ResponseType = "code id_token". So your Angular app triggers a challenge, but the response gets handled by ASP.Net backend, which leads to the failure. Actually you can host your Angular without any MVC back at all, or use this QA as a reference.