Ejemplo n.º 1
0
    def test_parse_token_response(self):
        client = MobileApplicationClient(self.client_id)

        # Parse code and state
        response = client.parse_request_uri_response(self.response_uri, scope=self.scope)
        self.assertEqual(response, self.token)
        self.assertEqual(client.access_token, response.get("access_token"))
        self.assertEqual(client.refresh_token, response.get("refresh_token"))
        self.assertEqual(client.token_type, response.get("token_type"))

        # Mismatching scope
        self.assertRaises(Warning, client.parse_request_uri_response, self.response_uri, scope="invalid")
        os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '4'
        token = client.parse_request_uri_response(self.response_uri, scope='invalid')
        self.assertTrue(token.scope_changed)

        scope_changes_recorded = []
        def record_scope_change(sender, message, old, new):
            scope_changes_recorded.append((message, old, new))

        signals.scope_changed.connect(record_scope_change)
        try:
            client.parse_request_uri_response(self.response_uri, scope="invalid")
            self.assertEqual(len(scope_changes_recorded), 1)
            message, old, new = scope_changes_recorded[0]
            self.assertEqual(message, 'Scope has changed from "invalid" to "/profile".')
            self.assertEqual(old, ['invalid'])
            self.assertEqual(new, ['/profile'])
        finally:
            signals.scope_changed.disconnect(record_scope_change)
        del os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE']
Ejemplo n.º 2
0
    def test_parse_token_response(self):
        client = MobileApplicationClient(self.client_id)

        # Parse code and state
        response = client.parse_request_uri_response(self.response_uri, scope=self.scope)
        self.assertEqual(response, self.token)
        self.assertEqual(client.access_token, response.get("access_token"))
        self.assertEqual(client.refresh_token, response.get("refresh_token"))
        self.assertEqual(client.token_type, response.get("token_type"))

        # Mismatching scope
        self.assertRaises(Warning, client.parse_request_uri_response, self.response_uri, scope="invalid")
        os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '4'
        token = client.parse_request_uri_response(self.response_uri, scope='invalid')
        self.assertTrue(token.scope_changed)

        scope_changes_recorded = []
        def record_scope_change(sender, message, old, new):
            scope_changes_recorded.append((message, old, new))

        signals.scope_changed.connect(record_scope_change)
        try:
            client.parse_request_uri_response(self.response_uri, scope="invalid")
            self.assertEqual(len(scope_changes_recorded), 1)
            message, old, new = scope_changes_recorded[0]
            self.assertEqual(message, 'Scope has changed from "invalid" to "/profile".')
            self.assertEqual(old, ['invalid'])
            self.assertEqual(new, ['/profile'])
        finally:
            signals.scope_changed.disconnect(record_scope_change)
        del os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE']
Ejemplo n.º 3
0
    def test_populate_attributes(self):

        client = MobileApplicationClient(self.client_id)

        response_uri = (self.response_uri + "&code=EVIL-CODE")

        client.parse_request_uri_response(response_uri, scope=self.scope)

        # We must not accidentally pick up any further security
        # credentials at this point.
        self.assertIsNone(client.code)
Ejemplo n.º 4
0
    def test_populate_attributes(self):

        client = MobileApplicationClient(self.client_id)

        response_uri = (self.response_uri + "&code=EVIL-CODE")

        client.parse_request_uri_response(response_uri, scope=self.scope)

        # We must not accidentally pick up any further security
        # credentials at this point.
        self.assertIsNone(client.code)
    def test_parse_token_response(self):
        client = MobileApplicationClient(self.client_id)

        # Parse code and state
        response = client.parse_request_uri_response(self.response_uri, scope=self.scope)
        self.assertEqual(response, self.token)
        self.assertEqual(client.access_token, response.get("access_token"))
        self.assertEqual(client.refresh_token, response.get("refresh_token"))
        self.assertEqual(client.token_type, response.get("token_type"))

        # Mismatching scope
        self.assertRaises(Warning, client.parse_request_uri_response, self.response_uri, scope="invalid")
    def test_parse_token_response(self):
        client = MobileApplicationClient(self.client_id)

        # Parse code and state
        response = client.parse_request_uri_response(self.response_uri,
                                                     scope=self.scope)
        self.assertEqual(response, self.token)
        self.assertEqual(client.access_token, response.get("access_token"))
        self.assertEqual(client.refresh_token, response.get("refresh_token"))
        self.assertEqual(client.token_type, response.get("token_type"))

        # Mismatching scope
        self.assertRaises(Warning,
                          client.parse_request_uri_response,
                          self.response_uri,
                          scope="invalid")
Ejemplo n.º 7
0
class Client(object):
    def __init__(self, username, password, client_id=None, api_key=None):
        if client_id is None:
            client_id = uuid.uuid4()
        self.client_id = client_id

        self._api_key = api_key
        self.username = username
        self.password = password

        self.endpoint = MobileApplicationClient(self.client_id)

    @property
    def api_key(self):
        if self._api_key is None:
            self._api_key = self.register()
        return self._api_key

    def url_for_workflow(self, workflow):
        return 'https://%s/view/%s' % (RESOURCE_URL, workflow)

    def url_for_register(self):
        return 'https://%s/register' % AUTH_URL

    def register(self):
        params = {
            'username': self.username,
            'password': self.password
        }
        response = requests.get(self.url_for_register(), params=params,
                verify=False)

        if response.status_code == 201:
            if 'X-API-Key' in response.headers:
                return response.headers['X-API-Key']
            else:
                raise RuntimeError('No X-API-Key header in response (%s)' %
                        response.text)
        elif response.status_code == 401:
            raise RuntimeError('Not authorized (%s)' % response.text)
        else:
            raise RuntimeError('Unexpected response %d from authorization server (%s)' %
                    (response.status_code, response.text))

    def view_without_access_token(self, workflow_name):
        response = requests.get(self.url_for_workflow(workflow_name),
                verify=False)

        if response.status_code == 401:
            return response
        elif response.status_code == 404:
            raise RuntimeError('Not found (%s)' % response.text)
        else:
            raise RuntimeError('Unexpected response %d from resource server (%s)' %
                    (response.status_code, response.text))

    def extract_auth_headers(self, response):
        try:
            oauth_url = response.headers['X-OAuth-URL']
            # Must be Unicode for oauthlib, le sigh:
            required_scope = unicode(response.headers['X-Required-Scope'])
        except KeyError:
            raise RuntimeError('Did not find expected headers in response from '
                    'resource server')
        return oauth_url, required_scope

    def authorize(self, oauth_url, redirect_uri, required_scope):
        headers = {
            'X-API-Key': self.api_key,
        }
        request_url = self.endpoint.prepare_request_uri(oauth_url,
                redirect_uri=redirect_uri, scope=required_scope)
        response = requests.get(request_url, headers=headers,
                allow_redirects=False, verify=False)

        if response.status_code == 302:
            return response
        elif response.status_code == 401:
            raise RuntimeError('Not authorized (%s)' % response.text)
        elif response.status_code == 403:
            raise RuntimeError('Forbidden (%s)' % response.text)
        else:
            raise RuntimeError('Unexpected response %d from authorization server (%s)' %
                    (response.status_code, response.text))

    def create_access_token(self, location):
        return AccessToken(**self.endpoint.parse_request_uri_response(location))

    def view_with_access_token(self, workflow_name, access_token):
        response = requests.get(self.url_for_workflow(workflow_name),
                params=access_token.as_query_params, verify=False)

        if response.status_code == 200:
            return response
        elif response.status_code == 403:
            raise RuntimeError('Forbidden (%s)' % response.text)
        elif response.status_code == 404:
            raise RuntimeError('Not found (%s)' % response.text)
        else:
            raise RuntimeError('Unexpected response %d from resource server (%s)' %
                    (response.status_code, response.text))

    def get_access_token_for_view_workflow(self, workflow_name):
        initial_view_response = self.view_without_access_token(workflow_name)
        oauth_url, required_scope = self.extract_auth_headers(initial_view_response)

        authorize_response = self.authorize(oauth_url=oauth_url,
                redirect_uri=self.url_for_workflow(workflow_name),
                required_scope=required_scope)

        return self.create_access_token(authorize_response.headers['Location'])

    def view_workflow(self, workflow_name, access_token=None):
        if access_token is None:
            access_token = self.get_access_token_for_view_workflow(workflow_name)
        view_response = self.view_with_access_token(workflow_name, access_token)
        return view_response.text