AWS Cognito для аутентификации Django3 + DRF - PullRequest
1 голос
/ 20 февраля 2020

Я пытаюсь настроить AWS Cognito backend. У меня уже есть интерфейс React, уже работающий с ним, теперь мне нужен мой DRF API для аутентификации с использованием Cognito в качестве backend.

Я нашел несколько Python пакетов для этого, ни один из них, кажется, не поддерживается активно django -рантрант не работает с Django3 и в значительной степени мертв

Django Cognito JWT , кажется, моя лучшая ставка, но также не поддерживается активно, документация очень плохая, и есть средний пост о том, как использовать, не очень подробный, но лучше, чем ничего.

Итак, я попытался следовать документации

Добавил env vars в мои настройки

COGNITO_AWS_REGION = 'us-east-1'
COGNITO_USER_POOL = 'us-east-1_xxxxxxx'  # same user pool id I'm using on the React app
COGNITO_AUDIENCE = 'XXXXXXXXXXXXXXXXXXXXXX' # the same client id I'm using on the React app

Затем в моих классах аутентификации DRF:

    'DEFAULT_AUTHENTICATION_CLASSES': [
        'django_cognito_jwt.JSONWebTokenAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ],

И, наконец, модель пользователя:

AUTH_USER_MODEL = 'accounts.MyUser'
COGNITO_USER_MODEL = "accounts.MyUser"

Моя пользовательская модель пользователя:

class MyUser(AbstractUser):
    """User model."""

    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

Я также использую пакет DRF JWT, и если я пытаюсь войти в систему с пользователем Cognito , что-то вроде:

curl -X POST -H "Content-Type: application/json" -d '{"email":"user@invalid.com","password":"secretpassword"}' http://localhost/api-token-auth/

Я получаю ошибку

{"non_field_errors":["Unable to log in with provided credentials."]}* 1 035 *

С другой стороны, если я пытаюсь войти в систему с локальным Django пользователем через Django Rest Framework JWT, он работает нормально, и я получаю токен JWT в качестве ответа, поэтому я предполагаю, что проблема заключается в интеграции Cognito. .

Есть идеи, что мне не хватает? или как я могу отладить, чтобы выяснить, что происходит?

ОБНОВЛЕНИЕ

Поработав немного о коде, я обнаружил несколько вещей:

Даже при выполнении аутентификации DRF JWT код заканчивается в: django / contrib / auth / init .py, где он проходит через все бэкэнды аутентификации для Django, а не для DRF:

for backend, backend_path in _get_backends(return_tuples=True):

Все еще используя ModelBackend для аутентификации пользователя.

Итак, я думаю, мне также нужно добавить некоторый сервер аутентификации Cognito для Django. Я проверил, могу ли я просто использовать тот же самый бэкэнд, который используется в DRF, но затем я получил ошибку неверного аргумента: TypeError: authenticate() got an unexpected keyword argument 'email'

UPDATE 2 Кажется, что одна из проблем заключается в том, что Я использую электронную почту вместо имени пользователя для аутентификации, и ни один из пакетов не поддерживает его

1 Ответ

1 голос
/ 20 февраля 2020

Как правило, есть 2 шага для достижения вашей цели.

  1. Получить IdToken и AccessToken из библиотеки Cognito by Boto3.
  2. Применить IdToken в этом шаблоне Authorization Bearer IdToken для вызова API через curl.

В отличие от rest_framework_jwt, django_cognito_jwt имеет дело только с токеном JWT в заголовке. django_cognito_jwt не охватывает шаг 1. Вот почему вы получаете эту ошибку TypeError: authenticate() got an unexpected keyword argument 'email'.

Итак, решение - использовать boto3, чтобы получить IdToken и применить curl, передав заголовок Authorization:Bearer IdToken.

...