Вопрос или проблема
У меня есть периодическая проблема, которая иногда мешает пользователям входить на мой сайт. Когда они пытаются войти, они видят нижеуказанную ошибку, когда их перенаправляют с сервера OpenIDDict.
error:invalid_token
error_description:Указанный токен связан с недействительным идентификатором.
error_uri:https://documentation.openiddict.com/errors/ID2088
Я обнаружил, что в большинстве случаев можно обновить страницу, и ошибка исчезает, но я не ожидаю, что обычный пользователь будет это делать. Я следовал примеру вебассемблера dantooine от OpenIDDict. Странно то, что эта проблема возникает только в производственной среде, когда приложение развернуто на моей службе Azure App Service.
Конфигурация клиента:
#region OpedIdDict
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlite(...);
options.UseOpenIddict();
});
builder.Services.AddAntiforgery(options =>
{
options.HeaderName = ...;
options.Cookie.Name = ...;
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = ...;
options.LogoutPath = ...;
options.ExpireTimeSpan = ...;
options.SlidingExpiration = false;
options.ClaimsIssuer = ...;
});
builder.Services.AddQuartz(options =>
{
options.UseMicrosoftDependencyInjectionJobFactory();
options.UseSimpleTypeLoader();
options.UseInMemoryStore();
});
builder.Services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
builder.Services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore().UseDbContext<ApplicationDbContext>();
options.UseQuartz();
})
.AddClient(options =>
{
options.AllowAuthorizationCodeFlow();
var certificate = ...;
options.AddSigningCertificate(certificate);
options.AddEncryptionCertificate(certificate);
options.UseAspNetCore()
.EnableStatusCodePagesIntegration()
.EnableRedirectionEndpointPassthrough()
.EnablePostLogoutRedirectionEndpointPassthrough();
options.UseSystemNetHttp()
.SetProductInformation(typeof(Program).Assembly);
options.AddRegistration(new OpenIddictClientRegistration
{
Issuer = ...,
ClientId = ...,
ClientSecret = ...,
Scopes = { Scopes.Profile, Scopes.Email, Scopes.Phone },
RedirectUri = new Uri(...),
PostLogoutRedirectUri = new Uri(...)
});
});
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("CookieAuthenticationPolicy", builder =>
{
builder.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme);
builder.RequireAuthenticatedUser();
});
});
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
.AddTransforms(builder => builder.AddRequestTransform(async context =>
{
var token = await context.HttpContext.GetTokenAsync(
scheme: CookieAuthenticationDefaults.AuthenticationScheme,
tokenName: Tokens.BackchannelAccessToken);
context.ProxyRequest.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Bearer, token);
}));
builder.Services.AddHostedService<Worker>();
#endregion
Ответ или решение
Проблема, с которой вы столкнулись, сигнализирует о том, что токен, получаемый от сервера OpenIDDict, имеет недействительный идентификатор (issuer). Ошибка invalid_token
с описанием The issuer associated to the specified token is not valid
может возникать по нескольким причинам. Давайте рассмотрим возможные причины и решения этой проблемы.
Причины ошибки
-
Несоответствие конфигурации Issuer: Убедитесь, что конфигурация
Issuer
в клиентской и серверной частях совпадает. При дополнительной развертке (например, на Azure) ваша конфигурация, возможные ошибки или опечатки могут производить несовпадение. -
Проблемы кеширования: Ваша проблема с интермитированным сбоем может быть связана с кешированием на стороне клиента или на сервере. В случае, если экземпляр OpenIDDict изменяется и новый токен выдает другой issuer, старые токены могут привести к этой ошибке.
- Разные URL-адреса: Если на локальной машине используется один URL (например,
localhost
), а в производственной среде – другой, отличающийся поддоменом или протоколом (http/https), это может вызвать несоответствие issuers.
Решения проблемы
-
Убедитесь в совпадении Issuer:
Проверьте конфигурацию сервера OpenIDDict и клиента. Важно, чтобы значениеIssuer
, заданное в клиенте, совпадало с тем, что используется на сервере. Пример конфигурации на сервере может выглядеть так:options.SetIssuer(new Uri("https://your-issuer-url"));
А в клиенте убедитесь, что вы используете то же значение:
options.AddRegistration(new OpenIddictClientRegistration { Issuer = new Uri("https://your-issuer-url"), ... });
-
Настройте кэширование на уровне токенов:
Если текущая конфигурация использования кеша вызывает проблемы, рассмотрите возможность изменения механизма кеширования. Например, возможно использование Redis или другого подхода для хранения состояния токенов. -
Убедитесь в однообразии URL:
Убедитесь, что у вас согласованы URL-адреса на всех средах. Проверьте не только сам адрес, но и протокол (http/https). Иногда отличия могут происходить из-за наличия дополнительных слешей или неверно настроенных редиректов. -
Запись логов:
Включите логирование на уровне OpenIDDict и ASP.NET Core. Это поможет вам более точно установить, когда и почему возникает проблема, а также предоставить дополнительную информацию о строках, вызывающих ошибку. - Протестируйте в разных сервисах:
Попробуйте тестировать на различных службах, чтобы обойтись без каких-либо проблем, связанных с Azure App Service. Возможны случаи, когда конфигурация Azure или проблемы с сетью могут влиять на аутентификацию.
Итог
Проблема, с которой вы столкнулись, может исходить из конфигурационных несоответствий или проблем с кешированием токенов. Очень важно, чтобы все параметры конфигурации для клиента и сервера совпадали, и отсутствовали расхождения между средами. Настройка логирования и предоставление статуса ошибок пользователям также может улучшить пользовательский опыт, если проблемы повторяются.