from django.contrib.auth import get_user_model from oauth2_provider.contrib.rest_framework import OAuth2Authentication from oauth2_provider.oauth2_backends import get_oauthlib_core from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework import exceptions from rest_framework_jwt.settings import api_settings import jwt from django.utils.translation import ugettext as _ from common.redis_cache import redis_handler as rh jwt_decode_handler = api_settings.JWT_DECODE_HANDLER class OAuth2AuthenticationWithUser(OAuth2Authentication): """ OAuth 2 authentication backend using `django-oauth-toolkit` """ www_authenticate_realm = "api" user = get_user_model().objects.first() def authenticate(self, request): """ Returns two-tuple of (user, token) if authentication succeeds, or None otherwise. """ oauthlib_core = get_oauthlib_core() valid, r = oauthlib_core.verify_request(request, scopes=[]) if valid: return self.user, r.access_token request.oauth2_error = getattr(r, "oauth2_error", {}) return None class MyJSONWebTokenAuthentication(JSONWebTokenAuthentication): def authenticate_credentials(self, username): """ Returns an active user that matches the payload's user id and email. """ User = get_user_model() # username = jwt_get_username_from_payload(payload) if not username: msg = _('Invalid payload.') raise exceptions.AuthenticationFailed(msg) try: user = User.objects.get_by_natural_key(username) except User.DoesNotExist: msg = _('Invalid signature.') raise exceptions.AuthenticationFailed(msg) if not user.is_active: msg = _('User account is disabled.') raise exceptions.AuthenticationFailed(msg) return user def authenticate(self, request): """ Returns a two-tuple of `User` and token if a valid signature has been supplied using JWT-based authentication. Otherwise returns `None`. """ jwt_value = self.get_jwt_value(request) if jwt_value is None: return None jwt_str = str(jwt_value, 'UTF-8')[-10:] username = rh.get_token(jwt_str) if isinstance(username, str): rh.set_token(jwt_str, username) else: msg = _('Signature has expired.') raise exceptions.AuthenticationFailed(msg) # try: # payload = jwt_decode_handler(jwt_value) # except jwt.ExpiredSignature: # msg = _('Signature has expired.') # raise exceptions.AuthenticationFailed(msg) # except jwt.DecodeError: # msg = _('Error decoding signature.') # raise exceptions.AuthenticationFailed(msg) # except jwt.InvalidTokenError: # raise exceptions.AuthenticationFailed() user = self.authenticate_credentials(username) return (user, jwt_value)