Формирование JWT-токенов в приложении

Формирование JWT-токенов в приложении #

Документация #

Подключение библиотеки Java JWT #

Библиотеку Java JWT можно использовать в любом JVM-проекте. Для веб-приложения необходимо добавить зависимость от библиотеки java-jwt в build.gradle. Возьмите последнюю доступную версию библиотеки. Выпуски можно посмотреть на mvnrepository.

Выбор алгоритма для подписи JWT-токена #

Библиотека поддерживает 3 варианта выполнения подписи:

  • HMAC — вычисление подписи на основании секретного ключа.
  • RSA — вычисление подписи с помощью асинхронного хеширования RSA.
  • ECDSA — вычисление подписи с помощью асинхронного хеширования ECDSA. Отличается от RSA более коротким ключом и более высокой стойкостью.

Использование RSA и ECDSA требует от разработчика создание валидной пары ключей. Желательно, чтобы сами ключи были выданы соответствующим сертифицированным центром. Обычно применяется, если служба идентификации отделена от самого приложения.

В рамках лабораторной и закрытых установок достаточно использовать HMAC-подписи. Секретный ключ для HMAC следует размещать в настройках приложения, чтобы его можно было подменить.

Указание алгоритма #

Для описания конкретного алгоритма подписи используется класс Algorithm. Для выбора алгоритма достаточно вызвать соответствующий метод алгоритма для подписи токена и передать ему необходимые данные.

Для создания алгоритма HMAC 512 следует воспользоваться методом Algorithm.HMAC512. Ему в качестве аргумента необходимо передать секретный ключ.

Описание алгоритма с параметрами настроек остаются актуальными во время работы всего приложения. Объект алгоритма можно создать один раз, а затем использовать при создании и проверки всех токенов в приложении.

Формирование JWT-токена #

Для создания подписи необходимо воспользоваться классом JWTCreator.Builder, который реализует шаблон проектирования строитель. Он предоставляет ряд методов, каждый из которых, позволяет установить поля для формируемого JWT-токена. Когда все поля установлены можно сформировать токен, вызвав метод sign. Данный метод возьмёт все данные, переданные ранее строителю, сформирует JWT-токен и подпишет его. Закодированный в base64-токен будет возвращён в виде строки.

В JWT-токен можно поместить любые данные, однако рекомендуется указать следующие поля:

  • withSubject() — для указания идентификатора пользователя. Затем это поле можно будет использовать для идентификации пользователя.
  • withExpiresAt() — для указания времени истечения времени работы токена, чтобы они не были бесконечно долгими. Есть 2 версии данного метода, принимающие разные формы указания конкретного момента истечения работы токена.
  • withIssuer() — для указания названия организации, которая выдала данный JWT-токен.

Стоит учесть, что метод sign может выбросить исключение. Его необходимо обработать в приложении.

Ввиду того, что при формировании JWT-токена все данные зависят от контекста вызова, то объект класса JWTCreator.Builder необходимо создавать заново для каждого запроса на создание токена.

Проверка JWT-токена #

Для проверки JWT-токена необходимо воспользоваться классом JWTVerifier. Для создания такого объекта нужно воспользоваться методом JWT.require, который принимает в качестве аргумента алгоритм для проверки подписи и возвращает объект типа Verification. Последний тоже реализует шаблон проектирования строитель. С помощью его методов можно описать ограничения: является ли проверяемый токен корректным или нет. После указания всех свойств необходимо вызвать метод build(), который вернёт объект типа JWTVerifier.

Для проверки указанных свойств можно воспользоваться методами:

  • withIssuer() — добавить проверку на идентификацию организации, выдавшей данный токен.
  • acceptExpiresAt() — для указания промежутка времени, в течение которого выданный токен считается корректным. Т.е. позволяет продлить время жизни токена на указанное время.

В отличие от задачи формирования JWT-токена созданный объект JWTVerifier можно повторно использовать для проверки JWT-токенов. Объект данного класса можно создать один раз для работы всего приложения, как и объект класса Algorithm.

Для проверки конкретного токена необходимо использовать метод JWTVerifier.verify(). Данный метод принимает себе в качестве аргумента JWT-токен и возвращает декодированный токен. В случае, если условия проверки не верны, тогда метод выбросит одно из следующих исключений:

  • AlgorithmMismatchException — алгоритм подписи не совпал.
  • SignatureVerificationException — подпись токена не верна.
  • TokenExpiredException — время жизни токена истекло.
  • MissingClaimException — в переданном токене нет нужного разрешения.
  • IncorrectClaimException — в переданном токене значение разрешения не совпало с исходным
  • JWTVerificationException — базовый класс для всех типов исключений.

Если исключение не было выброшено, то содержимое JWT-токена можно прочитать из содержимого структуры DecodedJWT. Для аутентификации пользователей нас будет интересовать метод getSubject().

Задача. Реализуйте процедур создания JWT-токенов #

Реализуйте класс JwtTools, предоставляющий методы по созданию и проверке JWT-токенов.

  1. Добавьте в приложение зависимость от библиотеки Java JWT.
  2. Добавьте в настройки приложения возможность считывания соли для вычисления хеша подписи JWT-токена.
  3. Добавьте в приложение класс JwtTools, позволяющий выполнять операции по формированию и проверки JWT-токена. В конструктор объекта следует передать:
    • секретную строку для формирования алгоритма
    • название организации для указания внутри токена
    • указание продолжительности жизни токена по умолчанию
  4. Добавьте в класс метод по созданию JWT-токена, который будет принимать в качестве аргумента идентификатор пользователя, строку. Данный метод должен возвращать строку, содержащую JWT-токен.
  5. Добавьте в класс метод по проверке JWT-токена. Данный метод должен принимать в качестве аргумента строку-токен и возвращать идентификатор пользователя, закодированный внутри токена.
  6. Проверьте работоспособность данных методов. Либо путём написания модульных тестов, либо путём вызова данных методов в главном файле приложения.

© A. M. Васильев, 2024, CC BY-SA 4.0, andrey@crafted.su