JWT (JSON Web Token) — це компактний формат передачі даних між сторонами у вигляді JSON-об'єкта, захищеного цифровим підписом. Токен може бути підписаний за допомогою HMAC (симетричний ключ) або RSA/ECDSA (асиметрична пара), що гарантує цілісність і справжність даних. Згідно з IETF RFC 7519, 2015, JWT використовується в мільйонах додатків для автентифікації, безпечного обміну claims і як формат ID Token в OpenID Connect.
Головне
JSON Web Token (JWT) — це відкритий стандарт (RFC 7519), що визначає компактний і самодостатній спосіб передачі інформації між сторонами у вигляді JSON-об'єкта. Інформація в JWT називається claims — твердження про суб'єкта (користувача) та додаткові атрибути. Кожен claim — це пара ключ-значення: ідентифікатор користувача, роль, термін дії, видавець.
JWT називається самодостатнім, тому що вся інформація для перевірки міститься всередині самого токена. Серверу не потрібно звертатися до бази даних або зовнішнього сховища, щоб переконатися у валідності токена — достатньо перевірити підпис. Ця властивість робить JWT ідеальним для розподілених систем та мікросервісної архітектури, де кілька сервісів повинні автентифікувати запити без спільного сховища сесій.
За даними Auth0, 2025, понад 65% мобільних та веб-додатків використовують JWT як основний формат токена для API-автентифікації, випереджаючи випадкові рядки (opaque tokens) та сесійні ідентифікатори.
JWT складається з трьох частин, розділених крапками: header.payload.signature. Кожна частина являє собою Base64url-закодований JSON. Розглянемо кожну частину докладно.
Header містить два обов'язкові поля: alg (algorithm — алгоритм підпису) і typ (type — тип токена, завжди «JWT»). Алгоритм може бути симетричним (HS256 — HMAC з SHA-256) або асиметричним (RS256 — RSA з SHA-256, ES256 — ECDSA з P-256). Асиметричні алгоритми є кращими, оскільки дозволяють клієнту перевіряти підпис без володіння секретним ключем.
Приклад декодованого header:
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-id-1"
}
Payload містить claims — твердження про суб'єкта. Claims поділяються на три типи: зареєстровані (iss, sub, aud, exp, nbf, iat, jti), публічні (визначені розробником у IANA Registry) і приватні (узгоджені між сторонами). sub (subject) — унікальний ідентифікатор користувача. exp (expiration) — timestamp закінчення терміну дії токена. iss (issuer) — видавець токена.
{
"sub": "user-abc-123",
"iss": "https://auth.example.com",
"aud": "my-mobile-app",
"exp": 1812345678,
"iat": 1812342078,
"role": "premium_user"
}
Signature створюється шляхом застосування алгоритму підпису до конкатенації header і payload з використанням секретного або приватного ключа. Формула: HMACSHA256(base64UrlEncode(header) + «.» + base64UrlEncode(payload), secret) для HMAC, або RSASHA256(...) для асиметричного алгоритму. Отримувач обчислює підпис тим самим способом і порівнює з отриманим — якщо вони збігаються, дані не були змінені.
Процес роботи з JWT складається з двох фаз: створення (випуск) токена сервером автентифікації та перевірка токена клієнтом або сервером ресурсів. Сервер автентифікації отримує облікові дані користувача, створює payload з claims і підписує його. Отриманий JWT надсилається клієнту у відповідь на запит логіна або в тілі відповіді OAuth 2.0 / OpenID Connect.
У мобільних додатках JWT використовується наступним чином: після успішного входу користувач отримує access token у форматі JWT. Додаток зберігає його у захищеному сховищі (Keychain на iOS, EncryptedSharedPreferences на Android). При кожному запиті до API додаток додає заголовок Authorization: Bearer <token>. Сервер API перевіряє підпис JWT, витягує claims і на їх основі приймає рішення про доступ — без звернення до бази даних.
За даними Google Codelabs, 2025, використання JWT у Firebase Authentication скорочує кількість запитів до сервера автентифікації на 40–60% порівняно з сесійними токенами, оскільки дані перевіряються локально на кожному мікросервісі. Це особливо важливо для архітектур з високим навантаженням, де кожна мілісекунда затримки впливає на користувацький досвід. При 50 000 запитах на хвилину перехід на JWT може заощадити до 10 серверних інстансів, що обробляють introspection-запити.
JWT і Session Token вирішують одне завдання — автентифікацію запитів — але принципово відрізняються за архітектурою. Session Token — це випадковий рядок-ідентифікатор, який посилається на дані сесії, що зберігаються на сервері (stateful). JWT — самодостатній токен, що містить усі дані всередині себе (stateless).
| Параметр | JWT | Session Token |
|---|---|---|
| Зберігання даних | Всередині токена (самодостатній) | На сервері (сесійне сховище) |
| Масштабування | Не потребує shared storage | Вимагає Redis/БД для multi-server |
| Відкликання токена | Складне (потрібен blacklist) | Просте (видалити сесію з БД) |
| Розмір | Великий (500–2000 байт) | Малий (16–64 байти) |
| Перевірка підпису | Криптографічна | Немає (порівняння рядків) |
JWT виграє в розподілених системах: мікросервіси можуть перевіряти токен локально без спільного сховища. Наприклад, в архітектурі з п'ятьма мікросервісами кожен сервіс перевіряє JWT за 1–2 мс без мережевого виклику, в той час як session token потребує звернення до централізованого Redis при кожному запиті, додаючи 10–30 мс затримки. Однак JWT складно відкликати — якщо токен вже випущений, він дійсний до закінчення терміну. Session Token легко відкликати, видаливши запис з БД або Redis.
Для мобільних додатків комбінований підхід — JWT з коротким терміном життя (15–30 хвилин) і Refresh Token — дає баланс між продуктивністю та безпекою. JWT використовується для доступу до API, а refresh token (зазвичай opaque) — для отримання нових JWT. При компрометації JWT зловмисник має доступ на 15–30 хвилин; при компрометації refresh token сесія блокується через rotation і reuse detection.
Безпека JWT залежить від правильної реалізації. Найпоширеніша вразливість — атака «alg none»: зловмисник змінює header токена на «alg»: «none», і сервер, не перевіривши алгоритм, приймає підроблений токен. Захист: завжди перевіряти, що алгоритм у header відповідає очікуваному (RS256, ES256), і відхиляти токени з alg: none.
Вразливості JWT також включають: слабкий секретний ключ для HMAC (перебір за хвилини), витік приватного ключа (підпис будь-яких даних від імені сервера), зберігання чутливих даних у payload (JWT не шифрує, тільки підписує), атака через JWK header injection (впровадження власного публічного ключа). Використання перевірених бібліотек — Nimbus JOSE + JWT, jjwt (io.jsonwebtoken), PyJWT — знижує ризик експлуатації цих вразливостей.
Додатковий захід захисту — JWK Thumbprint (RFC 7638): прив'язка публічного ключа до токена через відбиток (thumbprint) у header. Якщо сервер зберігає очікуваний thumbprint для кожного клієнта, атака JWK header injection стає неможливою — сервер відхиляє будь-який ключ, що не збігається з зареєстрованим. OAuth Security Workshop 2025 рекомендує JWK Thumbprint як обов'язковий захист для всіх JWT, що використовуються у фінансових та медичних додатках.
Бібліотека jjwt (auth0/java-jwt) дозволяє створювати та перевіряти JWT в Android-додатку за кілька рядків. У прикладі нижче сервер генерує токен з sub і role, а клієнт перевіряє підпис. Для безпечного зберігання секретного ключа на сервері використовуйте змінні оточення або HSM (Hardware Security Module) — зберігання ключа в коді або конфігураційному файлі є грубою помилкою безпеки.
val secret = "my-256-bit-secret-key-here"
val token = JWT.create()
.withSubject("user-abc-123")
.withIssuer("auth.example.com")
.withClaim("role", "premium_user")
.withExpiresAt(Date(System.currentTimeMillis() + 3600000))
.sign(Algorithm.HMAC256(secret))
// Відправка токена клієнту
println("JWT: $token")
fun verifyToken(token: String): Boolean {
return try {
val decoded = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("auth.example.com")
.build()
.verify(token)
// Підпис вірний, claims витягнуто
println("Subject: ${decoded.subject}")
true
} catch (e: Exception) {
println("Токен недійсний: ${e.message}")
false
}
}
Часто задавані питання
Ні. JWT підписується, а не шифрується — будь-хто може декодувати Base64 payload і прочитати дані. Чутлива інформація (паролі, номери карток, персональні дані) повинна передаватися тільки в зашифрованому вигляді через JWE (JSON Web Encryption).
Рекомендується ES256 (ECDSA з P-256) — він забезпечує еквівалентний RSA 2048-bit рівень безпеки при значно меншому розмірі підпису. Для сумісності з легасі-системами підходить RS256. HS256 (HMAC) потребує безпечного обміну секретним ключем, що складніше в розподіленій архітектурі.
JWT не можна відкликати безпосередньо — він дійсний до exp. Рішення: використовувати короткий термін життя (15–30 хвилин), вести blacklist відкликаних jti (JWT ID) на сервері, або зв'язувати токени з версією секретного ключа. Refresh token при цьому відкликається стандартним способом — видаленням зі сховища.
Bearer token — це концепція: будь-який токен, який пред'явник (bearer) може використовувати для доступу. JWT — це конкретний формат токена. Bearer token може бути JWT, а може бути opaque string. JWT додає до концепції Bearer самодостатність і криптографічну верифікацію.
Типовий JWT з RS256 підписом займає 500–2000 байт. Якщо payload містить багато кастомних claims або використовується асиметричний підпис з великим ключем, розмір може досягати 4–5 KB. Це значно більше, ніж session token (16–64 байти), що впливає на розмір HTTP-заголовків.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також