Exemplo n.º 1
0
    def handle_oauth2_response_discord(self, args):
        """Handles an oauth2 authorization response."""

        client = self.make_client()
        remote_args = {
            "client_id": self.consumer_key,
            "client_secret": self.consumer_secret,
            "code": args.get("code"),
            "redirect_uri": session.get("%s_oauthredir" % self.name),
            "scope": "identify",
        }
        log.debug("Prepare oauth2 remote args %r", remote_args)
        remote_args.update(self.access_token_params)
        headers = copy(self._access_token_headers)
        if self.access_token_method == "POST":
            headers.update(
                {"Content-Type": "application/x-www-form-urlencoded"})
            body = client.prepare_request_body(**remote_args)
            response = requests.request(
                self.access_token_method,
                self.expand_url(self.access_token_url),
                headers=headers,
                data=to_bytes(body, self.encoding),
            )
            if response.status_code not in (200, 201):
                raise OAuthException(
                    "Invalid response from %s" % self.name,
                    type="invalid_response",
                    data=to_bytes(body, self.encoding),
                )
            return jsonify(response.text.encode("utf8"))
        elif self.access_token_method == "GET":
            qs = client.prepare_request_body(**remote_args)
            url = self.expand_url(self.access_token_url)
            url += ("?" in url and "&" or "?") + qs
            response = requests.request(self.access_token_method,
                                        url,
                                        headers=headers)
            if response.status_code not in (200, 201):
                raise OAuthException(
                    "Invalid response from %s" % self.name,
                    type="invalid_response",
                    data=to_bytes(body, self.encoding),
                )
            return jsonify(response.text.encode("utf8"))
        else:
            raise OAuthException("Unsupported access_token_method: %s" %
                                 self.access_token_method)
Exemplo n.º 2
0
def test_server_login(app):
    headers = {
        'X-Forwarded-Path':
        'http://localhost:8090/auctions/11111111111111111111111111111111'
        '/authorized?code=HVRviZDxswGzM8AYN3rz0qMLrh6rhY'
    }
    res = app.post('/login', headers=headers)
    assert res.status == '405 METHOD NOT ALLOWED'
    assert res.status_code == 405

    res = app.get('/login')
    assert res.status == '401 UNAUTHORIZED'
    assert res.status_code == 401

    res = app.get('/login?bidder_id=5675acc9232942e8940a034994ad883e&'
                  'hash=bd4a790aac32b73e853c26424b032e5a29143d1f')
    assert res.status == '302 FOUND'
    assert res.status_code == 302
    assert res.location == 'https://my.test.url'
    with app.application.test_request_context():
        session['login_bidder_id'] = u'5675acc9232942e8940a034994ad883e'
        session['login_hash'] = u'bd4a790aac32b73e853c26424b032e5a29143d1f'
        session['login_callback'] = 'http://localhost/authorized'
        log_message = 'Session: {}'.format(repr(session))
        app.application.logger.debug.assert_called_with(log_message)

    res = app.get(
        '/login?bidder_id=5675acc9232942e8940a034994ad883e&'
        'hash=bd4a790aac32b73e853c26424b032e5a29143d1f',
        headers=headers)
    assert res.status == '302 FOUND'
    assert res.status_code == 302
    assert res.location == 'https://my.test.url'
    with app.application.test_request_context():
        session[u'login_bidder_id'] = u'5675acc9232942e8940a034994ad883e'
        session[u'login_hash'] = u'bd4a790aac32b73e853c26424b032e5a29143d1f'
        session[u'login_callback'] = u'http://localhost:8090/auctions/' \
            '11111111111111111111111111111111/authorized'
        log_message = 'Session: {}'.format(repr(session))
        app.application.logger.debug.assert_called_with(log_message)

    res = app.get('/login?bidder_id=5675acc9232942e8940a034994ad883e&'
                  'hash=bd4a790aac32b73e853c26424b032e5a29143d1f&'
                  'return_url=https://my.secret.url/')
    assert res.status == '302 FOUND'
    assert res.status_code == 302
    assert res.location == 'https://my.test.url'
    with app.application.test_request_context():
        session['return_url'] = u'https://my.secret.url/'
        session['login_bidder_id'] = u'5675acc9232942e8940a034994ad883e'
        session['login_hash'] = u'bd4a790aac32b73e853c26424b032e5a29143d1f'
        session['login_callback'] = 'http://localhost/authorized'

    app.application.remote_oauth.authorize.side_effect = OAuthException(
        "Invalid response")
    res = app.get(
        '/login?bidder_id=5675acc9232942e8940a034994ad883e&'
        'hash=bd4a790aac32b73e853c26424b032e5a29143d1f',
        headers=headers)
    assert res.status == "503 SERVICE UNAVAILABLE"
Exemplo n.º 3
0
def test_server_relogin(app):
    headers = {
        'X-Forwarded-Path':
        'http://localhost:8090/auctions/11111111111111111111111111111111'
        '/authorized?code=HVRviZDxswGzM8AYN3rz0qMLrh6rhY'
    }

    res = app.post('/relogin', headers=headers)
    assert res.status == '405 METHOD NOT ALLOWED'
    assert res.status_code == 405

    res = app.get('/relogin', headers=headers)
    assert res.status_code == 302
    assert res.status == '302 FOUND'
    assert res.location == \
        'http://localhost:8090/auctions/11111111111111111111111111111111'
    s = {
        'login_callback': 'https://some.url/',
        'login_bidder_id': 'some_id',
        'login_hash': 'some_cache',
        'amount': 100
    }
    with patch('openprocurement.auction.worker.server.session', s):
        res = app.get('/relogin?amount=100', headers=headers)
    assert res.status_code == 302
    assert res.status == '302 FOUND'
    assert res.location == 'https://my.test.url'

    app.application.remote_oauth.authorize.side_effect = OAuthException(
        "Invalid response")
    with patch('openprocurement.auction.worker.server.session', s):
        res = app.get('/relogin', headers=headers)
    assert res.status == "503 SERVICE UNAVAILABLE"
Exemplo n.º 4
0
def get_user_info(user):
    # https://developer-programs.linkedin.com/documents/field-selectors
    url = 'v1/people/~:(%s)?format=json' % ','.join(USER_INFO_FIELDS)
    token = retrieve_access_token(user)

    if token is None:
        raise OAuthException('Access token unavailable or expired for %s' %
                             user.email)

    res = linkedin.get(url, token=token)

    if res.status != 200:
        raise OAuthException('Server returned HTTP %d: %s' %
                             (res.status, repr(res.data)),
                             data=res.data)

    return res.data
Exemplo n.º 5
0
    def handle_oauth2_response(self):
        """Handles an oauth2 authorization response.

        This method overrides the one provided by OAuthRemoteApp in order to
        support Basic HTTP Authentication.
        """
        if self.access_token_method != 'POST':
            raise OAuthException(
                ('Unsupported access_token_method: {}. '
                 'Only POST is supported.').format(self.access_token_method))

        client = self.make_client()
        remote_args = {
            'code':
            request.args.get('code'),
            'client_secret':
            self.consumer_secret,
            'redirect_uri': (session.get('%s_oauthredir' % self.name)
                             or url_for('invenio_oauthclient.authorized',
                                        remote_app=self.name,
                                        _external=True)),
        }
        remote_args.update(self.access_token_params)
        # build the Basic HTTP Authentication code
        b2access_basic_auth = base64.encodestring(
            bytes('{0}:{1}'.format(self.consumer_key, self.consumer_secret),
                  'utf-8')).decode('ascii').replace('\n', '')
        body = client.prepare_request_body(**remote_args)
        resp, content = self.http_request(
            self.expand_url(self.access_token_url),
            # set the Authentication header
            headers={
                'Authorization': 'Basic {}'.format(b2access_basic_auth),
            },
            data=to_bytes(body, self.encoding),
            method=self.access_token_method,
        )

        data = parse_response(resp, content, content_type=self.content_type)
        if resp.code not in (200, 201):
            raise OAuthException('Invalid response from %s' % self.name,
                                 type='invalid_response',
                                 data=data)
        return data
Exemplo n.º 6
0
    def handle_oauth2_response_spotify(self, args):
        """Handles an oauth2 authorization response."""

        client = self.make_client()
        remote_args = {
            "code": args.get("code"),
            "redirect_uri": session.get("%s_oauthredir" % self.name),
        }
        log.debug("Prepare oauth2 remote args %r", remote_args)
        remote_args.update(self.access_token_params)
        data = f"{self._consumer_key}:{self._consumer_secret}"
        encoded = str(base64.b64encode(data.encode("utf-8")), "utf-8")
        headers = {"Authorization": f"Basic {encoded}"}
        if self.access_token_method == "POST":
            headers.update(
                {"Content-Type": "application/x-www-form-urlencoded"})
            body = client.prepare_request_body(**remote_args)
            resp, content = self.http_request(
                self.expand_url(self.access_token_url),
                headers=headers,
                data=to_bytes(body, self.encoding),
                method=self.access_token_method,
            )
        elif self.access_token_method == "GET":
            qs = client.prepare_request_body(**remote_args)
            url = self.expand_url(self.access_token_url)
            url += ("?" in url and "&" or "?") + qs
            resp, content = self.http_request(url,
                                              headers=headers,
                                              method=self.access_token_method)
        else:
            raise OAuthException("Unsupported access_token_method: %s" %
                                 self.access_token_method)

        data = OAuth.parse_response(resp,
                                    content,
                                    content_type=self.content_type)
        if resp.code not in (200, 201):
            raise OAuthException(
                "Invalid response from %s" % self.name,
                type="invalid_response",
                data=data,
            )
        return data
Exemplo n.º 7
0
def get_dict_from_response(response: OAuthResponse) -> dict:
    """Check for errors in the response and return the resulting dict.

    :param response: The OAuth response.
    :returns: Response data dict
    """
    if getattr(response, '_resp') and response._resp.code > 400:
        raise OAuthException(
            'OpenID Remote Application failed to parse response', None,
            response)

    return response.data
Exemplo n.º 8
0
    def test_if_get_profile_error_is_caught_return_false(self, app):
        from flask import current_app as flask_app

        flask_app.sso_client = unittest.mock.Mock()
        handled_exceptions = [
            URLError('e'),
            OAuthException('e'),
            HTTPException('e')
        ]
        flask_app.sso_client.get_profile.side_effect = handled_exceptions
        for e in handled_exceptions:
            response = token.is_authenticated()
            assert response is False
Exemplo n.º 9
0
    def handle_oauth2_response(self):
        if self.access_token_method != 'POST':
            raise OAuthException('Unsupported access_token_method: %s' %
                                 self.access_token_method)

        client = self.make_client()
        remote_args = {
            'code': request.args.get('code'),
            'client_secret': self.consumer_secret,
            'redirect_uri': session.get('%s_oauthredir' % self.name)
        }
        remote_args.update(self.access_token_params)

        reddit_basic_auth = base64.encodestring(
            '%s:%s' % (REDDIT_APP_ID, REDDIT_APP_SECRET)).replace('\n', '')
        body = client.prepare_request_body(**remote_args)
        while True:
            resp, content = self.http_request(
                self.expand_url(self.access_token_url),
                headers={
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Authorization': 'Basic %s' % reddit_basic_auth,
                    'User-Agent': REDDIT_USER_AGENT
                },
                data=to_bytes(body, self.encoding),
                method=self.access_token_method,
            )
            # Reddit API is rate-limited, so if we get 429, we need to retry
            if resp.code != 429:
                break
            time.sleep(1)

        data = parse_response(resp, content, content_type=self.content_type)
        if resp.code not in (200, 201):
            raise OAuthException('Invalid response from %s' % self.name,
                                 type='invalid_response',
                                 data=data)
        return data
Exemplo n.º 10
0
    def get_user_id(self, remote, email: str = None) -> str:
        """Determine ID for a given user/email.

        :param id_claim: Claim name containing user ID
        :param remote: The remote application.
        :param email: (optional) User e-mail address
        :returns: User ID
        """
        user_id = self.get_userinfo(remote).sub
        if not user_id:
            raise OAuthException(
                'User {} is missing *sub* attribute for '
                '{} Remote Application'.format(email, self.name), None, None)
        return user_id
Exemplo n.º 11
0
	def handle_unknown_response(self):
		if request.args.get('authorize') == 0:
			return None

		print "lkjalskdjflkjasdf"
		consumer = oldOauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
		client = oldOauth.Client(consumer, oldOauth.Token(*session['%s_oauthtok' % self.name]))
		response, content = client.request(self.access_token_url, 'POST')

		print response

		if response['status'] not in ('200', '201'):
			raise OAuthException(
				'Invalid response from %s' % self.name,
				type='invalid_response', data=response)

		decoded = url_decode(content).to_dict()
		return decoded
Exemplo n.º 12
0
def test_server_authorized(app):
    headers = {
        'X-Forwarded-Path':
        'http://localhost:8090/auctions/11111111111111111111111111111111'
        '/authorized?code=HVRviZDxswGzM8AYN3rz0qMLrh6rhY'
    }

    res = app.post('/authorized', headers=headers)
    assert res.status == '405 METHOD NOT ALLOWED'
    assert res.status_code == 405

    res = app.get('/authorized', headers=headers)
    assert res.status_code == 403
    assert res.status == '403 FORBIDDEN'

    res = app.get('/authorized?error=access_denied')
    assert res.status_code == 403
    assert res.status == '403 FORBIDDEN'

    res = app.get('/authorized', headers=headers)
    assert res.status_code == 302
    assert res.status == '302 FOUND'
    assert res.location == \
        'http://localhost:8090/auctions/11111111111111111111111111111111'
    auctions_loggedin = False
    auction_session = False
    path = False
    for h in res.headers:
        if h[1].startswith('auctions_loggedin=1'):
            auctions_loggedin = True
            if h[1].index('Path=/auctions/UA-11111'):
                path = True
        if h[1].startswith('auction_session='):
            auction_session = True
    assert auction_session is True
    assert auctions_loggedin is True
    assert path is True

    app.application.remote_oauth.authorized_response.side_effect = OAuthException(
        "Invalid response")
    res = app.get('/authorized', headers=headers)
    assert res.status == "503 SERVICE UNAVAILABLE"
Exemplo n.º 13
0
    def request(
        self,
        url,
        data=None,
        headers=None,
        format="urlencoded",
        method="GET",
        content_type=None,
        token=None,
        discord=False,
    ):
        """
        Sends a request to the remote server with OAuth tokens attached.

        :param data: the data to be sent to the server.
        :param headers: an optional dictionary of headers.
        :param format: the format for the `data`. Can be `urlencoded` for
                       URL encoded data or `json` for JSON.
        :param method: the HTTP request method to use.
        :param content_type: an optional content type. If a content type
                             is provided, the data is passed as it, and
                             the `format` is ignored.
        :param token: an optional token to pass, if it is None, token will
                      be generated by tokengetter.
        """

        headers = dict(headers or {})
        if token is None:
            token = self.get_request_token()

        client = self.make_client(token)
        url = self.expand_url(url)
        if method == "GET":
            assert format == "urlencoded"
            if data:
                url = add_params_to_uri(url, data)
                data = None
        else:
            if content_type is None:
                data, content_type = OAuth.encode_request_data(data, format)
            if content_type is not None:
                headers["Content-Type"] = content_type

        if self.request_token_url:
            # oauth1
            uri, headers, body = client.sign(url,
                                             http_method=method,
                                             body=data,
                                             headers=headers)
        else:
            # oauth2
            uri, headers, body = client.add_token(url,
                                                  http_method=method,
                                                  body=data,
                                                  headers=headers)

        if hasattr(self, "pre_request"):
            # This is designed for some rubbish services like weibo.
            # Since they don't follow the standards, we need to
            # change the uri, headers, or body.
            uri, headers, body = self.pre_request(uri, headers, body)

        if body:
            data = to_bytes(body, self.encoding)
        else:
            data = None
        if discord:
            response = requests.request(method,
                                        uri,
                                        headers=headers,
                                        data=to_bytes(body, self.encoding))
            if response.status_code not in (200, 201):
                raise OAuthException("Invalid response from %s" % self.name,
                                     type="invalid_response",
                                     data=data)
            return jsonify(response.text.encode("utf8"))

        resp, content = self.http_request(uri,
                                          headers,
                                          data=to_bytes(body, self.encoding),
                                          method=method)
        return OAuthResponse(resp, content, self.content_type)