Beispiel #1
0
 def assign_token_to_session(self):
     token = self.token
     if token and "oauth_token" in token and "oauth_token_secret" in token:
         # This really, really violates the Law of Demeter, but
         # I don't see a better way to set these parameters. :(
         self.session.auth.client.resource_owner_key = to_unicode(token["oauth_token"])
         self.session.auth.client.resource_owner_secret = to_unicode(token["oauth_token_secret"])
Beispiel #2
0
    def authenticate_client(self, request, *args, **kwargs):
        auth = request.headers.get('Authorization', None)
        log.debug('Authenticate client %r', auth)
        if auth:
            try:
                _, s = auth.split(' ')
                client_id, client_secret = decode_base64(s).split(':')
                client_id = to_unicode(client_id, 'utf-8')
                client_secret = to_unicode(client_secret, 'utf-8')
            except Exception as e:
                log.debug('Authenticate client failed with exception: %r', e)
                return False
        else:
            client_id = request.client_id
            client_secret = request.client_secret

        client = self._clientgetter(client_id)
        if not client:
            return False

        if client.client_secret != client_secret:
            log.debug('Authenticate client failed, secret not match.')
            return False

        request.client = client
        log.debug('Authenticate client success.')
        return True
Beispiel #3
0
    def authenticate_client(self, request, *args, **kwargs):
        """Authenticate itself in other means.

        Other means means is described in `Section 3.2.1`_.

        .. _`Section 3.2.1`: http://tools.ietf.org/html/rfc6749#section-3.2.1
        """
        auth = request.headers.get('Authorization', None)
        log.debug('Authenticate client %r', auth)
        if auth:
            try:
                _, s = auth.split(' ')
                client_id, client_secret = decode_base64(s).split(':')
                client_id = to_unicode(client_id, 'utf-8')
                client_secret = to_unicode(client_secret, 'utf-8')
            except Exception as e:
                log.debug('Authenticate client failed with exception: %r', e)
                return False
        else:
            client_id = request.client_id
            client_secret = request.client_secret

        client = self._clientgetter(client_id)
        if not client:
            log.debug('Authenticate client failed, client not found.')
            return False

        request.client = client

        if client.client_secret != client_secret:
            log.debug('Authenticate client failed, secret not match.')
            return False

        log.debug('Authenticate client success.')
        return True
    def authenticate_client(self, request, *args, **kwargs):
        """Whichever authentication method suits you, HTTP Basic might work."""
        auth = request.headers.get('Authorization', None)
        if auth:
            auth_type, s = auth.split(' ')
            if auth_type != 'Basic':
                return False
            client_id, client_secret = decode_base64(s).split(':')
            client_id = to_unicode(client_id, 'utf-8')
            client_secret = to_unicode(client_secret, 'utf-8')

        else:
            client_id = getattr(request, 'client_id', None)
            client_secret = getattr(request, 'client_secret', None)
            if client_id is None or client_secret is None:
                return False

        client = self.get_client(client_id)
        if not client:
            return False

        request.client = client
        request.client_id = client_id

        # oauthlib expect the client to has a client_id attribute
        request.client.client_id = client_id

        if client.secret != client_secret:
            return False

        # if client.client_type != 'confidential':
        #     return False

        return True
Beispiel #5
0
 def load_token(self):
     t = self.token
     if t and "oauth_token" in t and "oauth_token_secret" in t:
         # This really, really violates the Law of Demeter, but
         # I don't see a better way to set these parameters. :(
         self.auth.client.resource_owner_key = to_unicode(t["oauth_token"])
         self.auth.client.resource_owner_secret = to_unicode(t["oauth_token_secret"])
         return True
     return False
Beispiel #6
0
    def request(self, method, url, data=None, headers=None, **kwargs):
        t = self.token
        if t and "oauth_token" in t and "oauth_token_secret" in t:
            # This really, really violates the Law of Demeter, but
            # I don't see a better way to set these parameters. :(
            self.auth.client.resource_owner_key = to_unicode(t["oauth_token"])
            self.auth.client.resource_owner_secret = to_unicode(t["oauth_token_secret"])

        return super(OAuth1Session, self).request(
            method=method, url=url, data=data, headers=headers, **kwargs
        )
    def authenticate_client(self, request, *args, **kwargs):
        """Authenticate client through means outside the OAuth 2 spec.

        Means of authentication is negotiated beforehand and may for example
        be `HTTP Basic Authentication Scheme`_ which utilizes the Authorization
        header.

        Headers may be accesses through request.headers and parameters found in
        both body and query can be obtained by direct attribute access, i.e.
        request.client_id for client_id in the URL query.

        :param request: oauthlib.common.Request
        :rtype: True or False

        Method is used by:
            - Authorization Code Grant
            - Resource Owner Password Credentials Grant (may be disabled)
            - Client Credentials Grant
            - Refresh Token Grant

        .. _`HTTP Basic Authentication Scheme`: http://tools.ietf.org/html/rfc1945#section-11.1  # noqa
        """
        auth = request.headers.get('Authorization', None)
        log.debug('Authenticate client %r', auth)
        if auth:
            try:
                _, s = auth.split(' ')
                client_id, client_secret = decode_base64(s).split(':')
                client_id = to_unicode(client_id, 'utf-8')
                client_secret = to_unicode(client_secret, 'utf-8')
            except Exception as e:
                log.debug('Authenticate client failed with exception: %r', e)
                return False
        else:
            client_id = request.client_id
            client_secret = request.client_secret

        client = self._clientgetter(client_id)
        if not client:
            return False

        if client.client_secret != client_secret:
            log.debug('Authenticate client failed, secret not match.')
            return False

        request.client = client
        log.debug('Authenticate client success.')
        return True
    def __init__(self, client_key,
            client_secret=None,
            resource_owner_key=None,
            resource_owner_secret=None,
            callback_uri=None,
            signature_method=SIGNATURE_HMAC,
            signature_type=SIGNATURE_TYPE_AUTH_HEADER,
            rsa_key=None, verifier=None, realm=None,
            encoding='utf-8', nonce=None, timestamp=None):

        # Convert to unicode using encoding if given, else assume unicode
        encode = lambda x: to_unicode(x, encoding) if encoding else x

        self.client_key = encode(client_key)
        self.client_secret = encode(client_secret)
        self.resource_owner_key = encode(resource_owner_key)
        self.resource_owner_secret = encode(resource_owner_secret)
        self.signature_method = encode(signature_method)
        self.signature_type = encode(signature_type)
        self.callback_uri = encode(callback_uri)
        self.rsa_key = encode(rsa_key)
        self.verifier = encode(verifier)
        self.realm = encode(realm)
        self.encoding = encode(encoding)
        self.nonce = encode(nonce)
        self.timestamp = encode(timestamp)

        if self.signature_method == SIGNATURE_RSA and self.rsa_key is None:
            raise ValueError('rsa_key is required when using RSA signature method.')
 def test_authenticate_client_headers_good(self):
     rv, request = self._create_request_validator()
     credentials = "%s:%s" % (self.app_id, self.app_secret)
     auth = to_unicode(base64.b64encode(credentials.encode('utf-8')),
                       'utf-8')
     request.headers['Authorization'] = 'Basic ' + auth
     self.assertTrue(rv.authenticate_client(request))
Beispiel #10
0
 def _missing_error(r):
     token = loads(r.text)
     if 'errors' in token:
         # Set the error to the first one we have
         token['error'] = token['errors'][0]['errorType']
     r._content = to_unicode(dumps(token)).encode('UTF-8')
     return r
Beispiel #11
0
 def _missing_error(r):
     token = loads(r.text)
     if "errors" in token:
         # Set the error to the first one we have
         token["error"] = token["errors"][0]["errorType"]
     r._content = to_unicode(dumps(token)).encode("UTF-8")
     return r
Beispiel #12
0
    def get_request_token(
        self,
        base_auth_url=None,
        callback_url=None,
        auto_set_token=True,
        **kwargs
    ):
        if callback_url:
            self.session._client.client.callback_uri = \
                to_unicode(callback_url, 'utf-8')

        try:
            token = self.session.fetch_request_token(self.request_token_url)
        except requests.RequestException as e:
            raise TwitterClientError(str(e))
        except ValueError as e:
            raise TwitterClientError('Response does not contain a token.')

        if base_auth_url:
            token['auth_url'] = self.session.authorization_url(
                base_auth_url,
                **kwargs
            )

        if auto_set_token:
            self.auto_set_token(token)

        return JSONObject(token)
Beispiel #13
0
def request_request_token(request):
    """
    Checks provided client key and secret and assigns request token if all goes well.
    """
    server = DjangoOAuthServer()

    if request.method == 'POST':
        try:
            is_request_valid = server.verify_request_token_request(uri=request.build_absolute_uri(), headers=request.META)[0]
        except ValueError as exception:
            return HttpResponse(exception, status=400)
        else:
            if not is_request_valid:
                return HttpResponse(status=401)

        headers = collect_parameters(headers=to_unicode(request.META, 'utf-8'))
        client_key = dict(headers)[u'oauth_consumer_key']
        client = Client.objects.get(key=client_key)

        token = Token.objects.create_request_token(client)

        token_response = urlencode((('oauth_token', token.key), ('oauth_token_secret', token.secret)))

        return HttpResponse(token_response, status=200, content_type='application/x-www-form-urlencoded')

    return HttpResponseNotAllowed('POST', _('Only POST is allowed for this URI.'))
    def test_id_site_callback_handler(self):
        _, acc = self.create_account(self.app.accounts)
        now = datetime.datetime.utcnow()

        try:
            irt = uuid4().get_hex()
        except AttributeError:
            irt = uuid4().hex

        fake_jwt_data = {
                'exp': now + datetime.timedelta(seconds=3600),
                'aud': self.app._client.auth.id,
                'irt': irt,
                'iss': 'Stormpath',
                'sub': acc.href,
                'isNewSub': False,
                'state': None,
        }

        fake_jwt = to_unicode(jwt.encode(
            fake_jwt_data,
            self.app._client.auth.secret,
            'HS256'), 'UTF-8')
        fake_jwt_response = 'http://localhost/?jwtResponse=%s' % fake_jwt
        ret = self.app.handle_id_site_callback(fake_jwt_response)
        self.assertIsNotNone(ret)
        self.assertEqual(ret.account.href, acc.href)
        self.assertIsNone(ret.state)
def _generate_signed_token(request):
    client_id = request.client.client_id
    request.app.api_keys.get_key(client_id)

    # the SP ApiKey is already validated in SPOauth2RequestValidator.validate_client_id
    # but to prevent time based attacks oauthlib always goes through the entire
    # flow  even though the entire request will be deemed invalid
    # in the end.
    secret = request.app._client.auth.secret

    now = datetime.datetime.utcnow()

    data = {
        'iss': request.app.href,
        'sub': client_id,
        'iat': now,
        'exp': now + datetime.timedelta(seconds=request.expires_in)
    }

    if hasattr(request, 'scope'):
        data['scope'] = request.scope

    token = jwt.encode(data, secret, 'HS256')
    token = to_unicode(token, "UTF-8")

    return token
Beispiel #16
0
    def login(self):
        callback_uri = url_for(
            ".authorized", next=request.args.get('next'), _external=True,
        )
        self.session._client.client.callback_uri = to_unicode(callback_uri)

        flask_session['request_token'] = None
        try:
            request_token = self.session.fetch_request_token(self.request_token_url)
            flask_session['request_token'] = request_token
        except TokenRequestDenied as err:
            message = err.args[0]
            response = getattr(err, "response", None)
            log.warning("OAuth 1 request token error: %s", message)
            oauth_error.send(self, message=message, response=response)
            # can't proceed with OAuth, have to just redirect to next_url
            if "next" in request.args:
                next_url = request.args["next"]
            elif self.redirect_url:
                next_url = self.redirect_url
            elif self.redirect_to:
                next_url = url_for(self.redirect_to)
            else:
                next_url = "/"
            return redirect(next_url)

        url = self.session.authorization_url(self.authorization_url)
        return redirect(url)
Beispiel #17
0
    def get_access_token(self, oauth_verifier, auto_set_token=True):
        required = (self.access_token, self.access_token_secret)

        if not all(required):
            raise TwitterClientError(
                '{} must be initialized with access_token and '
                'access_token_secret to fetch authorized '
                'access token.'.format(
                    self.__class__.__name__
                )
            )

        self.session._client.client.verifier = \
            to_unicode(oauth_verifier, 'utf-8')

        try:
            token = self.session.fetch_access_token(self.access_token_url)
        except requests.RequestException as e:
            raise TwitterClientError(str(e))
        except ValueError:
            raise TwitterClientError('Reponse does not contain a token.')

        if auto_set_token:
            self.auto_set_token(token)

        return JSONObject(token)
    def test_id_site_callback_handler_with_major_clock_skew(self):
        _, acc = self.create_account(self.app.accounts)
        now = datetime.datetime.utcnow()

        try:
            irt = uuid4().get_hex()
        except AttributeError:
            irt = uuid4().hex

        fake_jwt_data = {
            'jti': '6S2TKhkW60uYNhcXLThyPo',
            'aud': self.app._client.auth.id,
            'irt': irt,
            'sub': acc.href,
            'isNewSub': False,
            'state': None,
            'exp': now + datetime.timedelta(seconds=3600),
            'iat': now + datetime.timedelta(seconds=20),
            'iss': 'Stormpath',
        }

        fake_jwt = to_unicode(jwt.encode(
            fake_jwt_data,
            self.app._client.auth.secret,
            'HS256'), 'UTF-8')
        fake_jwt_response = 'http://localhost/?jwtResponse=%s' % fake_jwt

        with self.assertRaises(jwt.InvalidIssuedAtError):
            self.app.handle_stormpath_callback(fake_jwt_response)
    def authenticate(self, headers, http_method='', uri='', body=None,
                     scopes=None, ttl=DEFAULT_TTL):
        """Method that authenticates an HTTP request.

        :rtype: :class:`stormpath.api_auth.ApiAuthenticationResult`
        :returns: result if request is valid, `None` otherwise.
        """
        headers = {k: to_unicode(v, 'ascii') for k, v in headers.items()}
        if body is None:
            body = {}
        if scopes is None:
            scopes = []

        auth_scheme, jwt_token = self._get_scheme_and_token(
            headers, http_method, uri, body, scopes, ttl)

        access_token = None
        if jwt_token:
            access_token = AccessToken(self.app, jwt_token)

        valid, result = self._authenticate_request(
            auth_scheme, scopes, http_method, uri, body, headers, ttl)

        if not valid:
            return None

        return ApiAuthenticationResult(
            account=result.account, api_key=result.api_key,
            access_token=access_token)
    def setUp(self):
        super(IDSiteCallbackTest, self).setUp()
        self.store = MagicMock()
        self.store.get_resource.return_value = {'href': 'acchref', 'sp_http_status': 200}
        self.store._cache_get.return_value = False # ignore nonce

        self.client.data_store = self.store

        self.app = Application(
                client=self.client,
                properties={'href': 'apphref', 'accounts': {'href': 'acchref'}})

        self.acc = MagicMock(href='acchref')
        now = datetime.datetime.utcnow()

        try:
            irt = uuid4().get_hex()
        except AttributeError:
            irt = uuid4().hex

        fake_jwt_data = {
                'exp': now + datetime.timedelta(seconds=3600),
                'aud': self.app._client.auth.id,
                'irt': irt,
                'iss': 'Stormpath',
                'sub': self.acc.href,
                'isNewSub': False,
                'state': None,
        }

        self.fake_jwt = to_unicode(jwt.encode(
            fake_jwt_data,
            self.app._client.auth.secret,
            'HS256'), 'UTF-8')
Beispiel #21
0
    def __init__(
        self,
        client_key,
        client_secret=None,
        resource_owner_key=None,
        resource_owner_secret=None,
        callback_uri=None,
        signature_method=SIGNATURE_HMAC,
        signature_type=SIGNATURE_TYPE_AUTH_HEADER,
        rsa_key=None,
        verifier=None,
        realm=None,
        encoding="utf-8",
        decoding=None,
        nonce=None,
        timestamp=None,
    ):
        """Create an OAuth 1 client.

        :param client_key: Client key (consumer key), mandatory.
        :param resource_owner_key: Resource owner key (oauth token).
        :param resource_owner_secret: Resource owner secret (oauth token secret).
        :param callback_uri: Callback used when obtaining request token.
        :param signature_method: SIGNATURE_HMAC, SIGNATURE_RSA or SIGNATURE_PLAINTEXT.
        :param signature_type: SIGNATURE_TYPE_AUTH_HEADER (default),
                               SIGNATURE_TYPE_QUERY or SIGNATURE_TYPE_BODY
                               depending on where you want to embed the oauth
                               credentials.
        :param rsa_key: RSA key used with SIGNATURE_RSA.
        :param verifier: Verifier used when obtaining an access token.
        :param realm: Realm (scope) to which access is being requested.
        :param encoding: If you provide non-unicode input you may use this
                         to have oauthlib automatically convert.
        :param decoding: If you wish that the returned uri, headers and body
                         from sign be encoded back from unicode, then set
                         decoding to your preferred encoding, i.e. utf-8.
        :param nonce: Use this nonce instead of generating one. (Mainly for testing)
        :param timestamp: Use this timestamp instead of using current. (Mainly for testing)
        """
        # Convert to unicode using encoding if given, else assume unicode
        encode = lambda x: to_unicode(x, encoding) if encoding else x

        self.client_key = encode(client_key)
        self.client_secret = encode(client_secret)
        self.resource_owner_key = encode(resource_owner_key)
        self.resource_owner_secret = encode(resource_owner_secret)
        self.signature_method = encode(signature_method)
        self.signature_type = encode(signature_type)
        self.callback_uri = encode(callback_uri)
        self.rsa_key = encode(rsa_key)
        self.verifier = encode(verifier)
        self.realm = encode(realm)
        self.encoding = encode(encoding)
        self.decoding = encode(decoding)
        self.nonce = encode(nonce)
        self.timestamp = encode(timestamp)

        if self.signature_method == SIGNATURE_RSA and self.rsa_key is None:
            raise ValueError("rsa_key is required when using RSA signature method.")
Beispiel #22
0
 def decorated(*args, **kwargs):
     auth = request.headers.get('Authorization', None)
     if not auth:
         raise NotConfidential()
     try:
         _, s = auth.split(' ')
         client_id, client_secret = decode_base64(s).split(':')
         client_id = to_unicode(client_id, 'utf-8')
         client_secret = to_unicode(client_secret, 'utf-8')
     except:
         raise NotConfidential()
     client = oauth._clientgetter(client_id)
     if not client or client.client_secret != client_secret:
         raise NotConfidential()
     if not client.is_confidential:
         raise NotConfidential()
     return f(*args, **kwargs)
 def extract_client_data(self):
     """Helper method for extracting client ID and secret from the
     authorization header.
     """
     _, b64encoded_data = self.authorization.split(' ')
     decoded_data = to_unicode(
         base64.b64decode(b64encoded_data.encode('utf-8')), 'ascii')
     self.client_id, self.client_secret = decoded_data.split(':')
Beispiel #24
0
 def login(self):
     callback_uri = url_for(
         ".authorized", next=request.args.get('next'), _external=True,
     )
     self.session._client.client.callback_uri = to_unicode(callback_uri)
     self.session.fetch_request_token(self.request_token_url)
     url = self.session.authorization_url(self.authorization_url)
     return redirect(url)
Beispiel #25
0
    def _compliance_fix(r):
        if r.status_code != 200:
            return r

        token = r.json()
        expires_in = token.get("expires_in")
        if expires_in and int(expires_in) < 1:
            token.pop("expires_in")
        r._content = to_unicode(dumps(token)).encode("UTF-8")
        return r
Beispiel #26
0
 def login(self):
     secure = request.is_secure or request.headers.get("X-Forwarded-Proto", "http") == "https"
     callback_uri = url_for(
         ".authorized", next=request.args.get('next'), _external=True,
         _scheme="https" if secure else "http",
     )
     self.session._client.client.callback_uri = to_unicode(callback_uri)
     self.session.fetch_request_token(self.request_token_url)
     url = self.session.authorization_url(self.authorization_url)
     return redirect(url)
    def _compliance_fix(r):
        # Plenty returns the Token in CamelCase instead of _
        if 'application/json' in r.headers.get('content-type', {}) and r.status_code == 200:
            token = loads(r.text)
        else:
            return r

        fixed_token = {}
        for k, v in token.items():
            fixed_token[_to_snake_case(k)] = v

        r._content = to_unicode(dumps(fixed_token)).encode('UTF-8')
        return r
 def authenticate_client(self, request, *args, **kwargs):
     request.app = self.app
     request.expires_in = self.ttl
     authorization = request.headers.get('Authorization')
     try:
         auth_scheme, b64encoded_data = authorization.split(' ')
         decoded_data = to_unicode(
             base64.b64decode(b64encoded_data.encode('utf-8')), 'ascii')
         client_id, _ = decoded_data.split(':')
         request.client = Oauth2BackendApplicationClient(client_id)
     except Exception:
         return False
     if self.validate_client_id(client_id, request):
         return True
     return False
    def build_id_site_redirect_url(self, callback_uri, path=None, state=None, logout=False):
        """Builds a redirect uri for ID site.

        :param callback_uri: Callback URI to witch Stormpaath will redirect after
            the user has entered their credentials on the ID site. Note: For security reasons
            this is required to be the same as "Authorized Redirect URI" in the
            Admin Console's ID Site settings.

        :param path:
            An optional string indicating to wich template we should redirect the user to.
            By default it will redirect to the login screen but you can redirect to the
            registration or forgot password screen with '/#/register' and '/#/forgot' respectively.

        :param state: an optional string that stores information that your application needs
            after the user is redirected back to your application

        :param logout: a Boolean value indicating if this should redirect to the logout endpoint

        :return: A URI to witch to redirect the user.
        """
        import jwt
        from oauthlib.common import to_unicode
        api_key_secret = self._client.auth.secret
        api_key_id = self._client.auth.id

        endpoint = self.SSO_LOGOUT_ENDPOINT if logout else self.SSO_ENDPOINT

        try:
            irt = uuid4().get_hex()
        except AttributeError:
            irt = uuid4().hex

        body = {
            'iat': datetime.utcnow(),
            'jti': irt,
            'iss': api_key_id,
            'sub': self.href,
            'cb_uri': callback_uri,
        }
        if path:
            body['path'] = path
        if state:
            body['state'] = state

        jwt_signature = to_unicode(jwt.encode(body, api_key_secret, 'HS256'), 'UTF-8')
        url_params = {'jwtRequest': jwt_signature}
        return endpoint + '?' + urlencode(url_params)
Beispiel #30
0
    def prepare_request_body(self,
                             private_key=None,
                             subject=None,
                             issuer=None,
                             audience=None,
                             expires_at=None,
                             issued_at=None,
                             extra_claims=None,
                             body='',
                             scope=None,
                             **kwargs):
        key = private_key or self.private_key
        if not key:
            raise ValueError(
                "Encryption key must be supplied to make JWT token requests."
            )

        claim = {
            "iss": issuer or self.issuer,
            "aud": audience or self.audience,
            "sub": subject,
            "exp": int(expires_at or time.time() + 3600),
            "iat": int(issued_at or time.time()),
            "scope": scope,
        }

        for attr in {"iss", "aud"}:
            if claim[attr] is None:
                raise ValueError(
                    "Claim must include {} but none was given.".format(attr)
                )

        if "not_before" in kwargs:
            claim["nbf"] = kwargs.pop("not_before")

        if "jwt_id" in kwargs:
            claim["jti"] = kwargs.pop("jwt_id")

        claim.update(extra_claims or {})

        assertion = jwt.encode(claim, key, "RS256")
        assertion = to_unicode(assertion)

        return prepare_token_request(self.grant_type,
                                     body=body,
                                     assertion=assertion,
                                     **kwargs)
Beispiel #31
0
def _encode(text, encoding='utf-8'):
    if encoding:
        return to_unicode(text, encoding)
    return text
Beispiel #32
0
 def dummy_client(self):
     return to_unicode('dummy_client', 'utf-8')