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