Используйте TokenAuthentication и SocialAuthentication из AllAuth

Я создал новый Django Rest API благодаря Django Rest Framework и хочу использовать два типа аутентификации: TokenAuthentication и SocialAuthentication с двумя провайдерами Facebook и Google.

Аутентификация токена прошла успешно (при таком синтаксисе : Authorization: Token <token>. Однако я не могу заставить его работать с SocialAuthentication. Когда я получаю access_token из моего POST в GoogleSocialLoginView, я не могу использовать его для входа в заголовки вызовов API других пользователей (я использую аутентифицированные разрешения для CRUD-вызовов других пользователей). Мой синтаксис для социальной аутентификации следующий :

Authorization : Bearer <token>

Итак, пользователи успешно зарегистрированы в базе данных, но они не могут аутентифицировать нас в API после этого.

Это часть моего файла settings.py

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework_swagger',
    'rest_framework.authtoken',
    "dj_rest_auth",
    'dj_rest_auth.registration',
    'allauth', 
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.facebook',
    'allauth.socialaccount.providers.google',
    # Local apps we created
    'api',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'thetiptop.urls'
AUTH_USER_MODEL = 'api.Users'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS':'rest_framework.schemas.coreapi.AutoSchema',
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}
REST_AUTH_SERIALIZERS = {
    "LOGIN_SERIALIZER": "api.serializers.CustomLoginSerializer",
}

REST_USE_JWT = True
ACCOUNT_LOGOUT_ON_GET = True
OLD_PASSWORD_FIELD_ENABLED = True
SITE_ID = 2
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
CORS_ALLOW_ALL_ORIGINS = True

SOCIALACCOUNT_QUERY_EMAIL = True
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USERNAME_REQUIRED = False
SOCIALACCOUNT_PROVIDERS = { 
    'google': { 
        'SCOPE': ['email'],
        'AUTH_PARAMS': { 'access_type': 'online' }
    },
    'facebook': { 
        'METHOD': 'oauth2',
        'SCOPE': ['email'],
        'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
        'INIT_PARAMS': {'cookie': True},
        'LOCALE_FUNC': lambda request: 'en_US',
        'EXCHANGE_TOKEN': True,
        'VERIFIED_EMAIL': False,
        'VERSION': 'v13.0'
    }
}

В моем файле url.py перечислены эти URL :

    path('auth/login/', obtain_auth_token, name='login'),
    path('auth/', include('dj_rest_auth.urls')), 
    path('auth/registration/', include('dj_rest_auth.registration.urls')),
    path('auth/facebook/', FacebookLogin.as_view(), name='fb_login'),
    path('auth/google/', GoogleLogin.as_view(), name='google_login'),
    path('accounts/', include('allauth.urls')),

И, наконец, GoogleLogin и FacebookLogin - это то же самое, что и :

from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
from allauth.socialaccount.providers.oauth2.client import OAuth2Client

class FacebookLogin(SocialLoginView):
    adapter_class = FacebookOAuth2Adapter

class GoogleLogin(SocialLoginView):
    adapter_class = GoogleOAuth2Adapter
    client_class = OAuth2Client

Наконец, я использую этот тип аутентификации для других вызовов CRUD :

from rest_framework import permissions

permission_classes = [permissions.IsAuthenticated]

Знаете ли вы решение для использования аутентификации с помощью токенов и социальной аутентификации allauth в одном классе User ?

PS: Я потребляю API из приложения Angular.

Важно помнить, что существует разница между системой аутентификации по умолчанию в Django и системой аутентификации для DRF. В вашей конфигурации DRF вы указали только два класса: rest_framework.authentication.SessionAuthentication и rest_framework.authentication.TokenAuthentication. SessionAuthentication - единственный, который совместим с бэкендом аутентификации сессии Django по умолчанию (но это может быть не то, что вам нужно в любом случае).

Как описано в руководстве по DRF API если вы используете аутентификацию на основе сеанса, вы должны включить маркер CSRF для аутентифицированных запросов:

Если вы используете API в стиле AJAX с SessionAuthentication, вам нужно убедиться, что вы включаете действительный CSRF-токен для любых "небезопасных" вызовов HTTP-методов, таких как PUT, PATCH, POST или DELETE запросы. [...]
Проверка CSRF в REST-фреймворке работает несколько иначе, чем в стандартном Django, из-за необходимости поддержки сеансовой и несеансовой аутентификации для одних и тех же представлений. Это означает, что только аутентифицированные запросы требуют CSRF-токенов, а анонимные запросы могут отправляться без CSRF-токенов.

Итак, если вы используете сессию пользователя (при условии, что вы предварительно аутентифицировали сессию пользователя), вам необходимо передать CSRF-токены при вызове DRF API в дополнение к cookie сессии.


Вы можете рассмотреть возможность использования метода аутентификации, который работает непосредственно с DRF, например , рекомендованного в документации DRF, например drf-social-oauth2. Затем добавьте его непосредственно в классы аутентификации DRF.

Вернуться на верх