JavaScript · API · Середній

JWT-автентифікація

5 завдань

Використовуйте JSON Web Tokens для автентифікації та обробляйте оновлення токенів.

JWT — access та refresh токени

#
JWT (JSON Web Token) аутентифікація використовує два токени замість одного: - **Access token** — короткоживучий (хвилини/години). Надсилайте його в кожному запиті як `Bearer <access_token>`. - **Refresh token** — довгоживучий (дні/тижні). Використовується для отримання нового access token після закінчення строку дії старого. **Отримати обидва токени:** ```javascript const response = await fetch('https://apilearn.tukas.dev/api/auth/jwt/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'alice42', password: 'SecurePass123!' }), }); const { access, refresh } = await response.json(); ``` **Використати access token — зверніть увагу: `Bearer`, не `Token`:** ```javascript const profile = await fetch('https://apilearn.tukas.dev/api/users/profile/', { headers: { 'Authorization': `Bearer ${access}` }, }).then(r => r.json()); ``` **Оновлення — отримати новий access token:** ```javascript const response = await fetch('https://apilearn.tukas.dev/api/auth/jwt/refresh/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refresh }), }); const { access: newAccess, refresh: newRefresh } = await response.json(); ``` Ендпоінт оновлення повертає і новий access token, і новий refresh token — оновлюйте обидва.

Отримання та оновлення JWT-токенів

#
Повний JWT-потік із оновленням: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function getJwtTokens(username, password) { const response = await fetch(`${BASE_URL}/api/auth/jwt/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); return response.json(); // { access, refresh } } async function refreshTokens(refreshToken) { const response = await fetch(`${BASE_URL}/api/auth/jwt/refresh/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refresh: refreshToken }), }); return response.json(); // { access, refresh } } async function main() { // Крок 1: отримати початкові токени let { access, refresh } = await getJwtTokens('YOUR_USERNAME', 'YOUR_PASSWORD'); console.log('Access token:', access.slice(0, 20) + '...'); // Крок 2: використати access token const profile = await fetch(`${BASE_URL}/api/users/profile/`, { headers: { 'Authorization': `Bearer ${access}` }, }).then(r => r.json()); console.log('Профіль:', profile.username); // Крок 3: симулюємо оновлення (на практиці робіть це при отриманні 401) const refreshed = await refreshTokens(refresh); access = refreshed.access; refresh = refreshed.refresh; console.log('Новий access token:', access.slice(0, 20) + '...'); // Крок 4: використати новий access token const cart = await fetch(`${BASE_URL}/api/cart/`, { headers: { 'Authorization': `Bearer ${access}` }, }).then(r => r.json()); console.log('Товарів у кошику:', cart.items.length); } main(); ```

Довідник JWT

#
**Ендпоінти** ``` POST /api/auth/jwt/ Отримати access + refresh токени тіло: { username, password } повертає: { access, refresh } POST /api/auth/jwt/refresh/ Отримати нові токени через refresh token тіло: { refresh } повертає: { access, refresh } ``` **Використання access token** ```javascript headers: { 'Authorization': `Bearer ${access}` } // Зверніть увагу: "Bearer", а не "Token" — відмінність від токен-автентифікації ``` **Порівняння Token та JWT** ``` Token auth Один токен, не закінчується "Token <token>" JWT auth пара access + refresh "Bearer <access>" access закінчується, refresh оновлюється ``` **Паттерн оновлення** ```javascript let { access, refresh } = await getJwtTokens(user, pass); // Коли access token закінчується (401): const tokens = await refreshTokens(refresh); access = tokens.access; refresh = tokens.refresh; // також оновлюємо refresh ``` **Структура JWT (інформаційно)** ``` header.payload.signature — три частини base64, розділені крапками atob(access.split('.')[1]) — декодувати payload (містить exp, user_id тощо) ```
01

Отримати JWT-токени

#

POST до `/api/auth/jwt/` з вашими обліковими даними. Виведіть обидва токени — `access` і `refresh` (перших 30 символів достатньо).

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // POST /api/auth/jwt/ і вивести access + refresh (перші 30 символів)
}

main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/auth/jwt/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  });
  const { access, refresh } = await response.json();
  console.log('access:', access.slice(0, 30) + '...');
  console.log('refresh:', refresh.slice(0, 30) + '...');
}

main();
02

Використати access token для запиту

#

Отримайте JWT-токени, потім використайте `access` токен із префіксом `Bearer` для запиту до `/api/users/profile/`. Виведіть `username` і `email`.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // отримати JWT, використати access token із префіксом Bearer для запиту профілю
}

main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const { access } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  const profile = await fetch(`${BASE_URL}/api/users/profile/`, {
    headers: { 'Authorization': `Bearer ${access}` },
  }).then(r => r.json());

  console.log(profile.username);
  console.log(profile.email);
}

main();
03

Оновити access token

#

Отримайте початкові JWT-токени, потім одразу викличте `/api/auth/jwt/refresh/` з токеном `refresh`. Виведіть новий `access` токен (перших 30 символів) і переконайтесь, що він відрізняється від старого.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // отримати токени, потім оновити, порівняти старий і новий access
}

main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const { access: oldAccess, refresh } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  const { access: newAccess } = await fetch(`${BASE_URL}/api/auth/jwt/refresh/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refresh }),
  }).then(r => r.json());

  console.log('Old:', oldAccess.slice(0, 30));
  console.log('New:', newAccess.slice(0, 30));
  console.log('Different:', oldAccess !== newAccess);
}

main();
04

Декодувати payload JWT

#

Отримайте access token. Payload JWT — це середня частина (між двома крапками), закодована в base64. Декодуйте її через `atob()` і `JSON.parse()`. Виведіть `user_id` і `exp` з payload.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // отримати access token
  // розділити по '.', взяти індекс 1, декодувати через atob, розпарсити JSON
  // вивести user_id і exp
}

main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const { access } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  const payload = JSON.parse(atob(access.split('.')[1]));
  console.log('user_id:', payload.user_id);
  console.log('exp:', payload.exp);
  console.log('expires:', new Date(payload.exp * 1000).toISOString());
}

main();
05

Повний JWT-потік

#

Напишіть повний скрипт: отримайте токени, запитайте профіль через `access`, оновіть токени, потім запитайте кошик з новим `access`. Виведіть username із профілю та кількість товарів у кошику.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // 1. отримати JWT-токени
  // 2. запросити профіль через access
  // 3. оновити токени
  // 4. запросити кошик з новим access
}

main();
Рішення
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // 1. Initial tokens
  let { access, refresh } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  // 2. Fetch profile
  const profile = await fetch(`${BASE_URL}/api/users/profile/`, {
    headers: { 'Authorization': `Bearer ${access}` },
  }).then(r => r.json());
  console.log('Username:', profile.username);

  // 3. Refresh
  ({ access, refresh } = await fetch(`${BASE_URL}/api/auth/jwt/refresh/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refresh }),
  }).then(r => r.json()));

  // 4. Fetch cart with new token
  const cart = await fetch(`${BASE_URL}/api/cart/`, {
    headers: { 'Authorization': `Bearer ${access}` },
  }).then(r => r.json());
  console.log('Cart items:', cart.items.length);
}

main();