Solución:
Si desea eliminar todos los tokens de acceso anteriores antes de emitir uno nuevo, existe una solución simple para este problema: ¡Crea tu propio proveedor de vistas de token!
El código a continuación probablemente lo ayudará a lograr ese tipo de funcionalidad:
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)
La parte que debe notar es el bloque Try-Except. Allí encontramos los tokens de acceso y los eliminamos. Todo antes de crear uno nuevo.
Puede ver cómo crear su propio proveedor utilizando OAuthLib. Además, esto también podría ser útil: TokenView en django-oauth-toolkit. Puede ver allí el Apiview original. Como dijiste, estabas usando este paquete.
En cuanto a refresh_token, como se mencionó anteriormente en otras respuestas aquí, no puede hacer lo que está pidiendo. Al mirar el código de oauthlib
tipo gruñido de contraseña, verá que en su inicialización, refresh_token se establece en True. A menos que cambie el tipo de Grunt, no se puede hacer.
Pero puede hacer lo mismo que hicimos anteriormente con los tokens de acceso. Cree el token y luego elimine el token de actualización.
Lo que necesito es que cada vez que un usuario solicite un nuevo token de acceso, el anterior se volverá inválido, inutilizable y será eliminado.
Dar una nueva ficha cuando la pides parece un comportamiento esperado. ¿No es posible que revoque el existente antes de solicitar el nuevo?
Actualizar
Si está decidido a conservar solo un token, la clase OAuth2Validator hereda OAuthLib’s RequestValidator
y anula el método save_bearer_token. En este método, antes del código relacionado con la creación de la instancia del modelo AccessToken y su método .save (), puede consultar (similar a este) para ver si ya hay un AccessToken guardado en la base de datos para este usuario. Si se encuentra, el token existente se puede eliminar de la base de datos.
Le sugiero encarecidamente que haga este cambio configurable, en caso de que cambie de opinión en el futuro (después de que se emitan todos los tokens múltiples por razones como esta)
Una solución más simple es tener su propia clase de validación, probablemente una que herede oauth2_provider.oauth2_validators.OAuth2Validator
y anula save_bearer_token
. Esta nueva clase debe darse para OAUTH2_VALIDATOR_CLASS
en settings.py
Además, ¿hay alguna manera de que el tipo gruñido de contraseña no cree un token de actualización? No tengo ningún uso para eso en mi aplicación.
Django OAuth Toolkit depende de OAuthLib.
Hacer que refresh_token sea opcional se reduce a create_token
método en BearerToken
class de oAuthLib en esta línea y la clase para la concesión de contraseña está aquí. Como puede ver el __init__
el método para esta clase toma refresh_token
argumento que por defecto se establece en True
. Este valor se utiliza en create_token_response
método de la misma clase en la línea
token = token_handler.create_token(request, self.refresh_token)
create_token_response
método en OAuthLibCore
la clase del kit de herramientas Django OAuth es la que, creo, llama al correspondiente create_token_response
en OAuthLib. Observe el uso de self.server
y su inicialización en __init__
método de esta clase, que solo tiene el validador pasado como argumento, pero nada relacionado con refresh_token
.
Compare esto con el tipo de concesión implícita de OAuthLib create_token_response
método, que explícitamente hace
token = token_handler.create_token(request, refresh_token=False)
no crear refresh_token
en absoluto
Entonces, a menos que me haya perdido algo aquí, tldr, No creo que el kit de herramientas de Django OAuth exponga la característica de opcional refresh_token
.