PRO

Как реализовать аутентификацию OAuth2 / JWT в FastAPI?

В FastAPI OAuth2-схему часто используют для извлечения bearer token из заголовка Authorization, а JWT — как формат самого access token. Типичный поток: проверить логин и пароль, выдать подписанный JWT, затем извлечь и проверить токен через dependency для защищённых endpoints.
Подробный ответ

OAuth2 и JWT — не одно и то же

OAuth2 — это протокол и набор flow для делегированной авторизации. JWT — формат токена с claims, который часто применяют в OAuth2-подобной bearer-аутентификации. В FastAPI OAuth2PasswordBearer помогает извлечь токен из заголовка, но сам не проверяет пароль и не создаёт JWT.

Извлечение Bearer token

from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl='/api/v1/auth/token')


@app.get('/api/v1/profile')
def get_profile(token: str = Depends(oauth2_scheme)):
    return {'token': token}

Клиент передаёт токен в заголовке Authorization: Bearer <token>.

Создание токена

После проверки учётных данных сервер создаёт JWT с идентификатором пользователя, сроком действия и другими нужными claims. Токен подписывают секретом или приватным ключом; пароль и чувствительные данные в payload не помещают.

from datetime import datetime, timedelta, timezone
from jose import jwt

SECRET_KEY = 'secret-from-environment'
ALGORITHM = 'HS256'


def create_access_token(subject: str) -> str:
    expires_at = datetime.now(timezone.utc) + timedelta(minutes=30)
    payload = {'sub': subject, 'exp': expires_at}
    return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)

Dependency текущего пользователя

Следующая dependency декодирует токен, проверяет подпись, срок действия и находит пользователя. Она становится единой точкой контроля аутентификации для защищённых endpoint.

from fastapi import HTTPException, status


def get_current_user(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username = payload.get('sub')
        if username is None:
            raise ValueError('Missing subject')
    except Exception:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail='Invalid credentials',
            headers={'WWW-Authenticate': 'Bearer'},
        )
    return get_user_by_username(username)

Безопасность

Секреты нужно хранить вне репозитория, использовать HTTPS, выбирать короткий срок жизни access token и продумывать refresh tokens, отзыв токенов и rotation ключей. Аутентификация отвечает на вопрос «кто пользователь», а права на действия задают отдельно через dependency или policy layer.

Как ответить на собеседовании

Я использую OAuth2PasswordBearer для извлечения bearer token, выдаю после логина подписанный JWT и проверяю его в dependency get_current_user. OAuth2-схема и JWT выполняют разные роли: первая описывает механизм авторизации, а второй является форматом токена.

Оцени свой прогресс

Честно оцени своё понимание этого вопроса, чтобы мы могли построить твой учебный трек максимально эффективно.
Читать в блоге