OIDC客户端JS:静默访问令牌更新中断,因为身份服务器身份验证Cookie滑动过期不起作用 [英] Oidc client js: silent access token renew breaks because identity server authentication cookie sliding expiration doesn't work

查看:392
本文介绍了OIDC客户端JS:静默访问令牌更新中断,因为身份服务器身份验证Cookie滑动过期不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用有角度的SPA,该SPA通过使用身份服务器4 来实现身份验证和 oidc客户端js .

I'm working with an angular SPA which implements authentication by using identity server 4 and oidc client js.

某些操作在静默访问令牌续订级别上不起作用.预期的行为是访问令牌的自动更新,这要归功于iframe调用/connect/authorize端点的幕后行为.该调用将身份服务器身份验证cookie与HTTP请求一起发送,从而使身份服务器知道用户会话仍然有效,并且能够发出新的新访问令牌而无需 >要求用户再次交互式登录.到目前为止,我很确定我的理解还可以.

Something is not working at the silent access token renew level. The expected behavior is an automatic renew of the access token, which happens under the hood thanks to an iframe which calls the /connect/authorize endpoint. This call sends the identity server authentication cookie along with the HTTP request, doing so identity server knowns that the user session is still valid and is able to issue a fresh new access token without requiring the user to sign in again interactively. Up to this point I'm quite sure that my understanding is fine.

这是棘手的部分:我的期望是身份服务器身份验证cookie应当具有滑动期满,这样,每次调用/connect/authorize时,其到期日期就会及时向前移动.端点已建立.换句话说,我希望用户第一次登录后不需要其他交互式登录,因为每次静默续订iframe需要新的访问令牌.

Here is the tricky part: my expectation is that the identity server authentication cookie should have a sliding expiration, so that its expiration date is moved forward in time each time a call to the /connect/authorize endpoint is made. Put another way, I expected that after the user signs in the first time no other interactive login is required to the user, because the user session expiration date is automatically moved forward in time each time a new access token is required by the silent renew iframe.

为了获得此行为,我在身份服务器级别设置了以下配置.

In order to obtain this behavior I've set up the following configuration at the identity server level.

这是客户端配置(请注意,访问令牌的生存期为2分钟= 120秒):

This is the client configuration (notice that the access token lifetime is 2 minutes = 120 seconds):

                    new Client
                    {
                        ClientId = "web-client",
                        ClientName = "SPA web client",
                        AllowedGrantTypes = GrantTypes.Code,
                        RequireClientSecret = false,
                        RequirePkce = true,
                        RequireConsent = false,
                        AccessTokenLifetime = 120,
                        
                        RedirectUris =           { "https://localhost:4200/assets/signin-callback.html", "https://localhost:4200/assets/silent-callback.html" },
                        PostLogoutRedirectUris = { "https://localhost:4200/signout-callback" },
                        AllowedCorsOrigins =     { "https://localhost:4200" },

                        AllowedScopes =
                        {
                            IdentityServerConstants.StandardScopes.OpenId,
                            IdentityServerConstants.StandardScopes.Profile,
                            IdentityServerConstants.StandardScopes.Email,
                            "dataset",
                            "exercise",
                            "user-permissions"
                        }
                    }

这是ConfigureServices,我在其中添加了所有身份服务器配置.请注意,cookie的生存期设置为15分钟,并且需要cookie滑动到期:

This is the ConfigureServices, where I've added all of the identity server configuration. Notice that the cookie lifetime is set to 15 minutes and that the cookie sliding expiration is required:

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<RequestLoggingOptions>(o =>
            {
                o.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
                {
                    diagnosticContext.Set("RemoteIpAddress", httpContext.Connection.RemoteIpAddress.MapToIPv4());
                };
            });

            services.AddControllersWithViews();

            var migrationsAssembly = GetRunningAssemblyName();
            var connectionString = this.Configuration.GetConnectionString(IdentityServerDatabaseConnectionString);

            var identityServerBuilder = services.AddIdentityServer(options =>
            {
                options.Authentication.CookieLifetime = TimeSpan.FromMinutes(15);
                options.Authentication.CookieSlidingExpiration = true;
            })
            .AddTestUsers(TestData.Users)
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = dbContextBuilder =>
                    dbContextBuilder.UseSqlServer(
                        connectionString,
                        sqlServerOptionsBuilder => sqlServerOptionsBuilder.MigrationsAssembly(migrationsAssembly)
                    );
            })
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = dbContextBuilder =>
                    dbContextBuilder.UseSqlServer(
                        connectionString,
                        sqlServerOptionsBuilder => sqlServerOptionsBuilder.MigrationsAssembly(migrationsAssembly)
                    );
            });

            services.AddAuthentication(x => x.DefaultAuthenticateScheme = IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme);

            identityServerBuilder.AddDeveloperSigningCredential();
        }

在阅读此github问题后,我已将呼叫添加到services.AddAuthentication(x => x.DefaultAuthenticateScheme = IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme); .根据我的理解,此调用是多余的,因为通过使用常量IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme作为身份验证方案名称,对services.AddIdentityServer的调用应该已经将cookie身份验证设置为默认身份验证方案.

I've added the call to services.AddAuthentication(x => x.DefaultAuthenticateScheme = IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme); after reading this github issue. Based on my understanding this call is redundant, because the call to services.AddIdentityServer should already set the cookie authentication as the default authentication scheme, by using the constant IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme as the authentication scheme name.

通过使用此身份服务器配置,silen访问令牌续订不会按我期望的方式工作.

By using this identity server configuration the silen access token renew does not work the way I expect.

访问令牌被静默更新14次,然后第十五次尝试更新访问令牌失败,并显示消息SilentRenewService._tokenExpiring: Error from signinSilent: login_required.

The access token is silently renewed 14 times, then the fifteenth attempt to renew the access token fails with the message SilentRenewService._tokenExpiring: Error from signinSilent: login_required.

这基本上意味着身份验证cookie的滑动过期无效,因为我的身份验证cookie的生命周期为15分钟,SPA客户端的访问令牌的生命周期为2分钟,并且oidc客户端js库正在执行静默刷新周期每分钟一次(访问令牌在其到期时间之前60秒进行更新,因此使用我的设置,每分钟完成一次无提示更新).在第十五次尝试更新访问令牌时,身份验证cookie最终到期,并且身份服务器授权端点将错误响应返回到https://localhost:4200/assets/silent-callback.html静态页面.

This basically means that the authentication cookie sliding expiration is not working, because my authentication cookie has a 15 minutes lifetime, the access token for my SPA client has a 2 minutes lifetime and the oidc client js library is doing the silent refresh cycle once per minute (the access token is renewed 60 seconds before its expiration time, so with my settings the silent renew in done every minute). At the fifteenth attempt to renew the access token the authentication cookie is finally expired and the identity server authorize endpoint returns an error response to the https://localhost:4200/assets/silent-callback.html static page.

这些是我的控制台日志(请注意,静音更新已按预期进行了14次):

These are my console logs (notice that for 14 times the silen renew has worked as expected):

这些是身份服务器编写的服务器端日志,该日志确认用户会话在第十五次尝试时已过期:

These are the server side logs written by identity server, which confirms that the user session is expired at the fifteenth attempt:

这些是在成功尝试更新访问令牌(前14次尝试更新访问令牌的尝试之一)期间调用/connect/authorize端点时身份服务器返回的响应标头.请注意,有一个响应标头为idsrv cookie设置了新值:

These are the response headers returned by identity server when the /connect/authorize endpoint is called during a successful attempt to renew the access token (one of the first 14 attempts to renew the access token). Notice that there is a response header which sets a new value for the idsrv cookie:

这些是身份验证服务器在尝试更新访问令牌的尝试失败(第十五次尝试更新访问令牌)期间调用/connect/authorize端点时返回的响应标头.请注意,idsrv.session cookie无效,因为其到期日期设置为2019年的过去日期:

These are the response headers returned by identity server when the /connect/authorize endpoint is called during a failed attempt to renew the access token (the fifteenth attempt to renew the access token). Notice that the idsrv.session cookie is invalidated, because its expiration date is set to a past date in 2019:

我是否丢失了有关静默访问令牌续订和身份验证Cookie滑动过期之间的关系的任何信息?

Am I missing anything about the relationship between the silent access token renew and the authentication cookie sliding expiration ?

这是预期的行为吗?

是否有一种方法可以使静默访问令牌续期工作而无需,而无需新的用户登录交互?

Is there a way to make the silent access token renew work without requiring a new user login interaction ?

更新2020年9月16日

我终于设法解决了这个问题.

I finally managed to solve this issue.

修复程序是将IdentityServer4.EntityFramework nuget软件包更新为最新的可用版本(今天为4.1.0).

The fix is the updating of the IdentityServer4.EntityFramework nuget package to the latest available version (4.1.0 as of today).

所有详细信息均在我自己的github问题中的中进行了报告. oidc-client-js github存储库.

All the details are reported in my own github issue on the oidc-client-js github repository.

总而言之,cookie滑动过期的奇怪行为的根本原因是此身份服务器错误,由IdentityServer4.EntityFramework nuget软件包的4.1.0版本修复,如发行说明.

To summarize, the underlying cause of the strange behavior with the cookie sliding expiration is this identity server bug, fixed by the 4.1.0 release of IdentityServer4.EntityFramework nuget package, as pointed in the release notes.

推荐答案

这是我在您的此外,以下是appsettings中的客户端配置:

Also, follwing is the client configuration in the appsettings:

{
    "Enabled": true,
    "ClientId": "dashboard",
    "ClientName": "Web Client",
    "ClientSecrets": [ { "Value": "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=" } ],
    "AllowedGrantTypes": [ "implicit", "authorization_code" ],
    "AllowedScopes": [ "openid", "email", "profile", "role" ],
    "AllowOfflineAccess": true,
    "AllowAccessTokensViaBrowser": true,
    "AllowedCorsOrigins": [
      "http://localhost:7004"
    ],
    "RedirectUris": [
      "http://localhost:7004/callback",
      "http://localhost:7004/refreshtoken"
    ],
    "PostLogoutRedirectUris": [
      "http://localhost:7004"
    ],
    "AccessTokenLifetime": 3600,
    "RequireConsent": false
  }

这篇关于OIDC客户端JS:静默访问令牌更新中断,因为身份服务器身份验证Cookie滑动过期不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆