Django DRF с oAuth2 с использованием DOT (django-oauth-toolkit)
Я пытаюсь заставить DRF работать с oAuth2 (django-oauth-toolkit).
Я сосредоточился на http://httplambda.com/a-rest-api-with-django-and-oauthw-authentication/
Сначала я выполнил эту инструкцию, но позже, после получения ошибок аутентификации, я установил эту демонстрацию: https://github.com/felix-d/Django-Oauth-Toolkit-Python-Social-Auth-Integration
Результат был тот же: я не мог генерировать токен доступа, используя этот завиток:
curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u "<client_id>:<client_secret>" http://127.0.0.1:8000/o/token/
Я получил эту ошибку:
{"error": "unsupported_grant_type"}
Приложение oAuth2 было установлено с помощью пароля grant_type. Я изменил параметр grant_type на "учетные данные клиента" и попробовал этот завиток:
curl -X POST -d "grant_type=client_credentials" -u "<client_id>:<client_secret>" http://127.0.0.1:8000/o/token/
Это сработало, и я получил сгенерированный токен аутентификации.
После этого я попытался получить список всех сортов пива:
curl -H "Authorization: Bearer <auth_token>" http://127.0.0.1:8000/beers/
И я получил ответ:
{"detail":"You do not have permission to perform this action."}
Это содержимое views.py, которое должно показывать пиво:
from beers.models import Beer
from beers.serializer import BeerSerializer
from rest_framework import generics, permissions
class BeerList(generics.ListCreateAPIView):
serializer_class = BeerSerializer
permission_classes = (permissions.IsAuthenticated,)
def get_queryset(self):
user = self.request.user
return Beer.objects.filter(owner=user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
Я не уверен, что может быть проблемой здесь. Сначала выберите "unsuported grant type", а затем другой вызов curl. Это также происходит со мной, когда я сделал основной учебник из django-oauth-toolkit. Я использую Django 1.8.2 и python3.4
Спасибо за помощь!
Мои параметры settings.py выглядят как
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
SECRET_KEY = 'hd#[email protected]+^*%i+klb)o0by!bh&[email protected]'
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
)
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'oauth2_provider',
'rest_framework',
'beers',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
ROOT_URLCONF = 'beerstash.urls'
WSGI_APPLICATION = 'beerstash.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
)
}
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope', 'write': 'Write scope'}
}
Ответы
Ответ 1
Я попробовал демо, о котором вы упомянули, и все было в порядке.
$ curl -X POST -d "grant_type=password&username=superuser&assword=123qwe" -u"xLJuHBcdgJHNuahvER9pgqSf6vcrlbkhCr75hTCZ:nv9gzOj0BMf2cdxoxsnYZuRYTK5QwpKWiZc7USuJpm11DNtSE9X6Ob9KaVTKaQqeyQZh4KF3oZS4IJ7o9n4amzfqKJnoL7a2tYQiWgtYPSQpY6VKFjEazcqSacqTx9z8" http://127.0.0.1:8000/o/token/
{"access_token": "jlLpKwzReB6maEnjuJrk2HxE4RHbiA", "token_type": "Bearer", "expires_in": 36000, "refresh_token": "DsDWz1LiSZ3bd7NVuLIp7Dkj6pbse1", "scope": "read write groups"}
$ curl -H "Authorization: Bearer jlLpKwzReB6maEnjuJrk2HxE4RHbiA" http://127.0.0.1:8000/beers/
[]
В вашем случае, я думаю, вы создали приложение с неправильным "Тип разрешения авторизации".
Используйте эти настройки приложения:
Name: just a name of your choice
Client Type: confidential
Authorization Grant Type: Resource owner password-based
Этот https://django-oauth-toolkit.readthedocs.org/en/latest/rest-framework/getting_started.html#step-3-register-an-application сильно меня остановил.
Вот файл базы данных, который я создал: https://www.dropbox.com/s/pxeyphkiy141i1l/db.sqlite3.tar.gz?dl=0
Вы можете попробовать сами. Исходный код вообще не изменился.
Имя пользователя admin Django - суперпользователь, пароль - 123qwe.
Ответ 2
Когда вы используете "учетные данные клиента", он не устанавливает пользователя в генерируемый токен доступа, это корень этой ошибки you do not have permission
, которую вы видите.
При использовании типа гранта client credentials
вам необходимо установить обработчик разрешений Rest Framework для просмотра токенов, поскольку client credentials
не устанавливает пользователя на сгенерированный токен. Django OAuth Toolkit предоставляет пользовательские разрешения для этой цели:
https://django-oauth-toolkit.readthedocs.org/en/latest/rest-framework/permissions.html
Или, если весь ваш API подчинен тому же типу разрешений, вы можете просто установить обработчик разрешений по всему миру в файле settings.py
, например:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'oauth2_provider.ext.rest_framework.TokenHasReadWriteScope',
)
}
Это предполагает, конечно, что вы предоставляете разрешения read write
в то время.
Подробнее о областях здесь:
https://django-oauth-toolkit.readthedocs.org/en/latest/settings.html