IdentityServer4 在用户浏览器闲置一段时间后出现“idp 声明丢失”错误

问题描述 投票:0回答:1

我们有两个 ASP.NET MVC 站点,其中一个充当另一个的 IDP。 IDP 使用 IdentityServer4。 SP 是 IDP 的 OpenIDConnect 客户端。

本周,我们收到了几位用户的报告,称他们发生了这种情况:

  • 在 SP 网站上单击“登录”。重定向到 IDP 上的登录页面,输入用户名+密码,重定向回 SP。
  • 浏览一下
  • 保持浏览器打开,走开,再回来
  • 再浏览一些,注意到您现在似乎已注销(“登录”按钮再次可见,并且无法访问受保护的资源)
  • 再次点击“登录”

此时,他们会看到我们的 IDP 的“500 错误”页面。查看日志,我们可以看到 500 错误源自 IdentityServer4 中间件,错误消息为“idp 声明丢失”。

为了解决这个问题,技术支持人员一直告诉我们的用户清除浏览器的 cookie 和缓存(这让他们可以再次登录),但我们确实需要永久修复。我们不知道“徘徊”期需要多长时间才能触发该错误,但我们假设某个地方的某些令牌即将到期。开发人员无法在本地重现这种效果:我们可以将 IDP 和 SP 作为本地站点运行,并在它们之间进行连接,但从未见过此设置中的错误。这限制了我们调试它的能力。

IdentityServer4 Github 上的共识是这个问题是由于未能在startup.cs中包含这一行而导致的:

opts.OnRefreshingPrincipal = SecurityStampValidatorCallback.UpdatePrincipal;
我们尝试添加这个,但没有帮助。经过进一步调查,我们意识到我们正在使用 

services.AddAspNetIdentity<T>()

,无论如何它已经做到了这一点,所以这种改变可能是多余的。

这就是 UpdatePrincipal 所做的,如果这有帮助的话 - 对“idp”的引用以粗体显示:

/// <summary> /// Maintains the claims captured at login time that are not being created by ASP.NET Identity. /// This is needed to preserve **claims such as idp**, auth_time, amr. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public static Task UpdatePrincipal(SecurityStampRefreshingPrincipalContext context) { var newClaimTypes = context.NewPrincipal.Claims.Select(x => x.Type).ToArray(); var currentClaimsToKeep = context.CurrentPrincipal.Claims.Where(x => !newClaimTypes.Contains(x.Type)).ToArray(); var id = context.NewPrincipal.Identities.First(); id.AddClaims(currentClaimsToKeep); return Task.CompletedTask; }
IDP 上的当前设置如下所示:

services.Configure<SecurityStampValidatorOptions>(opts => { opts.OnRefreshingPrincipal = SecurityStampValidatorCallback.UpdatePrincipal; }); services .AddTransient<IUserClaimsPrincipalFactory<MemberIdentityUser>, UserClaimsFactory>() .AddIdentityServer( options => { options.UserInteraction.LoginUrl = "/oidc/login"; options.UserInteraction.LogoutUrl = "/oidc/logout"; }) .AddAspNetIdentity<MemberIdentityUser>() .AddInMemoryIdentityResources(new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email() }) .AddDeveloperSigningCredential() .AddSigningCredential(cert) .AddInMemoryClients(_config.GetSection("IdentityServer:Oidc:Clients"));
我的想法是,如果这个问题是由过期的东西引起的,从而使用户处于不幸的半注销状态,那么最好的办法是在过期发生之前完全注销用户。但我不确定从哪里开始设置生命周期。据我所知,ASP.NET auth cookie(在我的浏览器中)似乎设置为“会话”,它没有到期时间。到目前为止,我们一直依赖 IdentityServer4 的相当“默认”安装,除了这个之外,并没有真正遇到问题。

有谁知道还有什么可能导致这种情况/对我们在这里遇到的到期时间有什么建议吗?我确实找到了

Github 问题,他们谈论添加 UpdatePrincipal 选项,他们说:

“Cookie 在滑动时不会丢失任何声明,但如果安全标记失效,它将丢失声明。这可能是您遇到的情况吗?”

但是由于我们已经设置了 UpdatePrincipal 选项,我不确定它有多相关。

identityserver4
1个回答
0
投票
回来解释发生了什么,以防有人发现这个:

果然,“UpdatePrincipal”从未运行过,因为我们使用 Umbraco,它用自己的值覆盖“SecurityStampValidatorOptions”。在 Umbraco 'MemberSecurityStampValidatorOptions' 中设置该选项解决了该问题。

您还可以使用 Umbraco 的“AddMemberIdentity”函数,它可以为您执行“ConfigureOptions”。

© www.soinside.com 2019 - 2024. All rights reserved.