ASP.NET Core集成AWS Cognito登出后仍可访问授权区域问题
ASP.NET Core AWS Cognito登出后仍可访问受保护区域问题排查与解决
核心问题定位
调用HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme)仅完成Cognito端的登出流程,但未彻底清除ASP.NET Core应用本地的认证会话,导致带[Authorize]特性的页面/接口仍能被访问。以下是针对性的解决方案:
1. 同时签出Cookie认证方案
ASP.NET Core默认用Cookie存储本地认证会话,仅签出OpenIdConnect方案不足以清除本地状态,需同时触发Cookie方案的签出:
public async Task<IActionResult> Logout() { // 签出Cognito端的OpenIdConnect会话 await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); // 清除本地认证Cookie await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return RedirectToAction("Index", "Home"); }
2. 完善OpenIdConnect配置
在Program.cs的认证配置中,关联Cookie方案并配置登出回调,确保Cognito登出后同步清理本地状态:
builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => { options.ClientId = builder.Configuration["AWS:Cognito:ClientId"]; options.ClientSecret = builder.Configuration["AWS:Cognito:ClientSecret"]; options.Authority = $"https://cognito-idp.{builder.Configuration["AWS:Region"]}.amazonaws.com/{builder.Configuration["AWS:Cognito:UserPoolId"]}"; options.ResponseType = OpenIdConnectResponseType.Code; options.SaveTokens = true; // 指定登出回调路径 options.SignedOutCallbackPath = "/signout-callback-oidc"; // 关联Cookie方案作为登出时的本地清理方案 options.SignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme; // 自定义Cognito登出跳转,确保第三方端会话彻底清除 options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProviderForSignOut = context => { var logoutUri = $"https://{builder.Configuration["AWS:Cognito:Domain"]}.auth.{builder.Configuration["AWS:Region"]}.amazonaws.com/logout?client_id={options.ClientId}&logout_uri={Uri.EscapeDataString(context.Request.Scheme + "://" + context.Request.Host + "/")}"; context.Response.Redirect(logoutUri); context.HandleResponse(); return Task.CompletedTask; } }; });
3. 验证Cookie清理状态
登出后打开浏览器开发者工具的Application标签,检查是否存在AspNetCore.Cookies(或自定义名称的认证Cookie)。若仍存在,需检查Cookie配置是否合理:
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.Cookie.Name = ".AspNetCore.CognitoAuth"; options.ExpireTimeSpan = TimeSpan.FromMinutes(30); options.SlidingExpiration = true; })
4. 清除认证缓存(若使用)
若应用用分布式缓存/内存缓存存储认证票据,登出时需同步删除对应缓存项:
public async Task<IActionResult> Logout(IDistributedCache distributedCache) { var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (!string.IsNullOrEmpty(userId)) { await distributedCache.RemoveAsync($"AuthTicket_{userId}"); } await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return RedirectToAction("Index", "Home"); }
5. 修正布局页登录状态判断
确保布局页依赖User.Identity.IsAuthenticated判断登录状态,而非本地存储的自定义状态:
@if (User.Identity.IsAuthenticated) { <a asp-controller="Account" asp-action="Logout">登出</a> } else { <a asp-controller="Account" asp-action="Login">登录</a> }
内容的提问来源于stack exchange,提问作者Joao Lima
相关产品推荐
相关产品推荐

