def token(request): class GrantError(Exception): def __init__(self, msg): super().__init__(msg) self.msg = msg # Authenticate Client by Basic Access Authentication try: auth = request.META['HTTP_AUTHORIZATION'] (auth_scheme, auth_param) = auth.split(' ', 1) assert auth_scheme.lower() == 'basic' auth_param = b64decode(auth_param.encode('ascii')).decode('ascii') (client_id, client_secret) = auth_param.split(':', 1) client_id = UUID(hex=client_id) client_secret = UUID(hex=client_secret) client = Client.objects.get(id=client_id) assert client.secret == client_secret except (KeyError, ValueError, AssertionError, Client.DoesNotExist): response = JsonResponse({'error': 'invalid_client'}, status=401) response['WWW-Authenticate'] = 'Basic realm="Django OAuth2 Client"' return response # Grant an Access Token by Different Grant Type try: grant_type = request.POST['grant_type'] if grant_type == 'authorization_code': code = request.POST['code'] redirect_uri = request.POST['redirect_uri'] if client.get_grant_type_display() != 'authorization_code': raise GrantError('unauthorized_client') try: code = UUID(hex=code) code = Code.objects.get(id=code) assert not code.is_expired() assert code.client == client assert code.redirect_uri == redirect_uri except (ValueError, Code.DoesNotExist, AssertionError): raise GrantError('invalid_grant') access_token = code.get_access_token() elif grant_type == 'password': username = request.POST['username'] password = request.POST['password'] if client.get_grant_type_display() != 'password': raise GrantError('unauthorized_client') user = authenticate(username=username, password=password) if user is None or not user.is_active: raise GrantError('invalid_grant') access_token = AccessToken(client=client, user=user) access_token.save() elif grant_type == 'client_credentials': if client.get_grant_type_display() != 'client_credentials': raise GrantError('unauthorized_client') access_token = AccessToken(client=client, user=None) access_token.save() elif grant_type == 'refresh_token': refresh_token = request.POST['refresh_token'] if client.get_grant_type_display() != 'authorization_code': raise GrantError('unauthorized_client') try: refresh_token = UUID(hex=refresh_token) access_token = AccessToken.objects.get( refresh_id=refresh_token) assert access_token.client == client assert not access_token.is_refresh_expired() except AccessToken.DoesNotExist: raise GrantError('invalid_grant') access_token = access_token.refresh() else: return JsonResponse({'error': 'unsupported_grant_type'}, status=400) except KeyError: return JsonResponse({'error': 'invalid_request'}, status=400) except GrantError as e: return JsonResponse({'error': e.msg}, status=400) return JsonResponse({ 'access_token': str(access_token), 'token_type': 'bearer', 'expires_in': access_token.client.access_token_expires_in, 'refresh_token': access_token.get_refresh_token(), })