예제 #1
0
    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()
예제 #2
0
    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()
예제 #5
0
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)
예제 #6
0
    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
예제 #7
0
    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)
예제 #9
0
    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
예제 #11
0
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
예제 #12
0
 def test_str(self):
     refresh_token = RefreshToken(token="test_token")
     self.assertEqual("%s" % refresh_token, refresh_token.token)
예제 #13
0
    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')
예제 #14
0
    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