Модуль 29

JWT та token authentication

Ось готовий урок, створений за твоїм майстер-промптом.


🎓 CS50-Style: JWT та Token Authentication

Привіт, друзі! 👋 Це CS50 (умовно 😉), і сьогодні ми розберемо тему, яка є кровоносною системою 99% сучасних веб-додатків.

1. 🔥 Вступ: Проблема «Амнезії» Сервера

Уявіть собі таку ситуацію. Ви приходите у великий бізнес-центр. На вході суворий охоронець запитує ваш паспорт, перевіряє його в базі даних і пропускає вас. Ви підходите до ліфта — там інший охоронець знову вимагає паспорт. Виходите на поверсі — знову перевірка. Хочете зайти в туалет — і там перевіряють паспорт!

Звучить як пекло, правда? Але саме так працює протокол HTTP.

HTTP — це протокол без стану (stateless). Це означає, що сервер має «амнезію». Коли ви відправляєте запит №2, він поняття не має, що запит №1 теж був від вас.

Риторичне запитання: Як зробити так, щоб ви один раз ввели логін/пароль, а далі сервер впізнавав вас автоматично, не запитуючи пароль при кожному кліку?

Раніше ми використовували сесії (Sessions). Це як запис у журналі охоронця: "Ага, Іван зайшов о 9:00, ось його ID". Але якщо у вас мільйон користувачів, цей журнал стає велетенським. А якщо у вас 10 серверів (охоронців)? Їм доведеться постійно перегукуватися між собою: "Ей, ти бачив Івана?".

Нам потрібен кращий спосіб. Нам потрібен JWT (JSON Web Token).

Уявіть фестивальний браслет. Ви один раз показуєте квиток на вході, вам чіпляють браслет. Все! Тепер будь-який охоронець на будь-якій сцені бачить браслет і знає: "Цьому хлопцю можна сюди". Йому не треба дзвонити на головний вхід. Ваші права доступу — прямо на вашій руці.


2. 🧠 Теоретична база: Що там «під капотом»?

Давайте розберемося, що таке JWT (вимовляється як "джот").

JWT — це відкритий стандарт передачі даних між клієнтом (браузером) і сервером у вигляді JSON-об'єкта. Але не простого, а підписаного.

Анатомія Токена

Якщо ви подивитеся на JWT, він виглядає як довгий рядок літер і цифр, розділених двома крапками. aaaaa.bbbbb.ccccc

Він складається з трьох частин:

  1. 🔴 Header (Заголовок): Який алгоритм шифрування використовується (наприклад, HS256). Це "метадані".
  2. 🟣 Payload (Корисне навантаження): Самі дані. Наприклад: {"userId": 123, "role": "admin"}.
  3. 🔵 Signature (Підпис): Це найважливіше! Це гарантія того, що дані не змінили.

Як працює магія (Інтуїтивно)

Уявіть, що ви відправляєте прозору скриньку з листом. * Header & Payload — це сам лист. Його може прочитати кожен (так-так, це важливо!). * Signature — це сургучева печатка на скриньці, яку поставив сервер своїм унікальним штампом (Secret Key).

Якщо хакер перехопить скриньку і змінить у листі "role": "user" на "role": "admin", то стара печатка вже не підійде до нового змісту (математично не зійдеться). А нову печатку хакер поставити не зможе, бо у нього немає унікального штампа (Secret Key), який є тільки у сервера.

❗️ Запам’ятати обов'язково: JWT не шифрує дані (за замовчуванням). Він їх підписує. Будь-хто, хто перехопив токен, може прочитати, що всередині. Тому ніколи не пхайте туди паролі!


3. 🧪 Приклади: Від простого до реального

Приклад 1: Сирий вигляд

Ви логінитесь у систему. Сервер перевірив пароль і віддав вам це:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Питання до вас: Що ви очікуєте побачити, якщо ми розкодуємо середню частину (після першої крапки)?

Давайте перевіримо. Це звичайний Base64 (спосіб кодування тексту). Всередині там:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
  • sub (subject) — ID користувача.
  • iat (issued at) — коли токен видали.

Приклад 2: Процес авторизації (Flow)

Як це виглядає у реальному житті веб-додатку:

  1. Клієнт: Відправляє POST запит /login з login та password.
  2. Сервер: Перевіряє базу. Все ок? Генерує JWT (бере ID юзера + Секретний ключ = Токен).
  3. Сервер: Віддає токен клієнту.
  4. Клієнт: Зберігає токен (наприклад, у LocalStorage).
  5. Клієнт: Хоче отримати список замовлень. Робить запит GET /orders. Але! У заголовок запиту додає: Authorization: Bearer <TOKEN>.
  6. Сервер: Бачить токен. Перевіряє підпис (Signature) своїм ключем. Підпис валідний? Токен не прострочений? Ок, ось твої замовлення. Базу даних для перевірки логіна чіпати не треба!

4. 🛠 Практична частина

Час забруднити руки! Виконайте ці завдання, щоб закріпити матеріал.

Завдання 1: Хірург токенів

Зайдіть на сайт jwt.io. Це головний інструмент розробника для роботи з JWT. 1. Подивіться на дефолтний токен. 2. У правій частині (Payload) змініть ім'я John Doe на своє ім'я. 3. Подивіться ліворуч: Що змінилося в зашифрованому рядку? Тільки середина чи й кінець? Чому?

Завдання 2: "Хакерська атака"

Уявіть, що ви — сервер. Ваш секретний ключ: "mySuperSecretKey". Використовуючи будь-яку онлайн-утиліту HMAC-SHA256 (або Node.js), спробуйте створити валідний підпис для даних {"user": "admin"}.

Завдання 3: Реалізація (Node.js псевдокод)

Вставте пропущені рядки в цей код:

const jwt = require('jsonwebtoken');

// 1. Користувач успішно ввів пароль
const user = { id: 55, username: "david_malan" };

// 2. Створення токена
// ПІДКАЗКА: нам потрібен user, секретний ключ і час життя токена
const token = jwt.sign(__________, 'SECRET_KEY', { expiresIn: '1h' });
console.log("Ваш токен:", token);

// 3. Перевірка токена (коли користувач повернувся)
try {
  const decoded = jwt.verify(token, __________);
  console.log("Ласкаво просимо,", decoded.username);
} catch(err) {
  console.log("Хто ти такий? Токен недійсний!");
}

Завдання 4: Міні-кейс

Ви створюєте додаток для банку. Чи безпечно передавати в Payload токена номер кредитної картки користувача? * А) Так, бо токен підписаний. * Б) Ні, бо Base64 легко розкодувати. * Обґрунтуйте відповідь.


5. 💡 Мислення як у розробника

Ось що відрізняє джуніора від сеньйора в темі JWT:

1. "Безсмертні" токени — це зло. Новачки часто роблять токени, які живуть вічно. Якщо хакер вкраде такий токен, він матиме доступ до акаунту назавжди. * Як думає про: Токен доступу (Access Token) має жити коротко (наприклад, 15 хвилин). Для подовження сесії використовуємо Refresh Token (він живе довше, але зберігається надійніше і його можна відкликати).

2. Де зберігати? * Новачок: Зберігає в LocalStorage браузера. Це зручно, але вразливо до XSS атак (якщо якийсь скрипт на сторінці вкраде токен). * Профі: Намагається використовувати HttpOnly Cookies. До них JavaScript не має доступу, а браузер сам відправляє їх на сервер.

3. Не вір клієнту. Навіть якщо токен валідний, завжди перевіряй, чи має цей юзер право на конкретну дію. Те, що у нього є бейдж "Співробітник", не означає, що він може відкрити сейф директора.


6. 🧩 Підсумок

Отже, що ми сьогодні вивчили?

  1. HTTP — забудькуватий. Йому потрібна допомога, щоб пам'ятати нас.
  2. JWT — це фестивальний браслет. Він дозволяє серверу зрозуміти, хто ви, не перевіряючи базу даних щоразу.
  3. Структура: Header + Payload + Signature.
  4. Головне правило: Підпис гарантує чесність, але не ховає інформацію.

Тепер ви вмієте реалізувати базову авторизацію, яка не "кладе" базу даних зайвими запитами.

🔜 У наступній серії: Гаразд, ми навчилися пускати користувачів за паролем. Але що, якщо ми хочемо, щоб вони заходили через Google або Facebook, не придумуючи нових паролів? Це називається OAuth 2.0. І це... тема нашого наступного уроку!

А поки що — успіхів у кодінгу! 👨‍💻👩‍💻