Python · API · Средний уровень

JWT-авторизация

5 задач

Используйте JSON Web Tokens для авторизации, разберитесь с access/refresh токенами и обновлением токена.

JWT — access и refresh токены

#
JWT (JSON Web Token) — это вторая схема аутентификации, которую предлагает API наряду с токен-авторизацией. Главное отличие: вместо одного токена вы получаете два. - Access token — короткоживущий (минуты или часы). Отправляете его с каждым запросом. - Refresh token — долгоживущий (дни). Используется только для получения нового access token, когда старый истекает. Зачем два токена? Если access token украдут, им можно воспользоваться лишь короткое время. Refresh token остаётся в безопасности, так как путешествует реже — только при обновлении доступа. Формат заголовка Authorization для JWT использует 'Bearer' вместо 'Token': ``` Authorization: Bearer <access_token> ``` В requests: ```python import requests BASE_URL = 'https://apilearn.tukas.dev' access_token = '...' headers = {'Authorization': f'Bearer {access_token}'} response = requests.get(f'{BASE_URL}/api/users/profile/', headers=headers) ``` Когда access token истекает, не нужно снова запрашивать учётные данные у пользователя. Отправьте refresh token на эндпоинт обновления и получите новый access token: ```python response = requests.post( f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh_token}, ) new_access = response.json()['access'] ``` Токен-авторизация против JWT — когда что выбирать: - Токен-авторизация проще: один токен, понятный заголовок, без управления сроком действия. - JWT безопаснее для долгосрочных сессий: access token быстро истекает, снижая риск при перехвате. Стандарт в современных мобильных приложениях и SPA. Для скриптов и кратковременной автоматизации токен-авторизации часто достаточно. JWT становится важным, когда вы строите что-то, что остаётся аутентифицированным дни или недели.

Получение и обновление JWT токенов

#
Получите пару JWT (нужен зарегистрированный пользователь — смотрите тему token-auth): ```python import requests BASE_URL = 'https://apilearn.tukas.dev' credentials = {'username': 'alice42', 'password': 'securepass123'} response = requests.post(f'{BASE_URL}/api/auth/jwt/', json=credentials) tokens = response.json() access = tokens['access'] refresh = tokens['refresh'] print('access:', access[:20], '...') print('refresh:', refresh[:20], '...') ``` Используйте access token для вызова защищённого эндпоинта: ```python headers = {'Authorization': f'Bearer {access}'} profile = requests.get(f'{BASE_URL}/api/users/profile/', headers=headers).json() print(profile['username']) # 'alice42' ``` Когда access token истекает, используйте refresh token для получения нового: ```python response = requests.post( f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh}, ) new_access = response.json()['access'] print('новый access token получен') # Используйте новый access token для следующего запроса headers = {'Authorization': f'Bearer {new_access}'} ``` Практичный паттерн — оберните процесс авторизации в функции: ```python def get_tokens(username, password): response = requests.post( f'{BASE_URL}/api/auth/jwt/', json={'username': username, 'password': password}, ) return response.json()['access'], response.json()['refresh'] def refresh_access(refresh_token): response = requests.post( f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh_token}, ) return response.json()['access'] access, refresh = get_tokens('alice42', 'securepass123') headers = {'Authorization': f'Bearer {access}'} # ... позже, если access истёк: access = refresh_access(refresh) ```

Справочник JWT

#
Эндпоинты JWT: ``` POST /api/auth/jwt/ Получить пару access + refresh token тело: {username, password} возвращает: {access: '...', refresh: '...'} POST /api/auth/jwt/refresh/ Обновить access token тело: {refresh: '...'} возвращает: {access: '...', refresh: '...'} ``` Заголовок Authorization: ``` Authorization: Bearer <access_token> ``` Токен-авторизация против JWT: ``` Токен-авт. JWT Заголовок Token <t> Bearer <t> Токенов 1 2 (access + refresh) Срок действия Нет по умолч. Access истекает, refresh долгий Обновление Не нужно POST /api/auth/jwt/refresh/ Подходит для Скрипты, простое Долгие сессии, mobile, SPA ``` Пример: ```python # Получить токены r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={'username': u, 'password': p}) access, refresh = r.json()['access'], r.json()['refresh'] # Использовать headers = {'Authorization': f'Bearer {access}'} # Обновить r = requests.post(f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh}) access = r.json()['access'] ```
01

Получить пару JWT токенов

#

Выполните POST к /api/auth/jwt/ с логином и паролем. Выведите первые 30 символов как access, так и refresh токенов.

import requests

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

credentials = {'username': 'ВАШ_ЛОГИН', 'password': 'ВАШ_ПАРОЛЬ'}

# Получите пару JWT и выведите первые 30 символов каждого токена
Решение
import requests

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

credentials = {'username': 'ВАШ_ЛОГИН', 'password': 'ВАШ_ПАРОЛЬ'}
response = requests.post(f'{BASE_URL}/api/auth/jwt/', json=credentials)
tokens = response.json()
print(tokens['access'][:30])
print(tokens['refresh'][:30])
02

Авторизация по схеме Bearer

#

Получите JWT access token и используйте его со схемой Bearer для GET /api/users/profile/. Выведите логин и email из ответа.

import requests

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

# Получите access token, затем GET профиля с Authorization: Bearer <token>
Решение
import requests

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

r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={
    'username': 'ВАШ_ЛОГИН', 'password': 'ВАШ_ПАРОЛЬ',
})
access = r.json()['access']

headers = {'Authorization': f'Bearer {access}'}
profile = requests.get(f'{BASE_URL}/api/users/profile/', headers=headers).json()
print(profile['username'])
print(profile['email'])
03

Обновить access token

#

Получите пару JWT, затем сразу используйте refresh token для получения нового access token через POST /api/auth/jwt/refresh/. Выведите новый access token (первые 30 символов).

import requests

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

# 1. Получите начальную пару токенов
# 2. Используйте refresh token для получения нового access token
# 3. Выведите первые 30 символов нового access token
Решение
import requests

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

r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={
    'username': 'ВАШ_ЛОГИН', 'password': 'ВАШ_ПАРОЛЬ',
})
refresh = r.json()['refresh']

r2 = requests.post(f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh})
new_access = r2.json()['access']
print(new_access[:30])
04

Написать get_access_token()

#

Напишите функцию get_access_token(username, password), которая возвращает свежий JWT access token. Вызовите её и выведите результат.

import requests

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

def get_access_token(username, password):
    # POST к /api/auth/jwt/ и возврат access token
    pass

token = get_access_token('ВАШ_ЛОГИН', 'ВАШ_ПАРОЛЬ')
print(token[:30])
Решение
import requests

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

def get_access_token(username, password):
    response = requests.post(
        f'{BASE_URL}/api/auth/jwt/',
        json={'username': username, 'password': password},
    )
    return response.json()['access']

token = get_access_token('ВАШ_ЛОГИН', 'ВАШ_ПАРОЛЬ')
print(token[:30])
05

Написать refresh_access()

#

Напишите функцию refresh_access(refresh_token), которая возвращает новый access token через эндпоинт обновления. Затем напишите небольшой скрипт, который получает начальную пару и сразу обновляет access token, выводя оба (первые 20 символов каждого).

import requests

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

def refresh_access(refresh_token):
    # POST к /api/auth/jwt/refresh/ и возврат нового access token
    pass

# Получите начальную пару, затем обновите
Решение
import requests

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

def refresh_access(refresh_token):
    response = requests.post(
        f'{BASE_URL}/api/auth/jwt/refresh/',
        json={'refresh': refresh_token},
    )
    return response.json()['access']

r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={
    'username': 'ВАШ_ЛОГИН', 'password': 'ВАШ_ПАРОЛЬ',
})
original_access = r.json()['access']
refresh_token = r.json()['refresh']

new_access = refresh_access(refresh_token)

print('оригинальный:', original_access[:20])
print('обновлённый:', new_access[:20])