Используйте 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.