Microsoft OIDC library OnAuthorizationCodeReceived getting fired twice

srijith 1 Reputation point
2021-11-04T14:27:53.097+00:00

I have an OIDC application, which was giving me correlation error for some time. We have managed to resolve it by passing correlation cookie properly. Our infrastructure has the following network topology.

Openshift Container(OIDC App) -> Reverser Proxy/Api gateway -> Identity Provider.

If we use boiler plate code, the callback path picks up the host of openshift, hence the redirection not working correctly. We are now building the url on the event onRedirectToIdentitityProvider.

We are also using OnAuthorizationCodeReceived event to make the /Token call as the default configuration was not working out.

We get callback properly with Authorization code but we see onAuthorizationCodeRecieved getting fired twice. This is happening only in the test environment with the reverse proxy set up. In development box, there is no issue but it does not have the reverse proxy set up(Now, reverse proxy is just a passthrough so not sure how that could break things).

Code Snippet Below

 public void ConfigureServices(IServiceCollection services)
        {
            string _authorityAPI = Configuration.GetValue<string>("authority");
            string _org = Configuration.GetValue<string>("orgDomain");
            string clientId = Configuration.GetValue<string>("ClientId");
            string clientSecret = Configuration.GetValue<string>("ClientSecret");


            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
                options.Secure = CookieSecurePolicy.Always;
                options.HandleSameSiteCookieCompatibility();



            services.AddAuthentication(auth =>
            {
                auth.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                auth.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
                auth.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.LoginPath = "/Profile/Index/";
                options.LogoutPath = "/Profile/Logout/";
            })

            .AddOpenIdConnect(options =>
            {

                options.ClientId = clientId;
                options.ClientSecret = clientSecret;
                options.Authority = Configuration.GetValue<string>("Authority");
                options.CallbackPath = "/web/auth/callback";
                options.ResponseType = OpenIdConnectResponseType.Code;
                options.MetadataAddress = string.Format("{0}/.well-known/openid-configuration", _authorityAPI);
                options.TokenValidationParameters.ValidateIssuer = false;
                //options.GetClaimsFromUserInfoEndpoint = true;
                options.RequireHttpsMetadata = true;
                options.SaveTokens = true;
                options.Scope.Add("openid");
                options.Scope.Add("email");
                options.Scope.Add("profile");
                options.NonceCookie.SameSite = SameSiteMode.None;
                options.CorrelationCookie.SameSite = SameSiteMode.None;
                options.NonceCookie.Path = "/";
                options.CorrelationCookie.Path = "/";

                options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.MetadataAddress, new ApiGatewayRetriever(_authorityAPI, _org));
                options.Events = new OpenIdConnectEvents()
                {
                    OnRedirectToIdentityProvider = (context) =>
                    {
                        if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                        {

                                context.ProtocolMessage.Parameters.Clear();
                                context.ProtocolMessage.IssuerAddress = centralLogin + "?RedirectURL=https://" + GetRequestHostName(context, Configuration);
                                return Task.FromResult(0);

                        }

                        return Task.FromResult(0);
                    }
                    ,
                    OnAuthorizationCodeReceived = authorizationCtx =>
                    {
                        try
                        {
                            BellLogger.WriteLog("OnAuthorizationCodeReceived start:" + authorizationCtx.TokenEndpointRequest.Code, Framework.Common.LogType.Info);

                            HttpClient httpClient = new HttpClient();
                            TokenClientOptions tokenClientOptions = new TokenClientOptions()
                            {
                                ClientId = clientId,
                                ClientSecret = clientSecret,
                                Address = string.Format("{0}/v1/token", _authorityAPI)
                            };
                            var tokenClient = new TokenClient(httpClient, tokenClientOptions);

                            var tokenResponse = await tokenClient.RequestAuthorizationCodeTokenAsync(authorizationCtx.TokenEndpointRequest.Code, authorizationCtx.TokenEndpointRequest.RedirectUri).Result;
                    authorizationCtx.HandleCodeRedemption(tokenResponse.AccessToken, tokenResponse.IdentityToken);


                        }
                        catch (Exception ex)
                        {
                            Logger.WriteLog(ex, Framework.Common.LogType.Error);
                        }

                        return Task.FromResult(0);
                    }
                };

            });
            services.AddSession(options =>
            {
                options.Cookie.Name = ".lLogin.Session";
                options.IdleTimeout = TimeSpan.FromSeconds(10);
                options.Cookie.IsEssential = true;
            });
            services.ConfigureApplicationCookie(options =>
            {
                options.Cookie.HttpOnly = true;
                options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
            });
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.All;
            });
            services.AddControllersWithViews();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        }


        private void CheckSameSite(HttpContext httpContext, CookieOptions options)
        {
            if (options.SameSite == SameSiteMode.None)
            {
                var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
                // TODO: Use your User Agent library of choice here.
                if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6") || userAgent.Contains("Chrome/9"))
                {
                    // For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1)
                    options.SameSite = SameSiteMode.Unspecified;
                }
            }
        }



            app.UseHttpsRedirection();
            app.UseStaticFiles();
            //app.UseAntiXssMiddleware();
            app.UseCookiePolicy();
            app.UseAuthentication();
            app.UseRouting();
            app.UseSession();
            app.UseAuthorization();
            app.UseForwardedHeaders();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
Microsoft Identity Manager
Microsoft Identity Manager
A family of Microsoft products that manage a user's digital identity using identity synchronization, certificate management, and user provisioning.
342 questions
Azure Active Directory
Azure Active Directory
An Azure enterprise identity service that provides single sign-on and multi-factor authentication.
12,632 questions
No comments
{count} votes