我使用最新的Django OAuth2 Toolkit (0.10.0)与Python 2.7,Django 1.8和Django REST框架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/
新访问令牌和刷新令牌已创建。在令牌超时之前,旧访问和刷新令牌仍然可用!
我的问题:
我发现的一个解决方案是REST Framework OAuth一次为一个访问令牌提供配置。我并不急于使用该提供商,但我可能无法做出选择。
答案 0 :(得分:13)
如果您想在发布新密码之前删除所有以前的访问权限,可以使用以下方法解决此问题:创建自己的代币视图提供程序!
下面的代码可能会帮助您实现这种功能:
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块。在那里,我们找到了访问令牌并删除它们。在我们创建一个新的之前。
您可以查看如何创建自己的Provider using OAuthLib。 此外,这也可能有用:TokenView in django-oauth-toolkit。你可以在那里看到原始的Apiview。正如你所说,你正在使用这个包。
至于 refresh_token ,正如之前在其他答案中所提到的那样,你不能做你想要的。查看oauthlib
密码grunt类型的代码时,您会看到在初始化时,refresh_token设置为True。除非你自己更改Grunt类型,否则无法完成。
但是您可以使用访问令牌执行上述操作。 创建令牌,然后删除刷新令牌。
答案 1 :(得分:5)
我需要的是每次用户请求新的访问令牌时, 旧的将变为无效,无法使用并将被删除。
当您要求提供新令牌时,似乎是预期的行为。在要求新的revoke之前,您是否不可能OAuth2Validator现有的?
<强>更新强>
<小时/> 如果您决定只保留一个令牌 - 课程save_bearer_token会继承OAuthLibRequestValidator
并覆盖方法AccessToken model。在与this实例创建及其.save()方法相关的代码之前的此方法中,您可以查询(类似于this)以查看是否已为此用户在DB中保存了AccessToken。如果找到,则可以从数据库中删除现有令牌。
我强烈建议您将此更改配置为可配置,以防您日后改变主意(在this line之后发布所有多个令牌之后)
更简单的解决方案是拥有自己的验证器类,可能是继承oauth2_provider.oauth2_validators.OAuth2Validator
并覆盖save_bearer_token
的验证器类。这个新课程应该在OAUTH2_VALIDATOR_CLASS
settings.py
提供
另外,有没有办法让密码grunt类型不会创建刷新 令牌。在我的申请中,我没有任何用处。
Django OAuth Toolkit依赖于OAuthLib。
使refresh_token可选归结为here的o {{{}}类oAuthLib中的create_token
方法,密码授权类为OAuthLibCore
。正如您所看到的,此类的BearerToken
方法采用__init__
参数,默认情况下该参数设置为refresh_token
。该值用于
True
方法
create_token_response
我相信,OAuthLib Imlicit grant type类Django OAuth工具包中的 token = token_handler.create_token(request, self.refresh_token)
方法会调用OAuthLib中的相应create_token_response
。观察create_token_response
及其在此类的self.server
方法中的初始化的用法,该方法仅将验证器作为参数传递但与__init__
无关。
将此与{{3}}的refresh_token
方法进行比较,该方法明确地执行
create_token_response
根本不创建token = token_handler.create_token(request, refresh_token=False)
所以,除非我在这里遗漏了一些内容, tldr ,否则我不认为Django OAuth工具包暴露了可选refresh_token
的功能。
答案 2 :(得分:0)
接受的答案仍然无法清除RefreshToken。下面的代码应撤销刷新和访问令牌。
from oauth2_provider.models import RefreshToken
def clear_token(user):
"""
Clear all user authorized tokens.
"""
for token in RefreshToken.objects.filter(user=user, revoked__isnull=True):
token.revoke()
答案 3 :(得分:0)
这是一个直接制作的例子:
from oauthlib.common import generate_token
from oauth2_provider.models import AccessToken, Application
from django.utils import timezone
from dateutil.relativedelta import relativedeltatok = generate_token()
tok = generate_token()
app = Application.objects.first9)
user = User.objects.first()
access_token = AccessToken.objects.create(user=user, application=app, expires=timezone.now() + relativedelta(hours=1), token=tok)