Существует два типа аутентификации: cookie и канал-носитель.
Там, где cookie-файл хранит вас в системе, маркер канала-носителя не может.Поскольку токен-носитель настроен на истечение в определенный момент, не позволяя изменить время жизни.
Единственный способ получить доступ к ресурсу (api) после истечения срока действия токена-доступа - это позволить пользователю снова войти в систему илизапросить новый токен доступа, используя токен обновления , без необходимости взаимодействия с пользователем.
Вы уже настроили его:
options.Scope.Add("offline_access");
При каждом входе в систему запрос будетхотя бы содержат токен обновления.Храните его в безопасном месте и используйте при необходимости.По умолчанию он настроен только на одноразовое использование.
Вы можете использовать что-то вроде этого кода для обновления токена (поскольку вы фактически не обновляете его, а вместо этого заменяете его).Вам нужно будет включить пакет NuGet «IdentityModel», как видно из примеров из IdentityServer.
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.