Создание токена доступа с помощью Django OAuth2 Toolkit

Я использую последний Django OAuth2 Toolkit (0.10.0) с Python 2.7, Django 1.8 и Django REST framework 3.3

При использовании grant_type=password я заметил какое-то странное поведение, когда пользователь запрашивает новый токен доступа:

curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u"<client_id>:<client_secret>" http://localhost:8000/o/token/

A новый токен доступа и токен обновления создан. старый токен доступа и обновления до сих пор используется до истечения времени ожидания маркера!

Мои проблемы:

  • Мне нужно, чтобы каждый раз, когда пользователь запрашивает новый токен доступа, старый станет недействительным, непригодным для использования и будет удален.
  • Кроме того, существует ли способ, которым тип grung для пароля не будет создавать обновление маркер. Я не использую это в своем приложении.

Одно из найденных мной решений заключается в том, что REST Framework OAuth предоставляет конфигурацию для одного токена доступа за раз. Я не хочу использовать этого провайдера, но у меня не будет выбора.

Ответ 1

Если вы хотите удалить все предыдущие токены доступа перед выпуском нового, существует простое решение этой проблемы: Сделать свой собственный поставщик токенов!

Ниже приведенный ниже код поможет вам в достижении такой функциональности:

from oauth2_provider.models import AccessToken, Application
from braces.views import CsrfExemptMixin
from oauth2_provider.views.mixins import OAuthLibMixin
from oauth2_provider.settings import oauth2_settings

class TokenView(APIView, CsrfExemptMixin, OAuthLibMixin):
    permission_classes = (permissions.AllowAny,)

    server_class = oauth2_settings.OAUTH2_SERVER_CLASS
    validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
    oauthlib_backend_class = oauth2_settings.OAUTH2_BACKEND_CLASS

    def post(self, request):
        username = request.POST.get('username')
        try:
            if username is None:
                raise User.DoesNotExist
            AccessToken.objects.filter(user=User.objects.get(username=username), application=Application.objects.get(name="Website")).delete()
        except Exception as e:
            return Response(e.message,status=400)

        url, headers, body, status = self.create_token_response(request)
        return Response(body, status=status, headers=headers)

Часть, которую вы должны заметить, это блок Try-Except. Там мы находим токены доступа и удаляем их. Все, прежде чем мы создадим новый.

Вы можете посмотреть, как создать свой собственный поставщик, используя OAuthLib. Кроме того, это может быть полезно также: TokenView в django-oauth-toolkit. Вы можете увидеть там оригинальный Apiview. Как вы сказали, вы использовали этот пакет.

Что касается refresh_token, как уже упоминалось в других ответах здесь, вы не можете делать то, что вы просите. Если вы посмотрите на код типа oauthlib grunt grut, вы увидите, что при его инициализации refresh_token имеет значение True. Если вы не измените тип Grunt, это не может быть сделано.

Но вы можете сделать то же самое, что и мы, с помощью токенов доступа. Создайте токен, а затем удалите токен обновления.

Ответ 2

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

Предоставление нового токена, когда вы запрашиваете его, похоже на ожидаемое поведение. Разве вам не возможно отменить существующий, прежде чем запрашивать новый?

Обновление


Если вы намерены сохранить только один токен - Класс OAuth2Validator наследует OAuthLib RequestValidator и переопределяет метод save_bearer_token. В этом методе перед кодом, связанным с моделью создания AccessToken и его методом .save() вы можете запросить (похоже на this), чтобы узнать, есть ли уже этот AccessToken, сохраненный в БД для этого пользователя. Если найден, существующий токен можно удалить из базы данных.

Я настоятельно рекомендую сделать это изменение настраиваемым, если вы измените свое мнение в будущем (ведь все же несколько токенов выдаются по причинам, таким как this)

Более простым решением является наличие собственного класса валидатора, возможно, который наследует oauth2_provider.oauth2_validators.OAuth2Validator и переопределяет save_bearer_token. Этот новый класс должен быть указан для OAUTH2_VALIDATOR_CLASS в settings.py


Кроме того, существует ли способ, которым тип grunt пароля не будет создавать обновление маркер. Я не использую это в своем приложении.

Инструмент Django OAuth зависит от OAuthLib.

Предоставление refresh_token необязательно сводится к методу create_token в классе BearerToken класса oAuthLib в этой строке, а класс для предоставления пароля - здесь. Как вы можете видеть, метод __init__ для этого класса принимает аргумент refresh_token, который по умолчанию имеет значение True. Это значение используется в методе create_token_response того же класса в строке

token = token_handler.create_token(request, self.refresh_token)

create_token_response метод в OAuthLibCore класс инструментария Django OAuth - тот, который, я считаю, вызывает соответствующий create_token_response в OAuthLib. Обратите внимание на использование self.server и его инициализацию в методе __init__ этого класса, который имеет только валидатор, переданный как аргумент, но ничего не связанный с refresh_token.

Сравните это с OAuthLib Неявный тип гранта create_token_response метод, который явно делает

token = token_handler.create_token(request, refresh_token=False)

не создавать refresh_token вообще

Итак, если я не пропустил что-то здесь, TL;DR, я не думаю, что инструментарий Django OAuth предоставляет функцию необязательного refresh_token.