Как проверить JWT с использованием времени UTC с использованием .NET Core

В настоящее время я программирую ASP.NET-Core WebApi, используя JWT-Bearer-Authentication.

Чтобы сделать API доступным из разных часовых поясов, я использую следующий шаблон для установки полей nbf (notBefore) и exp (срок действия) внутри моего JWT в UTC-Timestamp:

var utcNow = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified);

...

var tokenOptions = new JwtSecurityToken(
                notBefore: utcNow,
                expires: utcNow.AddSeconds(3600),
            );
...

Для генерации токенов все работает довольно хорошо, nbf и exp содержат метку времени UNIX, представляющую текущее время UTC.

Но при проверке токена все работает в течение 5 минут (моя настройка смещения часов), а затем я получаю только 401 от API, потому что проверка токена выполняется с моим текущим часовым поясом здесь, в Германии.

Есть ли способ настроить JwtAuthentication-Middleware в .NET-Core для использования UTC-Time для проверки токена? Или есть другие способы решить эту проблему?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
3 571
3

Ответы 3

Одним из решений является проверка токена без истечения срока действия. Это вернет действительный токен, даже если срок действия токена истек. Затем в своем коде вручную проверьте время истечения срока действия токенов. Вот фрагменты кодов:

var validationParameters = new TokenValidationParameters()
{
   RequireExpirationTime = false,  // we can check manually
   ValidateIssuer = true,
   ValidateAudience = true,

   .
   .
   IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
};
            

Затем, когда токен проверен, проверьте время истечения срока действия с помощью:

public bool IsExpired(DateTime now)
{
    return JwtSecurityToken.ValidTo < Date.UtcNow;
}

Я надеюсь, что этот ответ поможет кому-то.

Для более полного ответа, в вашем Startup.cs:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                // ...
                ValidateLifetime = true,
                LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, 
                                     TokenValidationParameters validationParameters) => 
                {
                    return notBefore <= DateTime.UtcNow &&
                           expires >= DateTime.UtcNow;
                }
            };
        });

Это не учитывает настройку ClockSkew.

disklosr 30.09.2020 12:18

Почему? Перекос часов будет означать разницу максимум в несколько секунд, что не имеет значения для этого типа приложений ... перекос часов - это проблема, о которой должны беспокоиться цифровые схемы, а не проверка подлинности программного обеспечения.

Serj Sagan 30.09.2020 19:20

На серверах действительно случаются дрейфы часов, и это может привести к случайному отклонению / принятию токена в зависимости от сервера, на который вы попали. Причина, по которой это свойство существует, означает, что оно имеет значение.

disklosr 02.10.2020 00:04

Кроме того, библиотека ms уже проверяет время в utc, поэтому код, знающий ответ, не дает никакой дополнительной ценности.

disklosr 02.10.2020 00:05

Я имею в виду, да, вы правы в том, что ClockSkew это вещь, но по умолчанию ASP.NET установлено на 5 минут... которое будет превышено только в очень редких случаях. ClockSkew обычно всего несколько секунд... так зачем связываться со значением по умолчанию?

Serj Sagan 02.10.2020 08:13

Значение по умолчанию 5 мн не будет учитываться в предоставленном вами коде, поскольку оно переопределяет логику проверки срока службы ASP.NET Core.

disklosr 03.10.2020 11:15

Нет, это не точно ... если специально не переопределить, по умолчанию установлено значение 5 минут. stackoverflow.com/a/55155711/550975

Serj Sagan 03.10.2020 13:28

Взгляните на исходный код или проведите несколько тестов самостоятельно. Когда вы переопределяете проверку времени жизни, это эквивалентно утверждению «Я знаю, что делаю», инфраструктура не выполняет никакой дополнительной проверки времени жизни, так как теперь ответственность за это лежит на разработчике.

disklosr 04.10.2020 17:56

Вы ошибаетесь... спасибо, что потратили мое время на поиск исходного кода, но это так, как я сказал... если специально не переопределить, он установлен на 5 минут: github.com/AzureAD/…

Serj Sagan 05.10.2020 01:01

Я не понимаю, почему вы отказываетесь понять мою точку зрения. Я никогда не говорил, что по умолчанию не было 5 минут. Я сказал следующее: 1. Ваш ответ не добавляет значение anh, поскольку проверка уже выполнена в utc библиотекой. 2. В вашем ответе не учитывается любое значение, установленное в ClockSkew, а это означает, что пожизненная проверка в вашем коде проверяется только на основе времени истечения срока действия без учета ClockSkew. Я надеюсь, что теперь это ясно для вас. Посмотрите мой ответ, в нем есть ссылка на соответствующий исходный код, который показывает, как ваш код предотвращает учет ClockSkew.

disklosr 06.10.2020 22:36

Это уже дело. Пакет System.IdentityModel.Tokens.Jwt действительно проверяет время жизни JWT по времени UTC. Вот соответствующий бит из источника:

public static void ValidateLifetime(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
        {
            ...

            if (notBefore.HasValue && expires.HasValue && (notBefore.Value > expires.Value))
                throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidLifetimeException(LogHelper.FormatInvariant(LogMessages.IDX10224, notBefore.Value, expires.Value))
                { NotBefore = notBefore, Expires = expires });

            DateTime utcNow = DateTime.UtcNow;
            if (notBefore.HasValue && (notBefore.Value > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew)))
                throw LogHelper.LogExceptionMessage(new SecurityTokenNotYetValidException(LogHelper.FormatInvariant(LogMessages.IDX10222, notBefore.Value, utcNow))
                    { NotBefore = notBefore.Value });
 
            if (expires.HasValue && (expires.Value < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate())))
                throw LogHelper.LogExceptionMessage(new SecurityTokenExpiredException(LogHelper.FormatInvariant(LogMessages.IDX10223, expires.Value, utcNow))
                    { Expires = expires.Value });

            // if it reaches here, that means lifetime of the token is valid
            LogHelper.LogInformation(LogMessages.IDX10239);
        }

https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/b5b7ed8fb8ce513469b51b87c5f76314783b74e3/src/Microsoft.IdentityModel.Tokens/Validators.cs#L268

Другие вопросы по теме