def post(self, request, format=None): # check token refresh valid serializer = TokenRefreshSerializer(data=request.data) try: serializer.is_valid(raise_exception=True) except TokenError as e: raise InvalidToken(e.args[0]) response = Response() """ send http only cookies """ data = serializer._validated_data payload = {"access": data["access"], "refresh": data["refresh"]} tomorrow = datetime.now() + datetime.timedelta(days=1) expires = datetime.strftime(tomorrow, "%a, %d-%b-%Y %H:%M:%S GMT") response.set_cookie( key=settings.SIMPLE_JWT["AUTH_COOKIE"], value=data["access"], expires=expires, secure=settings.SIMPLE_JWT["AUTH_COOKIE_SECURE"], httponly=settings.SIMPLE_JWT["AUTH_COOKIE_HTTP_ONLY"], samesite=settings.SIMPLE_JWT["AUTH_COOKIE_SAMESITE"], ) response.data = {"Messege": "refresh Success", "data": payload} response.status_code = status.HTTP_200_OK return response
def refresh_token(request: Request) -> JsonResponse: """ Refreshes a user's token info. They should contain: - Access token - Refresh token - Spotify access token (optional) - Spotify refresh token (if spotify access token is provided). """ if settings.DEBUG: print(json.loads(request.body)) # Refresh user's token body = json.loads(request.body) spotify_params = {} spotify_params['access_token'] = body.pop('spotify_access_token', '') spotify_params['refresh_token'] = body.pop('spotify_refresh_token', '') try: ser = TokenRefreshSerializer(data=body) ser.is_valid() except TokenError: # Request is not valid. return JsonResponse({'error': 'Refresh Token is Invalid'}, status=status.HTTP_401_UNAUTHORIZED) if settings.DEBUG: print('validated', ser.validated_data) # If this user's credentials doesn't contain spotify credentials, just return it. if not spotify_params['access_token'] or not spotify_params[ 'refresh_token']: return JsonResponse(ser.validated_data) # Check and refresh user's spotify token try: response = refresh_token_info(spotify_params) print(response) return JsonResponse({ 'access_token': ser.validated_data['access'], 'refresh': body['refresh'], 'spotify_access_token': response['access_token'], 'spotify_refresh_token': response['refresh_token'] }) except pyrequests.RequestException: pass try: refresh_response = refresh_token_info(spotify_params) spotify_params['access_token'] = refresh_response['access_token'] spotify_params['refresh_token'] = refresh_response['refresh_token'] return JsonResponse({ 'access_token': ser.validated_data['access'], 'refresh': body['refresh'], 'spotify_access_token': spotify_params['access_token'], 'spotify_refresh_token': spotify_params['refresh_token'] }) except pyrequests.RequestException: return JsonResponse({'error': 'Refresh Token is Invalid'}, status=status.HTTP_401_UNAUTHORIZED)
def get_access_token_from_refresh_token(self,request): serializer = TokenRefreshSerializer(data = request.data) try: serializer.is_valid(raise_exception=True) except TokenError as e: raise InvalidToken(e.args[0]) return Response(serializer.validated_data,status = status.HTTP_200_OK)
def token_refresh_handler(refresh): """ Takes a refresh type JSON web token and returns an access type JSON web token if the refresh token is valid. """ ser = TokenRefreshSerializer(data={'refresh': refresh}) ser.is_valid(raise_exception=True) res = dict(refresh=ser.validated_data.get('refresh'), access=ser.validated_data.get('access')) return res
def refresh(self, request): serializer = TokenRefreshSerializer(data=request.data, context={'request': request}) try: serializer.is_valid(raise_exception=True) except TokenError as e: raise InvalidToken(e.args[0]) return Response(serializer.validated_data, status=status.HTTP_200_OK)
def test_it_should_raise_token_error_if_token_has_wrong_type(self): token = RefreshToken() token[api_settings.TOKEN_TYPE_CLAIM] = 'wrong_type' s = TokenRefreshSerializer(data={'refresh': str(token)}) with self.assertRaises(TokenError) as e: s.is_valid() self.assertIn("wrong type", e.exception.args[0])
def decorated_function(self, request, *args, **kwargs): self.headers = {'Authorization': request.META['HTTP_AUTHORIZATION']} if 'headers' in request.META and 'refresh' in request.META['headers']: raw_token = request.META['headers']['refresh'].split(" ")[-1] token_serializer = TokenRefreshSerializer(data={'refresh': raw_token}) token_serializer.is_valid(raise_exception=True) access = token_serializer.validated_data['access'] refresh = token_serializer.validated_data['refresh'] self.headers['Refresh'] = settings.JWT_HEADER_TYPE + refresh self.headers['Authorization'] = settings.JWT_HEADER_TYPE + access return func(self, request, *args, **kwargs)
def test_it_should_not_validate_if_token_invalid(self): token = RefreshToken() del token['exp'] s = TokenRefreshSerializer(data={'refresh': str(token)}) self.assertFalse(s.is_valid()) self.assertIn('non_field_errors', s.errors) self.assertIn("has no 'exp' claim", s.errors['non_field_errors'][0]) token.set_exp(lifetime=-timedelta(days=1)) s = TokenRefreshSerializer(data={'refresh': str(token)}) self.assertFalse(s.is_valid()) self.assertIn('non_field_errors', s.errors) self.assertIn('invalid or expired', s.errors['non_field_errors'][0])
def post(self, request): """ API -> POST /api/v1/user/refresh/token/ """ serializer = TokenRefreshSerializer(data=request.data) try: if serializer.is_valid(): token_service = TokenService() user_id = token_service.get_user_from_token( request.data['refresh']) if user_id is None: return Response({'error': 'Invalid Claims'}, status=status.HTTP_401_UNAUTHORIZED) try: User.objects.get(id=user_id, is_deleted=False) except ObjectDoesNotExist: return Response({'error': 'User does not exist'}, status=status.HTTP_401_UNAUTHORIZED) tokens = serializer.validated_data return Response( { 'access_token': tokens['access'], 'refresh_token': tokens['refresh'] }, status=status.HTTP_200_OK) except Exception as error: return Response({'error': str(error)}, status=status.HTTP_403_FORBIDDEN)
def test_it_should_return_refresh_token_if_tokens_should_be_rotated(self): refresh = RefreshToken() refresh['test_claim'] = 'arst' old_jti = refresh['jti'] old_exp = refresh['exp'] # Serializer validates ser = TokenRefreshSerializer(data={'refresh': str(refresh)}) now = aware_utcnow() - api_settings.ACCESS_TOKEN_LIFETIME / 2 with override_api_settings(ROTATE_REFRESH_TOKENS=True, BLACKLIST_AFTER_ROTATION=False): with patch('rest_framework_simplejwt.tokens.aware_utcnow') as fake_aware_utcnow: fake_aware_utcnow.return_value = now self.assertTrue(ser.is_valid()) access = AccessToken(ser.validated_data['access']) new_refresh = RefreshToken(ser.validated_data['refresh']) self.assertEqual(refresh['test_claim'], access['test_claim']) self.assertEqual(refresh['test_claim'], new_refresh['test_claim']) self.assertNotEqual(old_jti, new_refresh['jti']) self.assertNotEqual(old_exp, new_refresh['exp']) self.assertEqual(access['exp'], datetime_to_epoch(now + api_settings.ACCESS_TOKEN_LIFETIME)) self.assertEqual(new_refresh['exp'], datetime_to_epoch(now + api_settings.REFRESH_TOKEN_LIFETIME))
def test_it_should_not_validate_if_token_has_wrong_type(self): token = RefreshToken() token[api_settings.TOKEN_TYPE_CLAIM] = 'wrong_type' s = TokenRefreshSerializer(data={'refresh': str(token)}) self.assertFalse(s.is_valid()) self.assertIn('non_field_errors', s.errors) self.assertIn("wrong type", s.errors['non_field_errors'][0])
def process_template_response(self, request, response): try: access_token = request.COOKIES[settings.SIMPLE_JWT["AUTH_COOKIE"]] refesh_token = request.COOKIES[ settings.SIMPLE_JWT["AUTH_COOKIE_REF"]] # check if the access token is valid # if not, send new access token to cookie if access_token: key = settings.SECRET_KEY else: return response try: decoded_access_token = jwt.decode(access_token, key, algorithms=["HS256"]) return response except jwt.ExpiredSignatureError: serializer = TokenRefreshSerializer( data={"refresh": refesh_token}) try: serializer.is_valid(raise_exception=True) except TokenError as e: # Code that is executed in each request after the view is return response """ send http only cookies """ data = serializer._validated_data response.set_cookie( key=settings.SIMPLE_JWT["AUTH_COOKIE"], value=data["access"], expires=settings.SIMPLE_JWT["ACCESS_TOKEN_LIFETIME"], secure=settings.SIMPLE_JWT["AUTH_COOKIE_SECURE"], httponly=settings.SIMPLE_JWT["AUTH_COOKIE_HTTP_ONLY"], samesite=settings.SIMPLE_JWT["AUTH_COOKIE_SAMESITE"], ) response.set_cookie( key=settings.SIMPLE_JWT["AUTH_COOKIE_REF"], value=data["refresh"], expires=settings.SIMPLE_JWT["REFRESH_TOKEN_LIFETIME"], secure=settings.SIMPLE_JWT["AUTH_COOKIE_SECURE"], httponly=settings.SIMPLE_JWT["AUTH_COOKIE_HTTP_ONLY"], samesite=settings.SIMPLE_JWT["AUTH_COOKIE_SAMESITE"], ) return response except KeyError: return response
def post(self, request, *args, **kwargs): data = { 'refresh': cookies.get_cookie(request=request, key='refresh_token') } serializer = TokenRefreshSerializer(data=data) try: serializer.is_valid(raise_exception=True) except Exception: return Response(data={'message': 'refresh token not found'}, status=status.HTTP_403_FORBIDDEN) access_token = serializer.validated_data['access'] response = Response(data={'message': 'refreshed token successfully'}, status=status.HTTP_200_OK) response = auths.helpers.set_cookies_with_access_token( response=response, access_token=access_token) return response
def refresh_token(self, request): serializer = TokenRefreshSerializer(data=request.data) try: if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.validated_data, status=status.HTTP_200_OK) except TokenError as ex: logger.exception(ex) return Response({"refresh": ["Token inválido"]}, status=status.HTTP_400_BAD_REQUEST)
def test_it_should_raise_token_error_if_token_invalid(self): token = RefreshToken() del token['exp'] s = TokenRefreshSerializer(data={'refresh': str(token)}) with self.assertRaises(TokenError) as e: s.is_valid() self.assertIn("has no 'exp' claim", e.exception.args[0]) token.set_exp(lifetime=-timedelta(days=1)) s = TokenRefreshSerializer(data={'refresh': str(token)}) with self.assertRaises(TokenError) as e: s.is_valid() self.assertIn('invalid or expired', e.exception.args[0])
def test_it_should_return_access_token_if_everything_ok(self): refresh = RefreshToken() refresh['test_claim'] = 'arst' # Serializer validates s = TokenRefreshSerializer(data={'refresh': str(refresh)}) now = aware_utcnow() - api_settings.ACCESS_TOKEN_LIFETIME / 2 with patch('rest_framework_simplejwt.tokens.aware_utcnow') as fake_aware_utcnow: fake_aware_utcnow.return_value = now self.assertTrue(s.is_valid()) access = AccessToken(s.validated_data['access']) self.assertEqual(refresh['test_claim'], access['test_claim']) self.assertEqual(access['exp'], datetime_to_epoch(now + api_settings.ACCESS_TOKEN_LIFETIME))
def test_it_should_blacklist_refresh_token_if_tokens_should_be_rotated_and_blacklisted( self, ): self.assertEqual(OutstandingToken.objects.count(), 0) self.assertEqual(BlacklistedToken.objects.count(), 0) refresh = RefreshToken() refresh["test_claim"] = "arst" old_jti = refresh["jti"] old_exp = refresh["exp"] # Serializer validates ser = TokenRefreshSerializer(data={"refresh": str(refresh)}) now = aware_utcnow() - api_settings.ACCESS_TOKEN_LIFETIME / 2 with override_api_settings(ROTATE_REFRESH_TOKENS=True, BLACKLIST_AFTER_ROTATION=True): with patch("rest_framework_simplejwt.tokens.aware_utcnow" ) as fake_aware_utcnow: fake_aware_utcnow.return_value = now self.assertTrue(ser.is_valid()) access = AccessToken(ser.validated_data["access"]) new_refresh = RefreshToken(ser.validated_data["refresh"]) self.assertEqual(refresh["test_claim"], access["test_claim"]) self.assertEqual(refresh["test_claim"], new_refresh["test_claim"]) self.assertNotEqual(old_jti, new_refresh["jti"]) self.assertNotEqual(old_exp, new_refresh["exp"]) self.assertEqual( access["exp"], datetime_to_epoch(now + api_settings.ACCESS_TOKEN_LIFETIME)) self.assertEqual( new_refresh["exp"], datetime_to_epoch(now + api_settings.REFRESH_TOKEN_LIFETIME), ) self.assertEqual(OutstandingToken.objects.count(), 1) self.assertEqual(BlacklistedToken.objects.count(), 1) # Assert old refresh token is blacklisted self.assertEqual(BlacklistedToken.objects.first().token.jti, old_jti)
def resolve_refresh_token(_, info, token): data = {"refresh": token} serializer = TokenRefreshSerializer(data=data) if serializer.is_valid(): return serializer.validated_data