1 回答

TA贡献1828条经验 获得超3个赞
有两种类型的身份验证,cookie 和持有者。
如果 Cookie 使您保持登录状态,则持有者令牌无法登录。因为持有者令牌设置为在某个时刻过期,不允许更改生存期。
访问令牌过期后访问资源 (api) 的唯一方法是让用户再次登录或使用刷新令牌请求新的访问令牌,而无需用户交互。
您已经配置了它:
options.Scope.Add("offline_access");
每次登录时,请求将至少包含一个刷新令牌。将其存放在安全的地方,并在需要时使用。默认情况下,它设置为仅一次使用。
您可以使用类似此代码的内容来续订令牌(因为您实际上不是在刷新它,而是在替换它)。需要包含“标识模型”NuGet 包,如标识服务器的示例所示。
private async Task<TokenResponse> RenewTokensAsync()
{
// Initialize the token endpoint:
var client = _httpClientFactory.CreateClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
if (disco.IsError) throw new Exception(disco.Error);
// Read the stored refresh token:
var rt = await HttpContext.GetTokenAsync("refresh_token");
var tokenClient = _httpClientFactory.CreateClient();
// Request a new access token:
var tokenResult = await tokenClient.RequestRefreshTokenAsync(new RefreshTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "mvc",
ClientSecret = "secret",
RefreshToken = rt
});
if (!tokenResult.IsError)
{
var old_id_token = await HttpContext.GetTokenAsync("id_token");
var new_access_token = tokenResult.AccessToken;
var new_refresh_token = tokenResult.RefreshToken;
var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn);
// Save the information in the cookie
var info = await HttpContext.AuthenticateAsync("Cookies");
info.Properties.UpdateTokenValue("refresh_token", new_refresh_token);
info.Properties.UpdateTokenValue("access_token", new_access_token);
info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
await HttpContext.SignInAsync("Cookies", info.Principal, info.Properties);
return tokenResult;
}
return null;
}
默认情况下,刷新令牌用法配置为一次性使用。请注意,当存储新的刷新令牌失败并且你应该丢失它时,请求新的刷新令牌的唯一方法是强制用户再次登录。
另请注意,刷新令牌可能会过期。
退后一步,当访问令牌过期或即将过期时,需要使用它:
var accessToken = await HttpContext.GetTokenAsync("access_token");
var tokenHandler = new JwtSecurityTokenHandler();
var jwtSecurityToken = tokenHandler.ReadJwtToken(accessToken);
// Depending on the lifetime of the access token.
// This is just an example. An access token may be valid
// for less than one minute.
if (jwtSecurityToken.ValidTo < DateTime.UtcNow.AddMinutes(5))
{
var responseToken = await RenewTokensAsync();
if (responseToken == null)
{
throw new Exception("Error");
}
accessToken = responseToken.AccessToken;
}
// Proceed, accessToken contains a valid token.
- 1 回答
- 0 关注
- 66 浏览
添加回答
举报