Що всередині JWT і чому декодування не означає перевірку
JSON Web Token (JWT) — це три текстові фрагменти, з'єднані крапками: заголовок, корисне навантаження і підпис. Перші дві частини лише закодовані, а не зашифровані, тож кожен, хто має токен, може їх прочитати. Підпис дозволяє серверу перевірити, що токен видав довірений учасник і що його ніхто не змінював. Декодування токена показує, що в ньому написано. Лише перевірка показує, чи варто йому довіряти.
Декодер JWTТокен прострочений чи дійсний?БезкоштовноТри частини
Токен виглядає як header.payload.signature. Перша частина відомого прикладу токена з jwt.io:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Кожна з перших двох частин — це JSON, перетворений на base64url, форму тексту, безпечну для URL. Перша частина декодується в:
{"alg":"HS256","typ":"JWT"}
Корисне навантаження того самого прикладу декодується в:
{"sub":"1234567890","name":"John Doe","iat":1516239022}
Корисне навантаження містить твердження — відомості про користувача або сесію. Підпис обчислюється з перших двох частин і ключа, тож зміна одного символу робить його невідповідним. Base64url можна розкодувати без ключа, тому ніколи не кладіть у корисне навантаження пароль, приватний ключ чи персональні дані.
Зареєстровані твердження
RFC 7519, стандарт для JWT, резервує кілька коротких назв тверджень:
iss(видавець): хто створив токен.sub(суб'єкт): кого стосується токен, зазвичай ідентифікатор користувача.aud(аудиторія): сервіс, для якого призначений токен.exp(час закінчення): момент, після якого токен недійсний.nbf(не раніше): найперший момент, коли токен дійсний.iat(час видачі): коли токен створено.
Час задається в секундах від 1 січня 1970 року за UTC, тобто в часі Unix. У прикладі немає exp, тож за стандартом він ніколи не спливає. Справжній токен має його містити. Інші назви, як-от role чи email, належать самому застосунку.
Декодування — не перевірка
Декодування розбиває токен по крапках, розкодовує base64url і читає JSON. Воно показує, що токен стверджує, і так само працює з підробленим токеном, бо будь-хто може записати будь-які твердження з будь-яким підписом.
Перевірка перераховує підпис правильним ключем і звіряє, що він збігається. Вона також перевіряє, що поточний час лежить між nbf і exp, а iss і aud мають значення, які очікує сервіс. Застосунок, який читає твердження role без перевірки, довіряє тому, хто написав токен. Це поширена помилка.
HS256, RS256 і ES256
Значення alg називає метод. Поширені три:
- HS256 — HMAC із SHA-256. Один спільний секрет і підписує, і перевіряє, тож секрет має залишатися на сервері, який видає токени.
- RS256 — підпис RSA із SHA-256. Видавець підписує приватним ключем, а перевірити може будь-хто з публічним. Інші сервіси можуть перевіряти токени, не маючи змоги їх створювати.
- ES256 — підпис ECDSA на кривій P-256 із SHA-256. Працює як RS256, але з меншими ключами й підписами.
Використовуйте HS256, коли один сервіс і видає, і перевіряє свої токени. Використовуйте RS256 або ES256, коли інші сервіси мають перевіряти токени, які вони не видавали.
Проблеми, що виникають через довіру до заголовка
Заголовок пише той, хто надсилає токен, тож перевіряючий не повинен дозволяти йому вибирати правила.
alg: none. Токен без підпису може оголосити"alg":"none". Деякі бібліотеки колись приймали такі токени й пропускали перевірку. Задавайте дозволені алгоритми у власному коді, ніколи не беріть їх із токена.- Плутанина алгоритмів. Сервер очікує RS256 і має публічний ключ. Зловмисник надсилає токен HS256, підписаний цим публічним ключем як секретом HMAC. Перевіряючий, який приймає будь-який алгоритм, названий у заголовку, такий токен прийме. Прив'язуйте кожен ключ рівно до одного алгоритму.
- Слабкі секрети. Зловмисник має заголовок, корисне навантаження й підпис, тож може офлайн перебирати кандидатів на секрет. Короткий секрет або поширене слово швидко піддаються такому перебору. RFC 7518 рекомендує, щоб ключ HS256 мав щонайменше 256 біт і був випадковим.
Вставка робочого токена на сайт
Чинний токен працює для того, хто ним володіє, доки не закінчиться строк його дії. Ставтеся до нього як до пароля. Перш ніж вставляти його на сайт, з'ясуйте, чи надсилає сайт його на сервер. Інструмент, який працює повністю у вкладці браузера, цього не потребує. Будь-яку сторінку можна перевірити, спостерігаючи за її мережевими запитами в засобах розробника браузера.
Токени зазвичай не можна відкликати до закінчення строку, якщо сервер не веде список. Якщо живий токен витік, попросіть сервіс відкликати сесію або змінити ключі. Для налагодження, де можливо, використовуйте токен із тестового середовища. Декодер JWT читає три частини у вкладці вашого браузера, і нічого з вставленого нікуди не надсилається.
Вебхуки: та сама ідея зі спільним секретом
Більшість провайдерів вебхуків надсилають у заголовку HMAC тіла запиту, обчислений із секретом, яким ви ділитеся з ними. Ваш приймач обчислює той самий HMAC і порівнює два значення. Поширені помилки дрібні. JSON переформатовують перед хешуванням, тож байти змінюються. Тестовий секрет використовують для живого трафіку. Або підписи порівнюють звичайною рівністю рядків, що може розкривати інформацію про час. Використовуйте порівняння за сталий час.
Перевірка підпису вебхука обчислює підпис із вставленого секрету й тіла для GitHub, Stripe, Slack, Shopify або будь-якої схеми HMAC, тож ви бачите, чи збігаються два значення.
Короткі відповіді
Чи зашифровано JWT?
Ні. Стандартний JWT підписаний, і будь-хто може прочитати його заголовок і корисне навантаження. Від змін його захищає лише підпис.
Що буде, якщо я зміню корисне навантаження?
Підпис перестане збігатися, тож сервер, що перевіряє, відхилить токен. Читання тверджень не перевіряє підпис, тому декодер усе одно покаже вашу змінену версію.
Переклад з Англійський оригінал за допомогою ШІ.
Коментарі
Коментарів поки немає. Будьте першим.


