AspNetCore应用程序中OpenIdConnect身份验证流的PostLogout重定向问题



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

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

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

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

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

单击此处查看浏览器的网络选项卡中的行为

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

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);
});
}

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

这是意料之中的事,还是我做错了什么?

另一件事是,当我在下面添加代码片段时,重定向按预期工作,并且正确地调用了注销后端点。这又一次证实了对基础应用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();

我已经解决了这个问题。我可能对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";
});

最新更新