Angular Oidc客户端js:静默访问令牌续订中断,因为身份服务器身份验证cookie滑动过期不';行不通
我正在使用angular SPA,它通过使用和实现身份验证 在静默访问令牌续订级别,某些内容不起作用。预期的行为是访问令牌的自动续订,由于调用Angular Oidc客户端js:静默访问令牌续订中断,因为身份服务器身份验证cookie滑动过期不';行不通,angular,identityserver4,openid-connect,oidc-client-js,Angular,Identityserver4,Openid Connect,Oidc Client Js,我正在使用angular SPA,它通过使用和实现身份验证 在静默访问令牌续订级别,某些内容不起作用。预期的行为是访问令牌的自动续订,由于调用/connect/authorize端点的iframe,这种情况在引擎盖下发生。此调用随HTTP请求一起发送identity server身份验证cookie,这样identity server就知道用户会话仍然有效,并且能够发出新的访问令牌,而不需要用户以交互方式再次登录。到目前为止,我确信我的理解是正确的 这里是棘手的部分:我的期望是identity
/connect/authorize
端点的iframe,这种情况在引擎盖下发生。此调用随HTTP请求一起发送identity server身份验证cookie,这样identity server就知道用户会话仍然有效,并且能够发出新的访问令牌,而不需要用户以交互方式再次登录。到目前为止,我确信我的理解是正确的
这里是棘手的部分:我的期望是identity server身份验证cookie应该有一个滑动过期,以便每次调用/connect/authorize
端点时,其过期日期都会及时向前移动。换句话说,我希望在用户第一次登录后,不需要用户进行其他交互登录,,因为每次静默续订iframe需要新的访问令牌时,用户会话过期日期都会自动向前移动
为了获得这种行为,我在identity server级别设置了以下配置
这是客户端配置(请注意,访问令牌生存期为2分钟=120秒):
这是ConfigureServices
,我在这里添加了所有identity server配置。请注意,cookie生存期设置为15分钟,并且需要cookie滑动到期:
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();
}
public void配置服务(IServiceCollection服务)
{
服务配置(o=>
{
o、 EnricDiagnosticContext=(diagnosticContext,httpContext)=>
{
diagnosticContext.Set(“RemoteIpAddress”,httpContext.Connection.RemoteIpAddress.MapToIPv4());
};
});
services.AddControllersWithViews();
var migrationassembly=GetRunningAssemblyName();
var connectionString=this.Configuration.GetConnectionString(IdentityServerDatabaseConnectionString);
var identityServerBuilder=services.AddIdentityServer(选项=>
{
options.Authentication.CookieLifetime=TimeSpan.FromMinutes(15);
options.Authentication.CookieSlidingExpiration=true;
})
.AddTestUsers(TestData.Users)
.AddConfigurationStore(选项=>
{
options.ConfigureDbContext=dbContextBuilder=>
dbContextBuilder.UseSqlServer(
连接字符串,
sqlServerOptionsBuilder=>sqlServerOptionsBuilder.MigrationsAssembly(MigrationsAssembly)
);
})
.addStore(选项=>
{
options.ConfigureDbContext=dbContextBuilder=>
dbContextBuilder.UseSqlServer(
连接字符串,
sqlServerOptionsBuilder=>sqlServerOptionsBuilder.MigrationsAssembly(MigrationsAssembly)
);
});
services.AddAuthentication(x=>x.DefaultAuthenticationScheme=IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme);
identityServerBuilder.AddDeveloperSigningCredential();
}
我已经添加了对services.AddAuthentication的调用(x=>x.DefaultAuthenticationScheme=IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme)代码>阅读后。根据我的理解,此调用是多余的,因为对服务.AddIdentityServer
的调用应该已经使用常量IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme
作为身份验证方案名称,将cookie身份验证设置为默认身份验证方案
通过使用此identity server配置,silen访问令牌续订不会以我期望的方式工作
访问令牌以静默方式续订14次,然后第十五次续订访问令牌的尝试失败,并显示消息SilentRenewService.\u令牌过期:登录错误\u必需
这基本上意味着身份验证cookie滑动过期不起作用,因为我的身份验证cookie有15分钟的生命周期,我的SPA客户端的访问令牌有2分钟的生命周期,而oidc客户端js库每分钟执行一次静默刷新周期(访问令牌在到期前60秒续订,因此,通过我的设置,静默续订每分钟完成一次)。在第十五次尝试续订访问令牌时,身份验证cookie最终过期,并且identity server授权终结点返回对https://localhost:4200/assets/silent-callback.html
静态页面
以下是我的控制台日志(请注意,silen renew已按预期工作了14次):
以下是identity server编写的服务器端日志,用于确认用户会话在第十五次尝试时已过期:
在成功尝试续订访问令牌期间调用/connect/authorize
端点时,这些是identity server返回的响应头(续订访问令牌的前14次尝试之一)。请注意,有一个响应标头,它为idsrv
cookie设置了一个新值:
这些是identity server在/connect/authorize
端点
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();
}
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();
}
{
"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
}