【问题标题】:PostLogout redirect issue with OpenIdConnect auth flow in AspNetCore appAsp Net Core 应用程序中 OpenIdConnect 身份验证流的注销后重定向问题
【发布时间】:2021-02-13 09:33:58
【问题描述】:

我已经为此苦苦挣扎了好几天,但我不明白为什么代码没有按应有的方式工作。

我有一个使用 OpenIdConnect 身份验证方案的 .NetCore 3.1 Web 应用程序。当用户未经身份验证时,他/她被重定向到身份提供者服务器,登录并被重定向回客户端应用程序。这部分流程运行良好。

当用户退出 IDP 服务器时会出现此问题。成功注销后:

  1. 服务器将用户重定向到客户端应用程序中的注销后端点;

  2. 但应用程序的身份验证中间件阻止调用端点并执行另一个重定向到应用程序的基本 url。 我不明白为什么会发生 2。

Click here to take a look at the behaviour in the browser's network tab

客户端应用中的身份验证配置:

services.AddAuthentication(config =>
                {
                    config.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    config.DefaultChallengeScheme = "oidc";
                })
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, config =>
                {
                    
                })
                .AddOpenIdConnect("oidc", config =>
                {
                    config.Authority = "https://localhost:5001/";
                    config.ClientId = "client.application.com";
                    config.ClientSecret = "Secret";
                    config.SaveTokens = true;
                    config.ResponseType = OpenIdConnectResponseType.Code;
                    config.SignedOutCallbackPath = "/Home/Logout";
                    config.GetClaimsFromUserInfoEndpoint = true;
                    config.Scope.Add("roles");
                    config.ClaimActions.MapJsonKey(ClaimTypes.Role, "role", "role");
                });

StartUp.cs 中的 Configure 方法:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            HttpContextAccessorHolder.HttpContextAccessor = app.ApplicationServices.GetService<IHttpContextAccessor>();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseCors("ClientAppCorsPolicy");
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseSpaAuthentication();
            app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = s =>
                {
                    var jsPath = env.IsDevelopment() ? "/dev/js" : "/dist/js";

                    if (s.Context.Request.Path.StartsWithSegments(new PathString(jsPath)) &&
                        !s.Context.User.Identity.IsAuthenticated)
                    {
                        s.Context.Response.StatusCode = 401;
                        s.Context.Response.Body = Stream.Null;
                        s.Context.Response.ContentLength = 0;
                    }
                }
            });
            
            app.UseSpaStaticFiles();
            
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
            
            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = GetSpaOutputDir(env);
            });
        }

我已经调试了中间件流程,结果表明,当请求注销回调时,请求永远不会通过身份验证中间件,该中间件会终止请求并将重定向添加到响应中。

这是预期的还是我做错了什么?

另一件事是,当我在重定向下方添加代码 sn-p 时,重定向按预期工作,并且正确调用了注销后端点。这是另一个确认,不需要的重定向到基本应用程序 URL 是由身份验证中间件以某种方式触发的。

           app.UseRouting();

           app.Map("/Home/Logout", appBuilder =>
           {
               appBuilder.UseRouting();
               
               appBuilder.UseEndpoints(endpoints =>
               {
                   endpoints.MapControllerRoute(
                       name: "Logout",
                       pattern: "Home/Logout");
               });
           });
           
           app.UseCors("ClientAppCorsPolicy");
           app.UseAuthentication();
           app.UseAuthorization();

【问题讨论】:

    标签: asp.net-core authentication openid-connect


    【解决方案1】:

    我已经解决了这个问题。我可能对 OpenId 协议注销过程了解得不够透彻。 首先,我不知道 SignedOutCallbackPath 和 SignedOutRedirectUri 是在注销过程的不同阶段调用的两个不同端点。第一个在用户退出身份提供者后立即调用。在调用 SignedOutCallbackPath 之后调用第二个并重定向到。
    其次,在 AspNetCore OpenIdConnect 扩展中,SignedOutRedirectUri 默认指向客户端应用程序的根。如果希望应用程序将用户代理重定向到不同的位置,则需要显式配置 SignedOutRedirectUri 属性。

    所以现在 Startup.cs 中的 OpenIdConnect 扩展看起来像这样:

    .AddOpenIdConnect("oidc", config =>
                    {
                        config.Authority = "https://localhost:5001/";
                        config.ClientId = "client.application.com";
                        config.ClientSecret = "Secret";
                        config.SaveTokens = true;
                        config.ResponseType = OpenIdConnectResponseType.Code;
                        config.SignedOutCallbackPath = "/signout-callback-oidc";
                        config.GetClaimsFromUserInfoEndpoint = true;
                        config.Scope.Add("roles");
                        config.ClaimActions.MapJsonKey(ClaimTypes.Role, "role", "role");
                        config.SignedOutRedirectUri = "/Home/Logout";
                    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-09
      • 1970-01-01
      • 2010-10-31
      • 2020-03-09
      • 1970-01-01
      • 2020-02-24
      • 2019-01-27
      • 2017-04-03
      相关资源
      最近更新 更多