示例#1
0
    def save_bearer_token(self, token, request, *args, **kwargs):
        if 'scope' not in token:
            raise FatalClientError(
                'Failed to renew access token: missing scope')

        if request.grant_type == 'client_credentials':
            request.user = None

        # TODO: check out a more reliable way to communicate expire time to oauthlib
        token['expires_in'] = oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS

        refresh_token_code = token.get('refresh_token', None)
        if not refresh_token_code:
            return

        if self.rotate_refresh_token(request):
            refresh_token = RefreshToken(
                user=request.user,
                token=refresh_token_code,
                application=request.client,
                expires=datetime.now() + timedelta(
                    seconds=oauth2_settings.REFRESH_TOKEN_EXPIRE_SECONDS),
                scope=token['scope'],
            )
            refresh_token.save()

        token[
            'refresh_token_expires_in'] = oauth2_settings.REFRESH_TOKEN_EXPIRE_SECONDS
示例#2
0
 def validate_authorization_request(self, request):
     require_approval = request.GET.get(
         "approval_prompt", oauth2_settings.REQUEST_APPROVAL_PROMPT)
     if require_approval != 'force' and request.GET.get(
             'scope') != 'profile':
         raise FatalClientError(
             'Combnination of require_approval and scope values not allowed.'
         )
     return super().validate_authorization_request(request)
示例#3
0
 def _create_access_token(self, expires, request, token, source_refresh_token=None):
     if not getattr(request, 'organizers', None) and not getattr(source_refresh_token, 'access_token', None) and token["scope"] != 'profile':
         raise FatalClientError('No organizers selected.')
     if token['scope'] != 'profile':
         if hasattr(request, 'organizers'):
             orgs = list(request.organizers.all())
         else:
             orgs = list(source_refresh_token.access_token.organizers.all())
     access_token = super()._create_access_token(expires, request, token, source_refresh_token=None)
     if token['scope'] != 'profile':
         access_token.organizers.add(*orgs)
     return access_token
示例#4
0
    def save_authorization_code(self, client_id, code, request, *args, **kwargs):
        if not getattr(request, 'organizers', None) and request.scopes != ['profile']:
            raise FatalClientError('No organizers selected.')

        expires = timezone.now() + timedelta(
            seconds=oauth2_settings.AUTHORIZATION_CODE_EXPIRE_SECONDS)
        g = Grant(application=request.client, user=request.user, code=code["code"],
                  expires=expires, redirect_uri=request.redirect_uri,
                  scope=" ".join(request.scopes))
        g.save()
        if request.scopes != ['profile']:
            g.organizers.add(*request.organizers.all())
示例#5
0
def verify_access_token(key):
    try:
        token = AccessToken.objects.get(token=key)

        if not token.is_valid():
            raise OAuthToolkitError('AccessToken is not valid.')
        if token.is_expired():
            raise OAuthToolkitError('AccessToken has expired.')
    except AccessToken.DoesNotExist:
        raise FatalClientError("AccessToken not found at all.")

    return token
示例#6
0
def verify_access_token(request, key):
    try:
        token = None
        if request:
            token = get_token_object_from_session(request.session)
        if not token or token.key != key:
            token = AccessToken.objects.get(token=key)
        if not token.is_valid():
            raise OAuthToolkitError('AccessToken is not valid.')
        if token.is_expired():
            raise OAuthToolkitError('AccessToken has expired.')
    except AccessToken.DoesNotExist:
        raise FatalClientError("AccessToken not found at all.")
    except BaseException:
        return None
    return token
示例#7
0
    def validate_authorization_request(self, request):
        """
        A wrapper method that calls validate_authorization_request on `server_class` instance.
        :param request: The current django.http.HttpRequest object
        """
        try:
            uri, http_method, body, headers = self._extract_params(request)
            headers["tatl.scopes"] = request.user.get_all_permissions(
            ) if request.user else []

            scopes, credentials = self.server.validate_authorization_request(
                uri, http_method=http_method, body=body, headers=headers)

            return scopes, credentials
        except oauth2.FatalClientError as error:
            raise FatalClientError(error=error)
        except oauth2.OAuth2Error as error:
            raise OAuthToolkitError(error=error)
示例#8
0
 def test_error_response_without_redirect(self):
     """Test that errors are rendered without a 'url' context variable."""
     base_error = FakeOAuthLibError(status_code=405)
     error = FatalClientError(error=base_error)
     response = self.view.error_response(error)
     self.assertNotIn('url', response.context_data)
示例#9
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