def save_bearer_token(self, token, request, *args, **kwargs): """ Check if an access_token exists for the couple user/application that is valid and authorized for the same scopes and ensures that no refresh token was used. If all the conditions are true the same access_token is issued. Otherwise a new one is created with the default strategy. """ # this queryset identifies all the valid access tokens # for the couple user/application. previous_valid_tokens = AccessToken.objects.filter( user=request.user, application=request.client, ).filter(expires__gt=timezone.now()).order_by('-expires') # if a refresh token was not used and a valid token exists we # can replace the new generated token with the old one. if not request.refresh_token and previous_valid_tokens.exists(): for access_token in previous_valid_tokens: # the previous access_token must allow access to the same scope # or bigger if access_token.allow_scopes(token['scope'].split()): token['access_token'] = access_token.token expires_in = access_token.expires - timezone.now() token['expires_in'] = expires_in.total_seconds() if hasattr(access_token, 'refresh_token'): token[ 'refresh_token'] = access_token.refresh_token.token # break the loop and exist because we found to old token return # default behaviour when no old token is found if request.refresh_token: # remove used refresh token try: RefreshToken.objects.get(token=request.refresh_token).revoke() except RefreshToken.DoesNotExist: assert ( ) # TODO though being here would be very strange, at least log the error expires = timezone.now() + timedelta(seconds=token['expires_in']) if request.grant_type == 'client_credentials': request.user = None access_token = AccessToken(user=request.user, scope=token['scope'], expires=expires, token=token['access_token'], application=request.client) access_token.save() if 'refresh_token' in token: refresh_token = RefreshToken(user=request.user, token=token['refresh_token'], application=request.client, access_token=access_token) refresh_token.save()
def save_bearer_token(self, token, request, *args, **kwargs): """ It's messy. It is 90% code from parent function. I didn't find a way to reduce it. I tried and I failed :'( Sin Count += 1 Save access and refresh token, If refresh token is issued, remove old refresh tokens as in rfc:`6` """ if request.refresh_token: # remove used refresh token # Copied as is from parent. I don't know why they're even caring to delete this! - Dheerendra try: RefreshToken.objects.get(token=request.refresh_token).revoke() except RefreshToken.DoesNotExist: assert ( ) # TODO though being here would be very strange, at least log the error expires = timezone.now() + timedelta( seconds=oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS) token['expires_in'] = oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS if request.response_type == 'token': expires = timezone.now() + timedelta( seconds=settings.IMPLICIT_ACCESS_TOKEN_EXPIRES_SECONDS) token[ 'expires_in'] = settings.IMPLICIT_ACCESS_TOKEN_EXPIRES_SECONDS if request.grant_type == 'client_credentials': request.user = None access_token = AccessToken(user=request.user, scope=token['scope'], expires=expires, token=token['access_token'], application=request.client) access_token.save() if 'refresh_token' in token: refresh_token = RefreshToken( user=request.user, token=token['refresh_token'], application=request.client, ) if request.grant_type == 'authorization_code': refresh_tokens = RefreshToken.objects.all().filter( user=request.user, application=request.client).order_by('-id') if len(refresh_tokens) > 0: refresh_token = refresh_tokens[0] # Delete the old access_token refresh_token.access_token.delete() if len(refresh_tokens) > 1: # Enforce 1 token pair. Delete all old refresh_tokens RefreshToken.objects.exclude( pk=refresh_token.id).delete() refresh_token.access_token = access_token refresh_token.save() token['refresh_token'] = refresh_token.token token['groups'] = request.user.groups
def save_bearer_token(self, token, request, *args, **kwargs): if request.refresh_token: try: RefreshToken.objects.get(token=request.refresh_token).revoke() except RefreshToken.DoesNotExist: assert () # TODO though being here would be very strange, at least log the error expires = timezone.now() + timedelta(seconds=oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS) if request.grant_type == 'client_credentials': request.user = None access_token = AccessToken( user=request.user, scope=token['scope'], expires=expires, token=token['access_token'], application=request.client) access_token.save() if 'refresh_token' in token: refresh_token = RefreshToken( user=request.user, token=token['refresh_token'], application=request.client, access_token=access_token ) refresh_token.save() if DEVICE_TOKEN_HEADER in request.headers: self.save_device(request=request, access_token=access_token, refresh_token=refresh_token) token['expires_in'] = oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS
def save_bearer_token(self, token, request, *args, **kwargs): """ Check if an access_token exists for the couple user/application that is valid and authorized for the same scopes and esures that no refresh token was used. If all the conditions are true the same access_token is issued. Otherwise a new one is created with the default strategy. """ # this queryset identifies all the valid access tokens # for the couple user/application. previous_valid_tokens = AccessToken.objects.filter( user=request.user, application=request.client, ).filter(expires__gt=timezone.now()).order_by('-expires') # if a refresh token was not used and a valid token exists we # can replace the new generated token with the old one. if not request.refresh_token and previous_valid_tokens.exists(): for access_token in previous_valid_tokens: # the previous access_token must allow access to the same scope # or bigger if access_token.allow_scopes(token['scope'].split()): token['access_token'] = access_token.token expires_in = access_token.expires - timezone.now() token['expires_in'] = expires_in.total_seconds() if hasattr(access_token, 'refresh_token'): token['refresh_token'] = access_token.refresh_token.token # break the loop and exist because we found to old token return # default behaviour when no old token is found if request.refresh_token: # remove used refresh token try: RefreshToken.objects.get(token=request.refresh_token).revoke() except RefreshToken.DoesNotExist: assert() # TODO though being here would be very strange, at least log the error expires = timezone.now() + timedelta(seconds=token['expires_in']) if request.grant_type == 'client_credentials': request.user = None access_token = AccessToken( user=request.user, scope=token['scope'], expires=expires, token=token['access_token'], application=request.client) access_token.save() if 'refresh_token' in token: refresh_token = RefreshToken( user=request.user, token=token['refresh_token'], application=request.client, access_token=access_token ) refresh_token.save()
def signup_client(request): serializer = SignupClientSerializer(data=request.data, context={'request': request}) serializer.is_valid() # print("serializer error: ", oauth2_settings) if serializer.errors: return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST) else: serializer.save() application = Application.objects.get(client_id=serializer.initial_data["client_id"]) expires = timezone.now() + timedelta(seconds=oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS) activated_user = User.objects.get(email=serializer.data["email"]) access_token = AccessToken( user=activated_user, scope='', expires=expires, token=common.generate_token(), application=application ) access_token.save() refresh_token = RefreshToken( user=activated_user, token=common.generate_token(), application=application, access_token=access_token ) refresh_token.save() return Response({"expires": expires, "access_token": access_token.token, "refresh_token": refresh_token.token}, status=200)
def save_bearer_token(self, token, request, *args, **kwargs): """ It's messy. It is 90% code from parent function. I didn't find a way to reduce it. I tried and I failed :'( Sin Count += 1 Save access and refresh token, If refresh token is issued, remove old refresh tokens as in rfc:`6` """ if request.refresh_token: # remove used refresh token # Copied as is from parent. I don't know why they're even caring to delete this! - Dheerendra try: RefreshToken.objects.get(token=request.refresh_token).revoke() except RefreshToken.DoesNotExist: assert () # TODO though being here would be very strange, at least log the error expires = timezone.now() + timedelta(seconds=oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS) token['expires_in'] = oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS if request.response_type == 'token': expires = timezone.now() + timedelta(seconds=settings.IMPLICIT_ACCESS_TOKEN_EXPIRES_SECONDS) token['expires_in'] = settings.IMPLICIT_ACCESS_TOKEN_EXPIRES_SECONDS if request.grant_type == 'client_credentials': request.user = None access_token = AccessToken( user=request.user, scope=token['scope'], expires=expires, token=token['access_token'], application=request.client) access_token.save() if 'refresh_token' in token: refresh_token = RefreshToken( user=request.user, token=token['refresh_token'], application=request.client, ) if request.grant_type == 'authorization_code': refresh_tokens = RefreshToken.objects.all().filter(user=request.user, application=request.client).order_by('-id') if len(refresh_tokens) > 0: refresh_token = refresh_tokens[0] # Delete the old access_token refresh_token.access_token.delete() if len(refresh_tokens) > 1: # Enforce 1 token pair. Delete all old refresh_tokens RefreshToken.objects.exclude(pk=refresh_token.id).delete() refresh_token.access_token = access_token refresh_token.save() token['refresh_token'] = refresh_token.token
def create_refresh_token( self, access_token: AccessToken, ) -> RefreshToken: """Create a refresh token.""" refresh_token = RefreshToken( user=access_token.user, token=common.generate_token(), application=self.jwt_app, access_token=access_token, ) refresh_token.save() return refresh_token
def create_refresh_token(self, user_id, application_id, access_token_id): from oauth2_provider.models import RefreshToken refresh_token = self._generate_access_token() refresh_token_object = RefreshToken(user_id=user_id, token=refresh_token, application_id=application_id, access_token_id=access_token_id) refresh_token_object.save() from common.dtos import RefreshTokenDTO return RefreshTokenDTO(token=refresh_token_object.token, access_token=refresh_token_object.access_token, user_id=refresh_token_object.user_id, revoked=refresh_token_object.revoked)
def create_oauth2_token(self, user, client_id, old_token=None): oauth_app = self.get_oauth2_app_by_client_id(client_id) remove_old_token = self.get_remove_old_token() if remove_old_token is True: #this field to remove all token associate with this user and the application AccessToken.objects.filter(user=user, application=oauth_app).delete() if old_token: AccessToken.objects.filter(user=user, token=old_token).delete() expire_seconds = self.get_expire_seconds() expires = timezone.now() + timedelta(seconds=expire_seconds) scopes = oauth2_settings.DEFAULT_SCOPES access_token = AccessToken(user=user, scope=scopes, expires=expires, token=common.generate_token(), application=oauth_app) access_token.save() refresh_token = RefreshToken(user=user, token=common.generate_token(), application=oauth_app, access_token=access_token) refresh_token.save() results = { "access_token": access_token.token, "refresh_token": refresh_token.token, "token_type": "Bearer", "expires_in": expire_seconds, "scope": scopes, "user_id": user.id, } return results
def post(self, request, format=None): if request.method == "POST": username = request.data.get("username") password = request.data.get("password") if username is None or password is None: return Response( {'error': 'Please provide both username and password'}, status=400) user = authenticate(username=username, password=password) if not user: return Response({'error': 'Invalid Credentials'}, status=404) expires = timezone.now() + timedelta(seconds=3600000) application = Application.objects.get( client_id=mainSettings.OAUTH_CLIENTID) access_token = AccessToken(user=user, scope='', expires=expires, token=common.generate_token(), application=application) access_token.save() refresh_token = RefreshToken(user=user, token=common.generate_token(), application=application, access_token=access_token) refresh_token.save() return Response( { 'token': access_token.token, 'refresh_token': refresh_token.token, "token_type": "Bearer" }, status=HTTPStatus.HTTP_200_OK) else: status_code = HTTPStatus.METHOD_NOT_ALLOWED response = JsonResponse({'success': 'false'}, status=status_code) return response
def create_token(user: User) -> Dict: # erase all existing access tokens that belong to the user tokens = AccessToken.objects.filter(user=user) tokens.delete() application = Application.objects.get(client_id='bmu_user') expires = (timezone.now() + timezone.timedelta( seconds=settings.OAUTH2_PROVIDER['ACCESS_TOKEN_EXPIRE_SECONDS'])) scope = 'read write' # Create access token access_token_string = common.generate_token() bmu_access_token = AccessToken(user=user, token=access_token_string, application=application, expires=expires, scope=scope) bmu_access_token.save() # Create refresh token refresh_token_string = common.generate_token() bmu_refresh_token = RefreshToken(user=user, token=refresh_token_string, application=application, access_token=bmu_access_token) bmu_refresh_token.save() data = { 'expires_in': settings.OAUTH2_PROVIDER['ACCESS_TOKEN_EXPIRE_SECONDS'], 'refresh_token': refresh_token_string, 'access_token': access_token_string, 'token_type': 'Bearer', 'scope': scope } return data
def test_str(self): refresh_token = RefreshToken(token="test_token") self.assertEqual("%s" % refresh_token, refresh_token.token)
def save_bearer_token(self, token, request, *args, **kwargs): if "scope" not in token: raise FatalClientError("Failed to renew access token: missing scope") expires = timezone.now() + timedelta(seconds=OAUTH2_PROVIDER.get('ACCESS_TOKEN_EXPIRE_SECONDS')) if request.grant_type == "client_credentials": request.user = None # This comes from OAuthLib: # https://github.com/idan/oauthlib/blob/1.0.3/oauthlib/oauth2/rfc6749/tokens.py#L267 # Its value is either a new random code; or if we are reusing # refresh tokens, then it is the same value that the request passed in # (stored in `request.refresh_token`) refresh_token_code = token.get("refresh_token", None) if refresh_token_code: # an instance of `RefreshToken` that matches the old refresh code. # Set on the request in `validate_refresh_token` refresh_token_instance = getattr(request, "refresh_token_instance", None) # If we are to reuse tokens, and we can: do so if not self.rotate_refresh_token(request) and \ isinstance(refresh_token_instance, RefreshToken) and \ refresh_token_instance.access_token: access_token = AccessToken.objects.select_for_update().get( pk=refresh_token_instance.access_token.pk ) access_token.user = request.user access_token.scope = token["scope"] access_token.expires = expires access_token.token = token["access_token"] access_token.application = request.client access_token.save() # else create fresh with access & refresh tokens else: # revoke existing tokens if possible if isinstance(refresh_token_instance, RefreshToken): try: refresh_token_instance.revoke() except (AccessToken.DoesNotExist, RefreshToken.DoesNotExist): pass else: setattr(request, "refresh_token_instance", None) access_token = self._create_access_token(expires, request, token) refresh_token = RefreshToken( user=request.user, token=refresh_token_code, application=request.client, access_token=access_token ) refresh_token.save() # No refresh token should be created, just access token else: self._create_access_token(expires, request, token) # TODO: check out a more reliable way to communicate expire time to oauthlib token["expires_in"] = OAUTH2_PROVIDER.get('ACCESS_TOKEN_EXPIRE_SECONDS')
def save_bearer_token(self, token, request, *args, **kwargs): """ Save access and refresh token, If refresh token is issued, remove or reuse old refresh token as in rfc:`6` @see: https://tools.ietf.org/html/draft-ietf-oauth-v2-31#page-43 """ if "scope" not in token: raise FatalClientError( "Failed to renew access token: missing scope") expires = timezone.now() + timedelta( seconds=oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS) if request.grant_type == "client_credentials": request.user = None # This comes from OAuthLib: # https://github.com/idan/oauthlib/blob/1.0.3/oauthlib/oauth2/rfc6749/tokens.py#L267 # Its value is either a new random code; or if we are reusing # refresh tokens, then it is the same value that the request passed in # (stored in `request.refresh_token`) refresh_token_code = token.get("refresh_token", None) if refresh_token_code: # an instance of `RefreshToken` that matches the old refresh code. # Set on the request in `validate_refresh_token` refresh_token_instance = getattr(request, "refresh_token_instance", None) # If we are to reuse tokens, and we can: do so if not self.rotate_refresh_token(request) and \ isinstance(refresh_token_instance, RefreshToken) and \ refresh_token_instance.access_token: access_token = AccessToken.objects.select_for_update().get( pk=refresh_token_instance.access_token.pk) auth_cache = caches['auth'] auth_cache.delete(access_token.token) access_token.user = request.user access_token.scope = ' '.join(request.user.scopes) access_token.expires = expires access_token.token = token["access_token"] access_token.application = request.client access_token.save() cached_auth = { 'uid': access_token.user.id, 'scopes': access_token.user.scopes, 'token': access_token.token, 'reused': 'true', } auth_cache.set(access_token.token, cached_auth, oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS) # else create fresh with access & refresh tokens else: # revoke existing tokens if possible to allow reuse of grant if isinstance(refresh_token_instance, RefreshToken): try: auth_cache = caches['auth'] refresh_token_key = 'auth:access_token:{access_token}:refresh_token'.format( access_token=refresh_token_instance.access_token. token) access_token_key = 'auth:access_token:{access_token}'.format( access_token=refresh_token_instance.access_token. token) auth_cache.delete_many( [access_token_key, refresh_token_key]) refresh_token_instance.revoke() except (AccessToken.DoesNotExist, RefreshToken.DoesNotExist): pass else: setattr(request, "refresh_token_instance", None) # If the refresh token has already been used to create an # access token (ie it's within the grace period), return that # access token # TODO rewrite to celery access_token = self._create_access_token( expires, request, token, ) refresh_token = RefreshToken(user=request.user, token=refresh_token_code, application=request.client, access_token=access_token) refresh_token.save() auth_cache = caches['auth'] key = 'auth:access_token:{access_token}:refresh_token'.format( access_token=access_token.token) auth_cache.set(key, access_token.token, oauth2_settings.REFRESH_TOKEN_EXPIRE_SECONDS) # No refresh token should be created, just access token else: self._create_access_token(expires, request, token) # TODO: check out a more reliable way to communicate expire time to oauthlib token["expires_in"] = oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS