仅使用外部OIDC身份提供程序不调用SignInAsync时如何持久化Cookie认证
核心原因
之前配置不生效的本质是:OIDC中间件完成身份回调后,自动构造的认证票据默认携带IsPersistent = false的属性,此时Cookie中间件会强制生成会话级Cookie,即便你在.AddCookie()里配置了ExpireTimeSpan也不会生效,浏览器关闭后Cookie就会直接清除。
实现方案
不需要改动现有登录流程,完全可以通过挂接认证中间件的内置事件,在不写任何自定义登录逻辑的前提下,强制让写入的Cookie为持久化状态,有两种适合当前场景的配置方式:
方案1:OIDC事件层配置(仅作用于OIDC登录场景)
在OpenIdConnect中间件的OnTokenValidated事件里,直接修改后续传递给Cookie方案的认证属性,仅对OIDC流程触发的登录生效:
services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "OpenIdConnect"; }) .AddCookie("Cookies", options => { // Cookie基础兜底配置 options.Cookie.HttpOnly = true; options.Cookie.SameSite = SameSiteMode.Lax; // 开启滑动过期,用户持续操作时自动续期 options.SlidingExpiration = true; // 兜底过期时间1天 options.ExpireTimeSpan = TimeSpan.FromDays(1); }) .AddOpenIdConnect("OpenIdConnect", options => { options.SignInScheme = "Cookies"; // 原有OIDC基础配置(Authority、ClientId、ClientSecret等)保持不变 options.Events.OnTokenValidated = context => { // 强制标记票据为持久化 context.Properties.IsPersistent = true; // 显式指定过期时间 context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1); return Task.CompletedTask; }; });
方案2:Cookie事件层全局配置(推荐)
直接在Cookie认证方案的OnSigningIn事件里强制修改认证属性,所有走这个Cookie方案的登录(不管是当前OIDC流程,还是后续新增的任何登录逻辑)都会自动应用持久化规则,完全不需要额外改动业务代码:
services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "OpenIdConnect"; }) .AddCookie("Cookies", options => { options.Cookie.HttpOnly = true; options.Cookie.SameSite = SameSiteMode.Lax; options.SlidingExpiration = true; options.ExpireTimeSpan = TimeSpan.FromDays(1); // 挂接Cookie签名事件 options.Events.OnSigningIn = context => { context.Properties.IsPersistent = true; context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1); return Task.CompletedTask; }; }) .AddOpenIdConnect("OpenIdConnect", options => { options.SignInScheme = "Cookies"; // 原有OIDC配置保持不变,不需要额外挂接事件 });
注意事项
- 该配置生成的持久化Cookie完全由主应用管控,只要Cookie未失效,所有经过
[Authorize]校验的请求都不会触发OIDC挑战流程,完全不会向IdP发起跳转请求,实现减少IdP访问压力的目标。 - 用户主动调用
SignOutAsync注销时,持久化Cookie会被正常清除,不会出现注销后仍残留的问题。 - 后续如果需要为不同用户动态调整持久化时长(比如管理员账号持久化7天、普通用户1天),可以直接在事件里根据用户的Claims动态修改
ExpiresUtc的值,不需要调整其他逻辑。
内容的提问来源于stack exchange,提问作者thankyoussd
相关产品推荐
相关产品推荐

