Вот что я придумал. Поскольку я не могу найти много примеров того, как сделать refre sh token в ASP. NET Core с cookie, я подумал, что опубликую это здесь. (У той, на которую я ссылаюсь в этом вопросе, есть проблемы.)
Это просто моя попытка заставить это работать. Он не использовался ни в каких производственных условиях. Этот код используется в методе ConfigureServices
.
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Events = new CookieAuthenticationEvents
{
// After the auth cookie has been validated, this event is called.
// In it we see if the access token is close to expiring. If it is
// then we use the refresh token to get a new access token and save them.
// If the refresh token does not work for some reason then we redirect to
// the login screen.
OnValidatePrincipal = async cookieCtx =>
{
var now = DateTimeOffset.UtcNow;
var expiresAt = cookieCtx.Properties.GetTokenValue("expires_at");
var accessTokenExpiration = DateTimeOffset.Parse(expiresAt);
var timeRemaining = accessTokenExpiration.Subtract(now);
// TODO: Get this from configuration with a fall back value.
var refreshThresholdMinutes = 5;
var refreshThreshold = TimeSpan.FromMinutes(refreshThresholdMinutes);
if (timeRemaining < refreshThreshold)
{
var refreshToken = cookieCtx.Properties.GetTokenValue("refresh_token");
// TODO: Get this HttpClient from a factory
var response = await new HttpClient().RequestRefreshTokenAsync(new RefreshTokenRequest
{
Address = tokenUrl,
ClientId = clientId,
ClientSecret = clientSecret,
RefreshToken = refreshToken
});
if (!response.IsError)
{
var expiresInSeconds = response.ExpiresIn;
var updatedExpiresAt = DateTimeOffset.UtcNow.AddSeconds(expiresInSeconds);
cookieCtx.Properties.UpdateTokenValue("expires_at", updatedExpiresAt.ToString());
cookieCtx.Properties.UpdateTokenValue("access_token", response.AccessToken);
cookieCtx.Properties.UpdateTokenValue("refresh_token", response.RefreshToken);
// Indicate to the cookie middleware that the cookie should be remade (since we have updated it)
cookieCtx.ShouldRenew = true;
}
else
{
cookieCtx.RejectPrincipal();
await cookieCtx.HttpContext.SignOutAsync();
}
}
}
};
})
.AddOpenIdConnect(options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = oidcDiscoveryUrl;
options.ClientId = clientId;
options.ClientSecret = clientSecret;
options.RequireHttpsMetadata = true;
options.ResponseType = OidcConstants.ResponseTypes.Code;
options.UsePkce = true;
// This scope allows us to get roles in the service.
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
// This aligns the life of the cookie with the life of the token.
// Note this is not the actual expiration of the cookie as seen by the browser.
// It is an internal value stored in "expires_at".
options.UseTokenLifetime = true;
options.SaveTokens = true;
});
Этот код состоит из двух частей:
AddOpenIdConnect
: эта часть кода устанавливает OID C для приложение. Основные настройки здесь: SignInScheme
: это позволяет ASP. NET Core знать, что вы хотите использовать куки для хранения вашей информации аутентификации. - *
UseTokenLifetime
: Как я поймите, это устанавливает внутреннее значение "expires_at" в cook ie как срок жизни токена доступа. (Не фактический срок действия повара ie, который остается на уровне сеанса.) - *
SaveTokens
: Насколько я понимаю, именно из-за этого токены сохраняются в поваре ie.
OnValidatePrincipal
: этот раздел вызывается, когда повар ie подтвержден. В этом разделе мы проверяем, близок ли или истек срок действия токена доступа. Если это так, то он обновляется и обновленные значения сохраняются в файле cook ie. Если токен не может быть обновлен, то пользователь перенаправляется на экран входа в систему.
Код использует следующие значения, которые должны поступить из вашего файла конфигурации:
clientId
: Идентификатор клиента OAuth2. Также называется ключом клиента, ключом потребителя и т. Д. c. clientSecret
: OAuth2 Client Secret. Также называется Consumer Secret и т. Д. c. oidcDiscoveryUrl
: базовая часть URL-адреса для хорошо известного документа конфигурации вашего IDP. Если документ общеизвестной конфигурации имеет значение https://youridp.domain.com/oauth2/oidcdiscovery/.well-known/openid-configuration
, тогда это значение будет https://youridp.domain.com/oauth2/oidcdiscovery
. tokenUrl
: URL-адрес конечной точки токена вашего IDP. Например: https:/youridp.domain.com/oauth2/token
refreshThresholdMinutes
: если вы подождете, пока токен доступа очень близок к истечению срока действия, вы рискуете прервать вызовы, основанные на маркере доступа. (Если срок действия истекает через 5 миллисекунд, то он может истечь и завершиться ошибкой вызова, прежде чем вы получите возможность обновить sh.) Этот параметр задает количество минут до истечения срока действия, которое вы хотите считать токеном доступа готовым к
* Я новичок в ASP. NET Core. Поэтому я не уверен на 100%, что эти настройки делают то, что я думаю. Это всего лишь кусок кода, который работает для меня, и я подумал, что поделюсь им. Это может или не может работать для вас.