Identityserver4/OpenId 连接,混合模式,令牌刷新失败
Identityserver4/OpenId Connect, Hybrid mode, Token Refresh Fails
我有 ASP.net 核心 MVC 站点,它使用 OpenId 连接与另一个 ASP.net 核心站点进行身份验证,该站点使用 IdentityServer4,该站点使用另一个 IdentityServer4 站点作为身份提供者。
客户端页面很少,理论上只用AJAX-calls就可以用很久。我不希望网站刷新访问令牌,这样用户就不会被迫登录,比方说第二天。
我设置了一个计时器,它调用 MVC-site 上的 WebAPI 方法,刷新令牌。
它适用于前两次刷新,但总是在第三次刷新时失败。
方法 returns 一个在外部使用的 JWT API-calls。我可以按预期在第一次调用时看到此更新,并且它获得了新的到期时间戳。
在第三次调用中,tokenClient.RequestRefreshTokenAsync 失败,因为 refreshToken 为空。
public async Task<IActionResult> RefreshToken()
{
var disco = await DiscoveryClient.GetAsync(_authenticationOptions.Value.Authority);
if (disco.IsError)
return BadRequest(disco.Error);
var tokenClient = new TokenClient(disco.TokenEndpoint, _authenticationOptions.Value.ClientId, _authenticationOptions.Value.ClientSecret);
var refreshToken = await HttpContext.Authentication.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
var tokenResult = await tokenClient.RequestRefreshTokenAsync(refreshToken);
if (tokenResult.IsError)
return BadRequest(disco.Error);
var old_id_token = await HttpContext.Authentication.GetTokenAsync(OpenIdConnectParameterNames.IdToken);
var new_access_token = tokenResult.AccessToken;
var new_refresh_token = tokenResult.RefreshToken;
var tokens = new List<AuthenticationToken>();
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.IdToken, Value = old_id_token });
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.AccessToken, Value = new_access_token });
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.RefreshToken, Value = new_refresh_token });
var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn);
tokens.Add(new AuthenticationToken { Name = "expires_at", Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) });
var info = await HttpContext.Authentication.GetAuthenticateInfoAsync("Cookies");
info.Properties.StoreTokens(tokens);
await HttpContext.Authentication.SignOutAsync("Cookies");
await HttpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties);
return Ok(HttpContext.Authentication.GetTokenAsync("access_token").Result);
}
我可以看到,Chrome 在控制台中通知,set-cookie header 被忽略了,因为它超过了 4kb。
有什么建议吗?
知道了。
客户端 IdentityToken 已过期,并且由于该 api 方法不受 [Authorize] 属性保护,因此它没有更新 + 更改脚本以使用 iframe 而不是 AJAX-来电!
案件结案。
我有 ASP.net 核心 MVC 站点,它使用 OpenId 连接与另一个 ASP.net 核心站点进行身份验证,该站点使用 IdentityServer4,该站点使用另一个 IdentityServer4 站点作为身份提供者。
客户端页面很少,理论上只用AJAX-calls就可以用很久。我不希望网站刷新访问令牌,这样用户就不会被迫登录,比方说第二天。
我设置了一个计时器,它调用 MVC-site 上的 WebAPI 方法,刷新令牌。
它适用于前两次刷新,但总是在第三次刷新时失败。
方法 returns 一个在外部使用的 JWT API-calls。我可以按预期在第一次调用时看到此更新,并且它获得了新的到期时间戳。
在第三次调用中,tokenClient.RequestRefreshTokenAsync 失败,因为 refreshToken 为空。
public async Task<IActionResult> RefreshToken()
{
var disco = await DiscoveryClient.GetAsync(_authenticationOptions.Value.Authority);
if (disco.IsError)
return BadRequest(disco.Error);
var tokenClient = new TokenClient(disco.TokenEndpoint, _authenticationOptions.Value.ClientId, _authenticationOptions.Value.ClientSecret);
var refreshToken = await HttpContext.Authentication.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
var tokenResult = await tokenClient.RequestRefreshTokenAsync(refreshToken);
if (tokenResult.IsError)
return BadRequest(disco.Error);
var old_id_token = await HttpContext.Authentication.GetTokenAsync(OpenIdConnectParameterNames.IdToken);
var new_access_token = tokenResult.AccessToken;
var new_refresh_token = tokenResult.RefreshToken;
var tokens = new List<AuthenticationToken>();
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.IdToken, Value = old_id_token });
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.AccessToken, Value = new_access_token });
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.RefreshToken, Value = new_refresh_token });
var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn);
tokens.Add(new AuthenticationToken { Name = "expires_at", Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) });
var info = await HttpContext.Authentication.GetAuthenticateInfoAsync("Cookies");
info.Properties.StoreTokens(tokens);
await HttpContext.Authentication.SignOutAsync("Cookies");
await HttpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties);
return Ok(HttpContext.Authentication.GetTokenAsync("access_token").Result);
}
我可以看到,Chrome 在控制台中通知,set-cookie header 被忽略了,因为它超过了 4kb。
有什么建议吗?
知道了。
客户端 IdentityToken 已过期,并且由于该 api 方法不受 [Authorize] 属性保护,因此它没有更新 + 更改脚本以使用 iframe 而不是 AJAX-来电!
案件结案。