身份服务器 4 静默更新错误响应:login_required

Identity Server 4 Silent Renew ErrorResponse: login_required

我已经从 redux-oidc-example 克隆了 repo,它在大部分情况下都有效,但几个小时后出现以下错误:

Action payload: ErrorResponse: login_required
at new e (oidc-client.min.js:1)
at t [as _processSigninParams] (oidc-client.min.js:1)
at t [as validateSigninResponse] (oidc-client.min.js:1)
at oidc-client.min.js:1

UserManager.js 看起来像这样:

const userManagerConfig = {
  client_id: 'js.dev',
  client_secret: 'secret',
  redirect_uri: `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}/callback`,
  response_type: 'id_token token',
  scope: 'openid email profile role offline_access',
  authority: 'http://localhost:8080',
  silent_redirect_uri: `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}/silent_renew.html`,
  automaticSilentRenew: true,
  filterProtocolClaims: true,
  loadUserInfo: true
};

和我的身份服务器配置:

{
        "Enabled": true,
        "ClientId": "js.dev",
        "ClientName": "Javascript Client",
        "ClientSecrets": [ { "Value": "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=" } ],
        "AllowedGrantTypes": [ "implicit", "authorization_code" ],
        "AllowedScopes": [ "openid", "email", "profile", "role", "offline_access" ],
        "AllowOfflineAccess": true,
        "AllowAccessTokensViaBrowser":true,
        "RedirectUris": [
          "http://localhost:8081/callback",
          "http://localhost:8081/silent_renew.html"
        ],
        "PostLogoutRedirectUris": [
          "http://localhost:8081"
        ],
        "AccessTokenLifetime": 900,
        "RequireConsent": false
      }

我注意到在错误之前,最后一个有效响应有一个 cookie 响应(idsrv.session),其值为空,到期日期设置为上一年:

我认为这是问题的根本原因,我在相关的 Github 存储库中搜索了它并尝试将 Cookie.SameSite 添加到 none 但它没有帮助:

services.AddAuthentication()
                .AddSaml(Configuration,externalProviders.UseSaml)
                .AddCookie(options => {
                    options.SlidingExpiration = true;
                    options.ExpireTimeSpan = TimeSpan.FromDays(30);
                    options.Cookie.SameSite = SameSiteMode.None;
                });

任何想法!

这可能是由于您的 IDP 会话到期 - 如果您使用 prompt=none 调用 authorize 端点但它无法满足该请求,因为不存在有效会话(即身份验证 cookie 不存在)或已过期)则它将 return error=login_required

如果发生这种情况,那么正确的做法是在顶级浏览器中执行交互式(即 prompt=login)登录请求 window。

搜索 Identity Server 4 repo 后,我对代码进行了以下更改:

services.AddIdentityServer(options=>
                {
                    options.Authentication.CookieLifetime = TimeSpan.FromDays(30);
                    options.Authentication.CookieSlidingExpiration = true;
                })
                .AddProfileService<ProfileService>()
                .AddSigningCertificate(Configuration)
                .AddInMemoryClients(Configuration.GetSection("IdentityServer:Clients"))
                .AddInMemoryIdentityResources(Resources.GetIdentityResources());

之后它开始工作了,但是您必须在关闭浏览器或重新打开新标签页后重新登录我猜这是因为 sessionStorage

当会话过期时,STS 正在调用 signin-callback,其查询参数名为 'error',值为 'login_required'。

在 signin-callback 中,在完成 sign-in 之前,您可以检查此查询参数,如果找到,您也可以从您的 Web 客户端 sign-out。

我遇到了同样的问题并尝试了上面提出的建议,但对我来说,它实际上是 SameSiteMode 在 IdentityServer Cookies 上设置不正确。它导致 Callback error: ErrorResponse: login_required 在登录后和 N 次尝试后用户注销。

这对我有帮助https://github.com/IdentityServer/IdentityServer4/blob/main/src/IdentityServer4/host/Extensions/SameSiteHandlingExtensions.cs

他们所做的是基于这篇文章https://devblogs.microsoft.com/dotnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/

希望这有用。