OIDC客户端JS:静默访问令牌更新中断,因为身份服务器身份验证Cookie滑动过期无效

时间:2020-09-15 12:16:47

标签: angular identityserver4 openid-connect oidc-client-js

我正在使用一个角度SPA,该角度SPA通过使用identity server 4oidc client js实现身份验证。

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

这是棘手的部分:我希望身份服务器身份验证cookie的滑动期限应为,以便每次调用{{1 }}端点。换句话说,我希望用户第一次登录后不需要其他交互式登录,因为每次时,用户会话的到期日期都会自动自动向前移动静默续订iframe需要新的访问令牌

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

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

/connect/authorize

这是 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" } } ,我在其中添加了所有身份服务器配置。请注意,cookie的生存期设置为15分钟,并且cookie的滑动期限是必需的:

ConfigureServices

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

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

访问令牌被静默更新14次,然后第十五次尝试更新访问令牌失败,并显示消息IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme

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

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

enter image description here

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

enter image description here

这些是身份服务器在成功尝试更新访问令牌(最初14次尝试更新访问令牌中的一个)期间调用https://localhost:4200/assets/silent-callback.html端点时由响应服务器返回的响应标头)。请注意,有一个响应标头为/connect/authorize cookie设置了新值:

enter image description here

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

enter image description here

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

这是预期的行为吗?

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

更新2020年9月16日

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

此修复程序是将idsrv.session nuget软件包更新为最新的可用版本(截至今天为IdentityServer4.EntityFramework)。

所有详细信息都报告为in my own github issue on the oidc-client-js github repository

总而言之,cookie滑动过期的异常行为的根本原因是此identity server bug,由4.1.0 nuget软件包的4.1.0版本修复,如{{ 3}}。

1 个答案:

答案 0 :(得分:0)

这是我在您的request上的配置:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();

        services.AddControllersWithViews();

        services.AddCustomOptions(Configuration);

        services.AddCustomDbContext(Configuration)
            .ResolveDependencies();

        services.AddIdentityServer(options =>
                {
                    options.Authentication.CookieLifetime = AccountOptions.RememberMeLoginDuration;
                    options.Events.RaiseSuccessEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseErrorEvents = true;
                })
            .AddProfileService<ProfileService>()
            .AddSigningCertificate(Configuration)
            .AddInMemoryClients(Configuration.GetSection("IdentityServer:Clients"))
            .AddInMemoryIdentityResources(Resources.GetIdentityResources())
            .AddInMemoryApiResources(Resources.GetApis());

        var externalProviders = Configuration.GetSection(nameof(ApplicationOptions.ExternalProviders))
            .Get<ExternalProvidersOptions>();

        services.AddWindowsIdentityProvider(externalProviders.UseWindows);

        services.AddLocalization(options => options.ResourcesPath = Constants.Resources);

        services.AddMvc()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .AddDataAnnotationsLocalization();

        services.AddMvcCore()
            .AddCustomCors();
    }

此外,以下是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
  }
相关问题