def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.get_default_redirect_uri.return_value = None
     self.web = WebApplicationServer(self.validator)
     self.mobile = MobileApplicationServer(self.validator)
     self.legacy = LegacyApplicationServer(self.validator)
     self.backend = BackendApplicationServer(self.validator)
Beispiel #2
0
class ExtraCredentialsTest(TestCase):
    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        self.web = WebApplicationServer(self.validator)
        self.mobile = MobileApplicationServer(self.validator)
        self.legacy = LegacyApplicationServer(self.validator)
        self.backend = BackendApplicationServer(self.validator)

    def test_post_authorization_request(self):
        def save_code(client_id, token, request):
            self.assertEqual('creds', request.extra)

        def save_token(token, request):
            self.assertEqual('creds', request.extra)

        # Authorization code grant
        self.validator.save_authorization_code.side_effect = save_code
        self.web.create_authorization_response(
            'https://i.b/auth?client_id=foo&response_type=code',
            scopes=['foo'],
            credentials={'extra': 'creds'})

        # Implicit grant
        self.validator.save_bearer_token.side_effect = save_token
        self.web.create_authorization_response(
            'https://i.b/auth?client_id=foo&response_type=token',
            scopes=['foo'],
            credentials={'extra': 'creds'})

    def test_token_request(self):
        def save_token(token, request):
            self.assertIn('extra', token)

        self.validator.save_bearer_token.side_effect = save_token
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.web.create_token_response(
            'https://i.b/token',
            body='grant_type=authorization_code&code=foo',
            credentials={'extra': 'creds'})

        # Password credentials grant
        self.legacy.create_token_response(
            'https://i.b/token',
            body='grant_type=password&username=foo&password=bar',
            credentials={'extra': 'creds'})

        # Client credentials grant
        self.backend.create_token_response(
            'https://i.b/token',
            body='grant_type=client_credentials',
            credentials={'extra': 'creds'})
Beispiel #3
0
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.get_default_redirect_uri.return_value = TestScopeHandling.DEFAULT_REDIRECT_URI
     self.validator.authenticate_client.side_effect = self.set_client
     self.web = WebApplicationServer(self.validator)
     self.mobile = MobileApplicationServer(self.validator)
     self.legacy = LegacyApplicationServer(self.validator)
     self.backend = BackendApplicationServer(self.validator)
class ExtraCredentialsTest(TestCase):

    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        self.web = WebApplicationServer(self.validator)
        self.mobile = MobileApplicationServer(self.validator)
        self.legacy = LegacyApplicationServer(self.validator)
        self.backend = BackendApplicationServer(self.validator)

    def test_post_authorization_request(self):
        def save_code(client_id, token, request):
            self.assertEqual('creds', request.extra)

        def save_token(token, request):
            self.assertEqual('creds', request.extra)

        # Authorization code grant
        self.validator.save_authorization_code.side_effect = save_code
        self.web.create_authorization_response(
                'https://i.b/auth?client_id=foo&response_type=code',
                scopes=['foo'],
                credentials={'extra': 'creds'})

        # Implicit grant
        self.validator.save_bearer_token.side_effect = save_token
        self.mobile.create_authorization_response(
                'https://i.b/auth?client_id=foo&response_type=token',
                scopes=['foo'],
                credentials={'extra': 'creds'})

    def test_token_request(self):
        def save_token(token, request):
            self.assertIn('extra', token)

        self.validator.save_bearer_token.side_effect = save_token
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.web.create_token_response('https://i.b/token',
                body='grant_type=authorization_code&code=foo',
                credentials={'extra': 'creds'})

        # Password credentials grant
        self.legacy.create_token_response('https://i.b/token',
                body='grant_type=password&username=foo&password=bar',
                credentials={'extra': 'creds'})

        # Client credentials grant
        self.backend.create_token_response('https://i.b/token',
                body='grant_type=client_credentials',
                credentials={'extra': 'creds'})
Beispiel #5
0
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.get_default_redirect_uri.return_value = 'http://i.b./path'
     self.validator.authenticate_client.side_effect = self.set_client
     self.web = WebApplicationServer(self.validator,
                                     token_generator=self.inspect_client)
     self.mobile = MobileApplicationServer(
         self.validator, token_generator=self.inspect_client)
     self.legacy = LegacyApplicationServer(
         self.validator, token_generator=self.inspect_client)
     self.backend = BackendApplicationServer(
         self.validator, token_generator=self.inspect_client)
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
     self.web = WebApplicationServer(self.validator)
     self.mobile = MobileApplicationServer(self.validator)
     self.legacy = LegacyApplicationServer(self.validator)
     self.backend = BackendApplicationServer(self.validator)
Beispiel #7
0
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.get_default_redirect_uri.return_value = TestScopeHandling.DEFAULT_REDIRECT_URI
     self.validator.authenticate_client.side_effect = self.set_client
     self.web = WebApplicationServer(self.validator)
     self.mobile = MobileApplicationServer(self.validator)
     self.legacy = LegacyApplicationServer(self.validator)
     self.backend = BackendApplicationServer(self.validator)
Beispiel #8
0
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.get_default_redirect_uri.return_value = None
     self.validator.get_code_challenge.return_value = None
     self.web = WebApplicationServer(self.validator)
     self.mobile = MobileApplicationServer(self.validator)
     self.legacy = LegacyApplicationServer(self.validator)
     self.backend = BackendApplicationServer(self.validator)
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.is_pkce_required.return_value = False
     self.validator.get_code_challenge.return_value = None
     self.validator.get_default_redirect_uri.return_value = 'http://i.b./path'
     self.web = WebApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.mobile = MobileApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.legacy = LegacyApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.backend = BackendApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.token_uri = 'http://example.com/path'
     self.auth_uri = 'http://example.com/path?client_id=abc&response_type=token'
     # should be base64 but no added value in this unittest
     self.basicauth_client_creds = {"Authorization": "john:doe"}
     self.basicauth_client_id = {"Authorization": "john:"}
Beispiel #10
0
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.get_default_redirect_uri.return_value = 'http://i.b./path'
     self.validator.authenticate_client.side_effect = self.set_client
     self.web = WebApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.mobile = MobileApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.legacy = LegacyApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.backend = BackendApplicationServer(self.validator,
             token_generator=self.inspect_client)
 def setUp(self):
     self.validator = mock.MagicMock(spec=RequestValidator)
     self.validator.is_pkce_required.return_value = False
     self.validator.get_code_challenge.return_value = None
     self.validator.get_default_redirect_uri.return_value = 'http://i.b./path'
     self.web = WebApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.mobile = MobileApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.legacy = LegacyApplicationServer(self.validator,
             token_generator=self.inspect_client)
     self.backend = BackendApplicationServer(self.validator,
             token_generator=self.inspect_client)
Beispiel #12
0
    def setUp(self):
        super().setUp()
        self.oauth = BottleOAuth2(self.app)
        self.validator = mock.MagicMock()
        self.server = LegacyApplicationServer(self.validator)
        self.metadata_endpoint = MetadataEndpoint([self.server], claims={
            "issuer": "https://xx",
            "token_endpoint": "https://xx/token",
            "revocation_endpoint": "https://xx/revoke",
            "introspection_endpoint": "https://xx/tokeninfo"
        })

        self.oauth.initialize(self.metadata_endpoint)

        self.fake_response = ({}, "", "200 fooOK")
Beispiel #13
0
class LegacyAuthorizeHandler(tornado.web.RequestHandler):
    def initialize(self):
        self._token_endpoint = LegacyApplicationServer(LegacyValidator())
        self._error_uri = self.reverse_url('legacy-error')

    def post(self, *args, **kwargs):
        uri, http_method, body, headers = extract_params(self.request)

        try:
            headers, body, status = self._token_endpoint.create_token_response(uri, http_method, body, headers)
        except errors.FatalClientError as e:
            logger.error(e)
            self.redirect(self._error_uri)
        except errors.OAuth2Error as e:
            logger.error(e)
            self.redirect(self._error_uri)

        self.set_header('Content-Type', 'application/json')
        self.finish(body)
class ErrorResponseTest(TestCase):
    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = None
        self.web = WebApplicationServer(self.validator)
        self.mobile = MobileApplicationServer(self.validator)
        self.legacy = LegacyApplicationServer(self.validator)
        self.backend = BackendApplicationServer(self.validator)

    def test_invalid_redirect_uri(self):
        uri = 'https://example.com/authorize?response_type={0}&client_id=foo&redirect_uri=wrong'

        # Authorization code grant
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.web.validate_authorization_request,
                          uri.format('code'))
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.web.create_authorization_response,
                          uri.format('code'),
                          scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.mobile.validate_authorization_request,
                          uri.format('token'))
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.mobile.create_authorization_response,
                          uri.format('token'),
                          scopes=['foo'])

    def test_invalid_default_redirect_uri(self):
        uri = 'https://example.com/authorize?response_type={0}&client_id=foo'
        self.validator.get_default_redirect_uri.return_value = "wrong"

        # Authorization code grant
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.web.validate_authorization_request,
                          uri.format('code'))
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.web.create_authorization_response,
                          uri.format('code'),
                          scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.mobile.validate_authorization_request,
                          uri.format('token'))
        self.assertRaises(errors.InvalidRedirectURIError,
                          self.mobile.create_authorization_response,
                          uri.format('token'),
                          scopes=['foo'])

    def test_missing_redirect_uri(self):
        uri = 'https://example.com/authorize?response_type={0}&client_id=foo'

        # Authorization code grant
        self.assertRaises(errors.MissingRedirectURIError,
                          self.web.validate_authorization_request,
                          uri.format('code'))
        self.assertRaises(errors.MissingRedirectURIError,
                          self.web.create_authorization_response,
                          uri.format('code'),
                          scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.MissingRedirectURIError,
                          self.mobile.validate_authorization_request,
                          uri.format('token'))
        self.assertRaises(errors.MissingRedirectURIError,
                          self.mobile.create_authorization_response,
                          uri.format('token'),
                          scopes=['foo'])

    def test_mismatching_redirect_uri(self):
        uri = 'https://example.com/authorize?response_type={0}&client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback'

        # Authorization code grant
        self.validator.validate_redirect_uri.return_value = False
        self.assertRaises(errors.MismatchingRedirectURIError,
                          self.web.validate_authorization_request,
                          uri.format('code'))
        self.assertRaises(errors.MismatchingRedirectURIError,
                          self.web.create_authorization_response,
                          uri.format('code'),
                          scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.MismatchingRedirectURIError,
                          self.mobile.validate_authorization_request,
                          uri.format('token'))
        self.assertRaises(errors.MismatchingRedirectURIError,
                          self.mobile.create_authorization_response,
                          uri.format('token'),
                          scopes=['foo'])

    def test_missing_client_id(self):
        uri = 'https://example.com/authorize?response_type={0}&redirect_uri=https%3A%2F%2Fi.b%2Fback'

        # Authorization code grant
        self.validator.validate_redirect_uri.return_value = False
        self.assertRaises(errors.MissingClientIdError,
                          self.web.validate_authorization_request,
                          uri.format('code'))
        self.assertRaises(errors.MissingClientIdError,
                          self.web.create_authorization_response,
                          uri.format('code'),
                          scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.MissingClientIdError,
                          self.mobile.validate_authorization_request,
                          uri.format('token'))
        self.assertRaises(errors.MissingClientIdError,
                          self.mobile.create_authorization_response,
                          uri.format('token'),
                          scopes=['foo'])

    def test_invalid_client_id(self):
        uri = 'https://example.com/authorize?response_type={0}&client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback'

        # Authorization code grant
        self.validator.validate_client_id.return_value = False
        self.assertRaises(errors.InvalidClientIdError,
                          self.web.validate_authorization_request,
                          uri.format('code'))
        self.assertRaises(errors.InvalidClientIdError,
                          self.web.create_authorization_response,
                          uri.format('code'),
                          scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.InvalidClientIdError,
                          self.mobile.validate_authorization_request,
                          uri.format('token'))
        self.assertRaises(errors.InvalidClientIdError,
                          self.mobile.create_authorization_response,
                          uri.format('token'),
                          scopes=['foo'])

    def test_empty_parameter(self):
        uri = 'https://example.com/authorize?client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback&response_type=code&'

        # Authorization code grant
        self.assertRaises(errors.InvalidRequestFatalError,
                          self.web.validate_authorization_request, uri)

        # Implicit grant
        self.assertRaises(errors.InvalidRequestFatalError,
                          self.mobile.validate_authorization_request, uri)

    def test_invalid_request(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        token_uri = 'https://i.b/token'

        invalid_bodies = [
            # duplicate params
            'grant_type=authorization_code&client_id=nope&client_id=nope&code=foo'
        ]
        for body in invalid_bodies:
            _, body, _ = self.web.create_token_response(token_uri, body=body)
            self.assertEqual('invalid_request', json.loads(body)['error'])

        # Password credentials grant
        invalid_bodies = [
            # duplicate params
            'grant_type=password&username=foo&username=bar&password=baz'
            # missing username
            'grant_type=password&password=baz'
            # missing password
            'grant_type=password&username=foo'
        ]
        self.validator.authenticate_client.side_effect = self.set_client
        for body in invalid_bodies:
            _, body, _ = self.legacy.create_token_response(token_uri,
                                                           body=body)
            self.assertEqual('invalid_request', json.loads(body)['error'])

        # Client credentials grant
        invalid_bodies = [
            # duplicate params
            'grant_type=client_credentials&scope=foo&scope=bar'
        ]
        for body in invalid_bodies:
            _, body, _ = self.backend.create_token_response(token_uri,
                                                            body=body)
            self.assertEqual('invalid_request', json.loads(body)['error'])

    def test_invalid_request_duplicate_params(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        uri = 'https://i.b/auth?client_id=foo&client_id=bar&response_type={0}'
        description = 'Duplicate client_id parameter.'

        # Authorization code
        self.assertRaisesRegexp(errors.InvalidRequestFatalError, description,
                                self.web.validate_authorization_request,
                                uri.format('code'))
        self.assertRaisesRegexp(errors.InvalidRequestFatalError,
                                description,
                                self.web.create_authorization_response,
                                uri.format('code'),
                                scopes=['foo'])

        # Implicit grant
        self.assertRaisesRegexp(errors.InvalidRequestFatalError, description,
                                self.mobile.validate_authorization_request,
                                uri.format('token'))
        self.assertRaisesRegexp(errors.InvalidRequestFatalError,
                                description,
                                self.mobile.create_authorization_response,
                                uri.format('token'),
                                scopes=['foo'])

    def test_invalid_request_missing_response_type(self):

        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'

        uri = 'https://i.b/auth?client_id=foo'

        # Authorization code
        self.assertRaises(errors.MissingResponseTypeError,
                          self.web.validate_authorization_request,
                          uri.format('code'))
        h, _, s = self.web.create_authorization_response(uri, scopes=['foo'])
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        self.assertIn('error=invalid_request', h['Location'])

        # Implicit grant
        self.assertRaises(errors.MissingResponseTypeError,
                          self.mobile.validate_authorization_request,
                          uri.format('token'))
        h, _, s = self.mobile.create_authorization_response(uri,
                                                            scopes=['foo'])
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        self.assertIn('error=invalid_request', h['Location'])

    def test_unauthorized_client(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        self.validator.validate_grant_type.return_value = False
        self.validator.validate_response_type.return_value = False
        self.validator.authenticate_client.side_effect = self.set_client
        token_uri = 'https://i.b/token'

        # Authorization code grant
        self.assertRaises(errors.UnauthorizedClientError,
                          self.web.validate_authorization_request,
                          'https://i.b/auth?response_type=code&client_id=foo')
        _, body, _ = self.web.create_token_response(
            token_uri, body='grant_type=authorization_code&code=foo')
        self.assertEqual('unauthorized_client', json.loads(body)['error'])

        # Implicit grant
        self.assertRaises(
            errors.UnauthorizedClientError,
            self.mobile.validate_authorization_request,
            'https://i.b/auth?response_type=token&client_id=foo')

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(
            token_uri, body='grant_type=password&username=foo&password=bar')
        self.assertEqual('unauthorized_client', json.loads(body)['error'])

        # Client credentials grant
        _, body, _ = self.backend.create_token_response(
            token_uri, body='grant_type=client_credentials')
        self.assertEqual('unauthorized_client', json.loads(body)['error'])

    def test_access_denied(self):
        self.validator.authenticate_client.side_effect = self.set_client
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        self.validator.confirm_redirect_uri.return_value = False
        token_uri = 'https://i.b/token'
        # Authorization code grant
        _, body, _ = self.web.create_token_response(
            token_uri, body='grant_type=authorization_code&code=foo')
        self.assertEqual('invalid_request', json.loads(body)['error'])

    def test_access_denied_no_default_redirecturi(self):
        self.validator.authenticate_client.side_effect = self.set_client
        self.validator.get_default_redirect_uri.return_value = None
        token_uri = 'https://i.b/token'
        # Authorization code grant
        _, body, _ = self.web.create_token_response(
            token_uri, body='grant_type=authorization_code&code=foo')
        self.assertEqual('invalid_request', json.loads(body)['error'])

    def test_unsupported_response_type(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'

        # Authorization code grant
        self.assertRaises(errors.UnsupportedResponseTypeError,
                          self.web.validate_authorization_request,
                          'https://i.b/auth?response_type=foo&client_id=foo')

        # Implicit grant
        self.assertRaises(errors.UnsupportedResponseTypeError,
                          self.mobile.validate_authorization_request,
                          'https://i.b/auth?response_type=foo&client_id=foo')

    def test_invalid_scope(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        self.validator.validate_scopes.return_value = False
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.assertRaises(errors.InvalidScopeError,
                          self.web.validate_authorization_request,
                          'https://i.b/auth?response_type=code&client_id=foo')

        # Implicit grant
        self.assertRaises(
            errors.InvalidScopeError,
            self.mobile.validate_authorization_request,
            'https://i.b/auth?response_type=token&client_id=foo')

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(
            'https://i.b/token',
            body='grant_type=password&username=foo&password=bar')
        self.assertEqual('invalid_scope', json.loads(body)['error'])

        # Client credentials grant
        _, body, _ = self.backend.create_token_response(
            'https://i.b/token', body='grant_type=client_credentials')
        self.assertEqual('invalid_scope', json.loads(body)['error'])

    def test_server_error(self):
        def raise_error(*args, **kwargs):
            raise ValueError()

        self.validator.validate_client_id.side_effect = raise_error
        self.validator.authenticate_client.side_effect = raise_error
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'

        # Authorization code grant
        self.web.catch_errors = True
        _, _, s = self.web.create_authorization_response(
            'https://i.b/auth?client_id=foo&response_type=code',
            scopes=['foo'])
        self.assertEqual(s, 500)
        _, _, s = self.web.create_token_response(
            'https://i.b/token',
            body='grant_type=authorization_code&code=foo',
            scopes=['foo'])
        self.assertEqual(s, 500)

        # Implicit grant
        self.mobile.catch_errors = True
        _, _, s = self.mobile.create_authorization_response(
            'https://i.b/auth?client_id=foo&response_type=token',
            scopes=['foo'])
        self.assertEqual(s, 500)

        # Password credentials grant
        self.legacy.catch_errors = True
        _, _, s = self.legacy.create_token_response(
            'https://i.b/token',
            body='grant_type=password&username=foo&password=foo')
        self.assertEqual(s, 500)

        # Client credentials grant
        self.backend.catch_errors = True
        _, _, s = self.backend.create_token_response(
            'https://i.b/token', body='grant_type=client_credentials')
        self.assertEqual(s, 500)

    def test_temporarily_unavailable(self):
        # Authorization code grant
        self.web.available = False
        _, _, s = self.web.create_authorization_response(
            'https://i.b/auth?client_id=foo&response_type=code',
            scopes=['foo'])
        self.assertEqual(s, 503)
        _, _, s = self.web.create_token_response(
            'https://i.b/token',
            body='grant_type=authorization_code&code=foo',
            scopes=['foo'])
        self.assertEqual(s, 503)

        # Implicit grant
        self.mobile.available = False
        _, _, s = self.mobile.create_authorization_response(
            'https://i.b/auth?client_id=foo&response_type=token',
            scopes=['foo'])
        self.assertEqual(s, 503)

        # Password credentials grant
        self.legacy.available = False
        _, _, s = self.legacy.create_token_response(
            'https://i.b/token',
            body='grant_type=password&username=foo&password=foo')
        self.assertEqual(s, 503)

        # Client credentials grant
        self.backend.available = False
        _, _, s = self.backend.create_token_response(
            'https://i.b/token', body='grant_type=client_credentials')
        self.assertEqual(s, 503)

    def test_invalid_client(self):
        self.validator.authenticate_client.return_value = False
        self.validator.authenticate_client_id.return_value = False

        # Authorization code grant
        _, body, _ = self.web.create_token_response(
            'https://i.b/token', body='grant_type=authorization_code&code=foo')
        self.assertEqual('invalid_client', json.loads(body)['error'])

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(
            'https://i.b/token',
            body='grant_type=password&username=foo&password=bar')
        self.assertEqual('invalid_client', json.loads(body)['error'])

        # Client credentials grant
        _, body, _ = self.legacy.create_token_response(
            'https://i.b/token', body='grant_type=client_credentials')
        self.assertEqual('invalid_client', json.loads(body)['error'])

    def test_invalid_grant(self):
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.validator.validate_code.return_value = False
        _, body, _ = self.web.create_token_response(
            'https://i.b/token', body='grant_type=authorization_code&code=foo')
        self.assertEqual('invalid_grant', json.loads(body)['error'])

        # Password credentials grant
        self.validator.validate_user.return_value = False
        _, body, _ = self.legacy.create_token_response(
            'https://i.b/token',
            body='grant_type=password&username=foo&password=bar')
        self.assertEqual('invalid_grant', json.loads(body)['error'])

    def test_unsupported_grant_type(self):
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        _, body, _ = self.web.create_token_response(
            'https://i.b/token', body='grant_type=bar&code=foo')
        self.assertEqual('unsupported_grant_type', json.loads(body)['error'])

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(
            'https://i.b/token',
            body='grant_type=bar&username=foo&password=bar')
        self.assertEqual('unsupported_grant_type', json.loads(body)['error'])

        # Client credentials grant
        _, body, _ = self.backend.create_token_response('https://i.b/token',
                                                        body='grant_type=bar')
        self.assertEqual('unsupported_grant_type', json.loads(body)['error'])
class ClientAuthenticationTest(TestCase):

    def inspect_client(self, request, refresh_token=False):
        if not request.client or not request.client.client_id:
            raise ValueError()
        return 'abc'

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.is_pkce_required.return_value = False
        self.validator.get_code_challenge.return_value = None
        self.validator.get_default_redirect_uri.return_value = 'http://i.b./path'
        self.web = WebApplicationServer(self.validator,
                token_generator=self.inspect_client)
        self.mobile = MobileApplicationServer(self.validator,
                token_generator=self.inspect_client)
        self.legacy = LegacyApplicationServer(self.validator,
                token_generator=self.inspect_client)
        self.backend = BackendApplicationServer(self.validator,
                token_generator=self.inspect_client)
        self.token_uri = 'http://example.com/path'
        self.auth_uri = 'http://example.com/path?client_id=abc&response_type=token'
        # should be base64 but no added value in this unittest
        self.basicauth_client_creds = {"Authorization": "john:doe"}
        self.basicauth_client_id = {"Authorization": "john:"}

    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def set_client_id(self, client_id, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def basicauth_authenticate_client(self, request):
        assert "Authorization" in request.headers
        assert "john:doe" in request.headers["Authorization"]
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def test_client_id_authentication(self):
        token_uri = 'http://example.com/path'

        # authorization code grant
        self.validator.authenticate_client.return_value = False
        self.validator.authenticate_client_id.return_value = False
        _, body, _ = self.web.create_token_response(token_uri,
                body='grant_type=authorization_code&code=mock')
        self.assertEqual(json.loads(body)['error'], 'invalid_client')

        self.validator.authenticate_client_id.return_value = True
        self.validator.authenticate_client.side_effect = self.set_client
        _, body, _ = self.web.create_token_response(token_uri,
                body='grant_type=authorization_code&code=mock')
        self.assertIn('access_token', json.loads(body))

        # implicit grant
        auth_uri = 'http://example.com/path?client_id=abc&response_type=token'
        self.assertRaises(ValueError, self.mobile.create_authorization_response,
                auth_uri, scopes=['random'])

        self.validator.validate_client_id.side_effect = self.set_client_id
        h, _, s = self.mobile.create_authorization_response(auth_uri, scopes=['random'])
        self.assertEqual(302, s)
        self.assertIn('Location', h)
        self.assertIn('access_token', get_fragment_credentials(h['Location']))

    def test_basicauth_web(self):
        self.validator.authenticate_client.side_effect = self.basicauth_authenticate_client
        _, body, _ = self.web.create_token_response(
            self.token_uri,
            body='grant_type=authorization_code&code=mock',
            headers=self.basicauth_client_creds
        )
        self.assertIn('access_token', json.loads(body))

    def test_basicauth_legacy(self):
        self.validator.authenticate_client.side_effect = self.basicauth_authenticate_client
        _, body, _ = self.legacy.create_token_response(
            self.token_uri,
            body='grant_type=password&username=abc&password=secret',
            headers=self.basicauth_client_creds
        )
        self.assertIn('access_token', json.loads(body))

    def test_basicauth_backend(self):
        self.validator.authenticate_client.side_effect = self.basicauth_authenticate_client
        _, body, _ = self.backend.create_token_response(
            self.token_uri,
            body='grant_type=client_credentials',
            headers=self.basicauth_client_creds
        )
        self.assertIn('access_token', json.loads(body))

    def test_basicauth_revoke(self):
        self.validator.authenticate_client.side_effect = self.basicauth_authenticate_client

        # legacy or any other uses the same RevocationEndpoint
        _, body, status = self.legacy.create_revocation_response(
            self.token_uri,
            body='token=foobar',
            headers=self.basicauth_client_creds
        )
        self.assertEqual(status, 200, body)

    def test_basicauth_introspect(self):
        self.validator.authenticate_client.side_effect = self.basicauth_authenticate_client

        # legacy or any other uses the same IntrospectEndpoint
        _, body, status = self.legacy.create_introspect_response(
            self.token_uri,
            body='token=foobar',
            headers=self.basicauth_client_creds
        )
        self.assertEqual(status, 200, body)

    def test_custom_authentication(self):
        token_uri = 'http://example.com/path'

        # authorization code grant
        self.assertRaises(NotImplementedError,
                self.web.create_token_response, token_uri,
                body='grant_type=authorization_code&code=mock')

        # password grant
        self.validator.authenticate_client.return_value = True
        self.assertRaises(NotImplementedError,
                self.legacy.create_token_response, token_uri,
                body='grant_type=password&username=abc&password=secret')

        # client credentials grant
        self.validator.authenticate_client.return_value = True
        self.assertRaises(NotImplementedError,
                self.backend.create_token_response, token_uri,
                body='grant_type=client_credentials')
Beispiel #16
0
class ResourceOwnerAssociationTest(TestCase):

    auth_uri = 'http://example.com/path?client_id=abc'
    token_uri = 'http://example.com/path'

    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def set_user(self, client_id, code, client, request):
        request.user = '******'
        return True

    def set_user_from_username(self, username, password, client, request):
        request.user = '******'
        return True

    def set_user_from_credentials(self, request):
        request.user = '******'
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def inspect_client(self, request, refresh_token=False):
        if not request.user:
            raise ValueError()
        return 'abc'

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = 'http://i.b./path'
        self.validator.authenticate_client.side_effect = self.set_client
        self.web = WebApplicationServer(self.validator,
                                        token_generator=self.inspect_client)
        self.mobile = MobileApplicationServer(
            self.validator, token_generator=self.inspect_client)
        self.legacy = LegacyApplicationServer(
            self.validator, token_generator=self.inspect_client)
        self.backend = BackendApplicationServer(
            self.validator, token_generator=self.inspect_client)

    def test_web_application(self):
        # TODO: code generator + intercept test
        h, _, s = self.web.create_authorization_response(
            self.auth_uri + '&response_type=code',
            credentials={'user': '******'},
            scopes=['random'])
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        code = get_query_credentials(h['Location'])['code'][0]
        self.assertRaises(ValueError,
                          self.web.create_token_response,
                          self.token_uri,
                          body='grant_type=authorization_code&code=%s' % code)

        self.validator.validate_code.side_effect = self.set_user
        _, body, _ = self.web.create_token_response(
            self.token_uri,
            body='grant_type=authorization_code&code=%s' % code)
        self.assertEqual(json.loads(body)['access_token'], 'abc')

    def test_mobile_application(self):
        self.assertRaises(ValueError,
                          self.mobile.create_authorization_response,
                          self.auth_uri + '&response_type=token')

        h, _, s = self.mobile.create_authorization_response(
            self.auth_uri + '&response_type=token',
            credentials={'user': '******'},
            scopes=['random'])
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        self.assertEqual(
            get_fragment_credentials(h['Location'])['access_token'][0], 'abc')

    def test_legacy_application(self):
        body = 'grant_type=password&username=abc&password=secret'
        self.assertRaises(ValueError,
                          self.legacy.create_token_response,
                          self.token_uri,
                          body=body)

        self.validator.validate_user.side_effect = self.set_user_from_username
        _, body, _ = self.legacy.create_token_response(self.token_uri,
                                                       body=body)
        self.assertEqual(json.loads(body)['access_token'], 'abc')

    def test_backend_application(self):
        body = 'grant_type=client_credentials'
        self.assertRaises(ValueError,
                          self.backend.create_token_response,
                          self.token_uri,
                          body=body)

        self.validator.authenticate_client.side_effect = self.set_user_from_credentials
        _, body, _ = self.backend.create_token_response(self.token_uri,
                                                        body=body)
        self.assertEqual(json.loads(body)['access_token'], 'abc')
Beispiel #17
0
class TestScopeHandling(TestCase):

    DEFAULT_REDIRECT_URI = 'http://i.b./path'

    def set_scopes(self, scopes):
        def set_request_scopes(client_id, code, client, request):
            request.scopes = scopes
            return True

        return set_request_scopes

    def set_user(self, request):
        request.user = '******'
        request.client_id = 'bar'
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = TestScopeHandling.DEFAULT_REDIRECT_URI
        self.validator.authenticate_client.side_effect = self.set_client
        self.web = WebApplicationServer(self.validator)
        self.mobile = MobileApplicationServer(self.validator)
        self.legacy = LegacyApplicationServer(self.validator)
        self.backend = BackendApplicationServer(self.validator)

    def test_scope_extraction(self):
        scopes = (
            ('images', ['images']),
            ('images+videos', ['images', 'videos']),
            ('http%3A%2f%2fa.b%2fvideos', ['http://a.b/videos']),
            ('http%3A%2f%2fa.b%2fvideos+pics', ['http://a.b/videos', 'pics']),
            ('pics+http%3A%2f%2fa.b%2fvideos', ['pics', 'http://a.b/videos']),
            ('http%3A%2f%2fa.b%2fvideos+https%3A%2f%2fc.d%2Fsecret',
             ['http://a.b/videos', 'https://c.d/secret']),
        )

        uri = 'http://example.com/path?client_id=abc&scope=%s&response_type=%s'
        for scope, correct_scopes in scopes:
            scopes, _ = self.web.validate_authorization_request(
                uri % (scope, 'code'))
            self.assertItemsEqual(scopes, correct_scopes)
            scopes, _ = self.mobile.validate_authorization_request(
                uri % (scope, 'token'))
            self.assertItemsEqual(scopes, correct_scopes)

    def test_scope_preservation(self):
        scope = 'pics+http%3A%2f%2fa.b%2fvideos'
        decoded_scope = 'pics http://a.b/videos'
        auth_uri = 'http://example.com/path?client_id=abc&response_type='
        token_uri = 'http://example.com/path'

        # authorization grant
        h, _, s = self.web.create_authorization_response(
            auth_uri + 'code', scopes=decoded_scope.split(' '))
        self.validator.validate_code.side_effect = self.set_scopes(
            decoded_scope.split(' '))
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        code = get_query_credentials(h['Location'])['code'][0]
        _, body, _ = self.web.create_token_response(
            token_uri, body='grant_type=authorization_code&code=%s' % code)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

        # implicit grant
        h, _, s = self.mobile.create_authorization_response(
            auth_uri + 'token', scopes=decoded_scope.split(' '))
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        self.assertEqual(
            get_fragment_credentials(h['Location'])['scope'][0], decoded_scope)

        # resource owner password credentials grant
        body = 'grant_type=password&username=abc&password=secret&scope=%s'

        _, body, _ = self.legacy.create_token_response(token_uri,
                                                       body=body % scope)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

        # client credentials grant
        body = 'grant_type=client_credentials&scope=%s'
        self.validator.authenticate_client.side_effect = self.set_user
        _, body, _ = self.backend.create_token_response(token_uri,
                                                        body=body % scope)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

    def test_scope_changed(self):
        scope = 'pics+http%3A%2f%2fa.b%2fvideos'
        scopes = ['images', 'http://a.b/videos']
        decoded_scope = 'images http://a.b/videos'
        auth_uri = 'http://example.com/path?client_id=abc&response_type='
        token_uri = 'http://example.com/path'

        # authorization grant
        h, _, s = self.web.create_authorization_response(auth_uri + 'code',
                                                         scopes=scopes)
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        code = get_query_credentials(h['Location'])['code'][0]
        self.validator.validate_code.side_effect = self.set_scopes(scopes)
        _, body, _ = self.web.create_token_response(
            token_uri, body='grant_type=authorization_code&code=%s' % code)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

        # implicit grant
        self.validator.validate_scopes.side_effect = self.set_scopes(scopes)
        h, _, s = self.mobile.create_authorization_response(auth_uri + 'token',
                                                            scopes=scopes)
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        self.assertEqual(
            get_fragment_credentials(h['Location'])['scope'][0], decoded_scope)

        # resource owner password credentials grant
        self.validator.validate_scopes.side_effect = self.set_scopes(scopes)
        body = 'grant_type=password&username=abc&password=secret&scope=%s'
        _, body, _ = self.legacy.create_token_response(token_uri,
                                                       body=body % scope)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

        # client credentials grant
        self.validator.validate_scopes.side_effect = self.set_scopes(scopes)
        self.validator.authenticate_client.side_effect = self.set_user
        body = 'grant_type=client_credentials&scope=%s'
        _, body, _ = self.backend.create_token_response(token_uri,
                                                        body=body % scope)

        self.assertEqual(json.loads(body)['scope'], decoded_scope)

    def test_invalid_scope(self):
        scope = 'pics+http%3A%2f%2fa.b%2fvideos'
        auth_uri = 'http://example.com/path?client_id=abc&response_type='
        token_uri = 'http://example.com/path'

        self.validator.validate_scopes.return_value = False

        # authorization grant
        h, _, s = self.web.create_authorization_response(auth_uri + 'code',
                                                         scopes=['invalid'])
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        error = get_query_credentials(h['Location'])['error'][0]
        self.assertEqual(error, 'invalid_scope')

        # implicit grant
        h, _, s = self.mobile.create_authorization_response(auth_uri + 'token',
                                                            scopes=['invalid'])
        self.assertEqual(s, 302)
        self.assertIn('Location', h)
        error = get_fragment_credentials(h['Location'])['error'][0]
        self.assertEqual(error, 'invalid_scope')

        # resource owner password credentials grant
        body = 'grant_type=password&username=abc&password=secret&scope=%s'
        _, body, _ = self.legacy.create_token_response(token_uri,
                                                       body=body % scope)
        self.assertEqual(json.loads(body)['error'], 'invalid_scope')

        # client credentials grant
        self.validator.authenticate_client.side_effect = self.set_user
        body = 'grant_type=client_credentials&scope=%s'
        _, body, _ = self.backend.create_token_response(token_uri,
                                                        body=body % scope)
        self.assertEqual(json.loads(body)['error'], 'invalid_scope')
Beispiel #18
0
class ResourceOwnerAssociationTest(TestCase):

    auth_uri = 'http://example.com/path?client_id=abc'
    token_uri = 'http://example.com/path'

    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def set_user(self, client_id, code, client, request):
        request.user = '******'
        return True

    def set_user_from_username(self, username, password, client, request):
        request.user = '******'
        return True

    def set_user_from_credentials(self, request):
        request.user = '******'
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def inspect_client(self, request, refresh_token=False):
        if not request.user:
            raise ValueError()
        return 'abc'

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = 'http://i.b./path'
        self.validator.authenticate_client.side_effect = self.set_client
        self.web = WebApplicationServer(self.validator,
                token_generator=self.inspect_client)
        self.mobile = MobileApplicationServer(self.validator,
                token_generator=self.inspect_client)
        self.legacy = LegacyApplicationServer(self.validator,
                token_generator=self.inspect_client)
        self.backend = BackendApplicationServer(self.validator,
                token_generator=self.inspect_client)

    def test_web_application(self):
        # TODO: code generator + intercept test
        uri, _, _, _ = self.web.create_authorization_response(
                self.auth_uri + '&response_type=code',
                credentials={'user': '******'})
        code = get_query_credentials(uri)['code'][0]
        self.assertRaises(ValueError,
                self.web.create_token_response, self.token_uri,
                body='grant_type=authorization_code&code=%s' % code)

        self.validator.validate_code.side_effect = self.set_user
        _, _, body, _ = self.web.create_token_response(self.token_uri,
                body='grant_type=authorization_code&code=%s' % code)
        self.assertEqual(json.loads(body)['access_token'], 'abc')

    def test_mobile_application(self):
        self.assertRaises(ValueError,
                self.mobile.create_authorization_response,
                self.auth_uri + '&response_type=token')

        uri, _, _, _ = self.mobile.create_authorization_response(
                self.auth_uri + '&response_type=token',
                credentials={'user': '******'})
        self.assertEqual(get_fragment_credentials(uri)['access_token'][0], 'abc')

    def test_legacy_application(self):
        body = 'grant_type=password&username=abc&password=secret'
        self.assertRaises(ValueError,
                self.legacy.create_token_response,
                self.token_uri, body=body)

        self.validator.validate_user.side_effect = self.set_user_from_username
        _, _, body, _ = self.legacy.create_token_response(
                self.token_uri, body=body)
        self.assertEqual(json.loads(body)['access_token'], 'abc')

    def test_backend_application(self):
        body = 'grant_type=client_credentials'
        self.assertRaises(ValueError,
                self.backend.create_token_response,
                self.token_uri, body=body)

        self.validator.authenticate_client.side_effect = self.set_user_from_credentials
        _, _, body, _ = self.backend.create_token_response(
                self.token_uri, body=body)
        self.assertEqual(json.loads(body)['access_token'], 'abc')
Beispiel #19
0
class TestScopeHandling(TestCase):

    DEFAULT_REDIRECT_URI = 'http://i.b./path'

    def set_scopes(self, scopes):
        def set_request_scopes(client_id, code, client, request):
            request.scopes = scopes
            return True
        return set_request_scopes

    def set_user(self, request):
        request.user = '******'
        request.client_id = 'bar'
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = TestScopeHandling.DEFAULT_REDIRECT_URI
        self.validator.authenticate_client.side_effect = self.set_client
        self.web = WebApplicationServer(self.validator)
        self.mobile = MobileApplicationServer(self.validator)
        self.legacy = LegacyApplicationServer(self.validator)
        self.backend = BackendApplicationServer(self.validator)

    def test_scope_extraction(self):
        scopes = (
            ('images', ['images']),
            ('images+videos', ['images', 'videos']),
            ('http%3A%2f%2fa.b%2fvideos', ['http://a.b/videos']),
            ('http%3A%2f%2fa.b%2fvideos+pics', ['http://a.b/videos', 'pics']),
            ('pics+http%3A%2f%2fa.b%2fvideos', ['pics', 'http://a.b/videos']),
            ('http%3A%2f%2fa.b%2fvideos+https%3A%2f%2fc.d%2Fsecret', ['http://a.b/videos', 'https://c.d/secret']),
        )

        uri = 'http://example.com/path?client_id=abc&scope=%s&response_type=%s'
        for scope, correct_scopes in scopes:
            scopes, _ = self.web.validate_authorization_request(
                    uri % (scope, 'code'))
            self.assertItemsEqual(scopes, correct_scopes)
            scopes, _ = self.mobile.validate_authorization_request(
                    uri % (scope, 'token'))
            self.assertItemsEqual(scopes, correct_scopes)

    def test_scope_preservation(self):
        scope = 'pics+http%3A%2f%2fa.b%2fvideos'
        correct_scope = 'pics http%3A%2f%2fa.b%2fvideos'
        decoded_scope = 'pics http://a.b/videos'
        scopes = ['pics', 'http%3A%2f%2fa.b%2fvideos']
        auth_uri = 'http://example.com/path?client_id=abc&scope=%s&%s'
        token_uri = 'http://example.com/path'

        # authorization grant
        uri, _, _, _ = self.web.create_authorization_response(
                auth_uri % (scope, 'response_type=code'))
        self.validator.validate_code.side_effect = self.set_scopes(scopes)
        code = get_query_credentials(uri)['code'][0]
        _, _, body, _ = self.web.create_token_response(token_uri,
                body='grant_type=authorization_code&code=%s' % code)
        self.assertEqual(json.loads(body)['scope'], correct_scope)

        # implicit grant
        uri, _, _, _ = self.mobile.create_authorization_response(
                auth_uri % (scope, 'response_type=token'))
        self.assertEqual(get_fragment_credentials(uri)['scope'][0], decoded_scope)

        # resource owner password credentials grant
        body = 'grant_type=password&username=abc&password=secret&scope=%s'
        _, _, body, _ = self.legacy.create_token_response(token_uri,
                body=body % scope)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

        # client credentials grant
        body = 'grant_type=client_credentials&scope=%s'
        self.validator.authenticate_client.side_effect = self.set_user
        _, _, body, _ = self.backend.create_token_response(token_uri,
                body=body % scope)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

    def test_scope_changed(self):
        scope = 'pics+http%3A%2f%2fa.b%2fvideos'
        scopes = ['images', 'http://a.b/videos']
        decoded_scope = 'images http://a.b/videos'
        auth_uri = 'http://example.com/path?client_id=abc&scope=%s&%s'
        token_uri = 'http://example.com/path'

        # authorization grant
        uri, _, _, _ = self.web.create_authorization_response(
                auth_uri % (scope, 'response_type=code'))
        code = get_query_credentials(uri)['code'][0]
        self.validator.validate_code.side_effect = self.set_scopes(scopes)
        _, _, body, _ = self.web.create_token_response(token_uri,
                body='grant_type=authorization_code&code=%s' % code)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

        # implicit grant
        self.validator.validate_scopes.side_effect = self.set_scopes(scopes)
        uri, _, _, _ = self.mobile.create_authorization_response(
                auth_uri % (scope, 'response_type=token'))
        self.assertEqual(get_fragment_credentials(uri)['scope'][0], decoded_scope)

        # resource owner password credentials grant
        self.validator.validate_scopes.side_effect = self.set_scopes(scopes)
        body = 'grant_type=password&username=abc&password=secret&scope=%s'
        _, _, body, _ = self.legacy.create_token_response(token_uri,
                body=body % scope)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

        # client credentials grant
        self.validator.validate_scopes.side_effect = self.set_scopes(scopes)
        self.validator.authenticate_client.side_effect = self.set_user
        body = 'grant_type=client_credentials&scope=%s'
        _, _, body, _ = self.backend.create_token_response(token_uri,
                body=body % scope)
        self.assertEqual(json.loads(body)['scope'], decoded_scope)

    def test_invalid_scope(self):
        scope = 'pics+http%3A%2f%2fa.b%2fvideos'
        auth_uri = 'http://example.com/path?client_id=abc&scope=%s&%s'
        token_uri = 'http://example.com/path'

        self.validator.validate_scopes.return_value = False

        # authorization grant
        uri, _, _, _ = self.web.create_authorization_response(
                auth_uri % (scope, 'response_type=code'))
        error = get_query_credentials(uri)['error'][0]
        self.assertEqual(error, 'invalid_scope')

        # implicit grant
        uri, _, _, _ = self.mobile.create_authorization_response(
                auth_uri % (scope, 'response_type=token'))
        error = get_fragment_credentials(uri)['error'][0]
        self.assertEqual(error, 'invalid_scope')

        # resource owner password credentials grant
        body = 'grant_type=password&username=abc&password=secret&scope=%s'
        _, _, body, _ = self.legacy.create_token_response(token_uri,
                body=body % scope)
        self.assertEqual(json.loads(body)['error'], 'invalid_scope')

        # client credentials grant
        self.validator.authenticate_client.side_effect = self.set_user
        body = 'grant_type=client_credentials&scope=%s'
        _, _, body, _ = self.backend.create_token_response(token_uri,
                body=body % scope)
        self.assertEqual(json.loads(body)['error'], 'invalid_scope')
Beispiel #20
0
class ErrorResponseTest(TestCase):

    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = 'mocked'
        return True

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = None
        self.web = WebApplicationServer(self.validator)
        self.mobile = MobileApplicationServer(self.validator)
        self.legacy = LegacyApplicationServer(self.validator)
        self.backend = BackendApplicationServer(self.validator)

    def test_invalid_redirect_uri(self):
        uri = 'https://example.com/authorize?client_id=foo&redirect_uri=wrong'
        # Authorization code grant
        self.assertRaises(errors.InvalidRedirectURIError,
                self.web.validate_authorization_request, uri)
        self.assertRaises(errors.InvalidRedirectURIError,
                self.web.create_authorization_response, uri, scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.InvalidRedirectURIError,
                self.mobile.validate_authorization_request, uri)
        self.assertRaises(errors.InvalidRedirectURIError,
                self.mobile.create_authorization_response, uri, scopes=['foo'])

    def test_missing_redirect_uri(self):
        uri = 'https://example.com/authorize?client_id=foo'
        # Authorization code grant
        self.assertRaises(errors.MissingRedirectURIError,
                self.web.validate_authorization_request, uri)
        self.assertRaises(errors.MissingRedirectURIError,
                self.web.create_authorization_response, uri, scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.MissingRedirectURIError,
                self.mobile.validate_authorization_request, uri)
        self.assertRaises(errors.MissingRedirectURIError,
                self.mobile.create_authorization_response, uri, scopes=['foo'])

    def test_mismatching_redirect_uri(self):
        uri = 'https://example.com/authorize?client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback'
        # Authorization code grant
        self.validator.validate_redirect_uri.return_value = False
        self.assertRaises(errors.MismatchingRedirectURIError,
                self.web.validate_authorization_request, uri)
        self.assertRaises(errors.MismatchingRedirectURIError,
                self.web.create_authorization_response, uri, scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.MismatchingRedirectURIError,
                self.mobile.validate_authorization_request, uri)
        self.assertRaises(errors.MismatchingRedirectURIError,
                self.mobile.create_authorization_response, uri, scopes=['foo'])

    def test_missing_client_id(self):
        uri = 'https://example.com/authorize?redirect_uri=https%3A%2F%2Fi.b%2Fback'
        # Authorization code grant
        self.validator.validate_redirect_uri.return_value = False
        self.assertRaises(errors.MissingClientIdError,
                self.web.validate_authorization_request, uri)
        self.assertRaises(errors.MissingClientIdError,
                self.web.create_authorization_response, uri, scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.MissingClientIdError,
                self.mobile.validate_authorization_request, uri)
        self.assertRaises(errors.MissingClientIdError,
                self.mobile.create_authorization_response, uri, scopes=['foo'])

    def test_invalid_client_id(self):
        uri = 'https://example.com/authorize?client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback'
        # Authorization code grant
        self.validator.validate_client_id.return_value = False
        self.assertRaises(errors.InvalidClientIdError,
                self.web.validate_authorization_request, uri)
        self.assertRaises(errors.InvalidClientIdError,
                self.web.create_authorization_response, uri, scopes=['foo'])

        # Implicit grant
        self.assertRaises(errors.InvalidClientIdError,
                self.mobile.validate_authorization_request, uri)
        self.assertRaises(errors.InvalidClientIdError,
                self.mobile.create_authorization_response, uri, scopes=['foo'])

    def test_invalid_request(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        token_uri = 'https://i.b/token'
        invalid_uris = [
            # Duplicate parameters
            'https://i.b/auth?client_id=foo&client_id=bar&response_type={0}',
            # Missing response type
            'https://i.b/auth?client_id=foo',
        ]

        # Authorization code grant
        for uri in invalid_uris:
            self.assertRaises(errors.InvalidRequestError,
                    self.web.validate_authorization_request,
                    uri.format('code'))
            url, _, _, _ = self.web.create_authorization_response(
                    uri.format('code'), scopes=['foo'])
            self.assertIn('error=invalid_request', url)
        invalid_bodies = [
            # duplicate params
            'grant_type=authorization_code&client_id=nope&client_id=nope&code=foo'
        ]
        for body in invalid_bodies:
            _, _, body, _ = self.web.create_token_response(token_uri,
                    body=body)
            self.assertEqual('invalid_request', json.loads(body)['error'])

        # Implicit grant
        for uri in invalid_uris:
            self.assertRaises(errors.InvalidRequestError,
                    self.mobile.validate_authorization_request,
                    uri.format('token'))
            url, _, _, _ = self.mobile.create_authorization_response(
                    uri.format('token'), scopes=['foo'])
            self.assertIn('error=invalid_request', url)

        # Password credentials grant
        invalid_bodies = [
            # duplicate params
            'grant_type=password&username=foo&username=bar&password=baz'
            # missing username
            'grant_type=password&password=baz'
            # missing password
            'grant_type=password&username=foo'
        ]
        self.validator.authenticate_client.side_effect = self.set_client
        for body in invalid_bodies:
            _, _, body, _ = self.legacy.create_token_response(token_uri,
                    body=body)
            self.assertEqual('invalid_request', json.loads(body)['error'])

        # Client credentials grant
        invalid_bodies = [
            # duplicate params
            'grant_type=client_credentials&scope=foo&scope=bar'
        ]
        for body in invalid_bodies:
            _, _, body, _ = self.backend.create_token_response(token_uri,
                    body=body)
            self.assertEqual('invalid_request', json.loads(body)['error'])

    def test_unauthorized_client(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        self.validator.validate_grant_type.return_value = False
        self.validator.validate_response_type.return_value = False
        self.validator.authenticate_client.side_effect = self.set_client
        token_uri = 'https://i.b/token'

        # Authorization code grant
        self.assertRaises(errors.UnauthorizedClientError,
                self.web.validate_authorization_request,
                'https://i.b/auth?response_type=code&client_id=foo')
        _, _, body, _ = self.web.create_token_response(token_uri,
                body='grant_type=authorization_code&code=foo')
        self.assertEqual('unauthorized_client', json.loads(body)['error'])

        # Implicit grant
        self.assertRaises(errors.UnauthorizedClientError,
                self.mobile.validate_authorization_request,
                'https://i.b/auth?response_type=token&client_id=foo')

        # Password credentials grant
        _, _, body, _ = self.legacy.create_token_response(token_uri,
                body='grant_type=password&username=foo&password=bar')
        self.assertEqual('unauthorized_client', json.loads(body)['error'])

        # Client credentials grant
        _, _, body, _ = self.backend.create_token_response(token_uri,
                body='grant_type=client_credentials')
        self.assertEqual('unauthorized_client', json.loads(body)['error'])

    def test_access_denied(self):
        self.validator.authenticate_client.side_effect = self.set_client
        self.validator.confirm_redirect_uri.return_value = False
        token_uri = 'https://i.b/token'
        # Authorization code grant
        _, _, body, _ = self.web.create_token_response(token_uri,
                body='grant_type=authorization_code&code=foo')
        self.assertEqual('access_denied', json.loads(body)['error'])

    def test_unsupported_response_type(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'

        # Authorization code grant
        self.assertRaises(errors.UnsupportedResponseTypeError,
                self.web.validate_authorization_request,
                'https://i.b/auth?response_type=foo&client_id=foo')

        # Implicit grant
        self.assertRaises(errors.UnsupportedResponseTypeError,
                self.mobile.validate_authorization_request,
                'https://i.b/auth?response_type=foo&client_id=foo')

    def test_invalid_scope(self):
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'
        self.validator.validate_scopes.return_value = False
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.assertRaises(errors.InvalidScopeError,
                self.web.validate_authorization_request,
                'https://i.b/auth?response_type=code&client_id=foo')

        # Implicit grant
        self.assertRaises(errors.InvalidScopeError,
                self.mobile.validate_authorization_request,
                'https://i.b/auth?response_type=token&client_id=foo')

        # Password credentials grant
        _, _, body, _ = self.legacy.create_token_response(
                'https://i.b/token',
                body='grant_type=password&username=foo&password=bar')
        self.assertEqual('invalid_scope', json.loads(body)['error'])

        # Client credentials grant
        _, _, body, _ = self.backend.create_token_response(
                'https://i.b/token',
                body='grant_type=client_credentials')
        self.assertEqual('invalid_scope', json.loads(body)['error'])

    def test_server_error(self):
        def raise_error(*args, **kwargs):
            raise ValueError()

        self.validator.validate_client_id.side_effect = raise_error
        self.validator.authenticate_client.side_effect = raise_error
        self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb'

        # Authorization code grant
        self.web.catch_errors = True
        _, _, _, s = self.web.create_authorization_response(
                'https://i.b/auth?client_id=foo&response_type=code',
                scopes=['foo'])
        self.assertEqual(s, 500)
        _, _, _, s = self.web.create_token_response(
                'https://i.b/token',
                body='grant_type=authorization_code&code=foo',
                scopes=['foo'])
        self.assertEqual(s, 500)

        # Implicit grant
        self.mobile.catch_errors = True
        _, _, _, s = self.mobile.create_authorization_response(
                'https://i.b/auth?client_id=foo&response_type=token',
                scopes=['foo'])
        self.assertEqual(s, 500)

        # Password credentials grant
        self.legacy.catch_errors = True
        _, _, _, s = self.legacy.create_token_response(
                'https://i.b/token',
                body='grant_type=password&username=foo&password=foo')
        self.assertEqual(s, 500)

        # Client credentials grant
        self.backend.catch_errors = True
        _, _, _, s = self.backend.create_token_response(
                'https://i.b/token',
                body='grant_type=client_credentials')
        self.assertEqual(s, 500)

    def test_temporarily_unavailable(self):
        # Authorization code grant
        self.web.available = False
        _, _, _, s = self.web.create_authorization_response(
                'https://i.b/auth?client_id=foo&response_type=code',
                scopes=['foo'])
        self.assertEqual(s, 503)
        _, _, _, s = self.web.create_token_response(
                'https://i.b/token',
                body='grant_type=authorization_code&code=foo',
                scopes=['foo'])
        self.assertEqual(s, 503)

        # Implicit grant
        self.mobile.available = False
        _, _, _, s = self.mobile.create_authorization_response(
                'https://i.b/auth?client_id=foo&response_type=token',
                scopes=['foo'])
        self.assertEqual(s, 503)

        # Password credentials grant
        self.legacy.available = False
        _, _, _, s = self.legacy.create_token_response(
                'https://i.b/token',
                body='grant_type=password&username=foo&password=foo')
        self.assertEqual(s, 503)

        # Client credentials grant
        self.backend.available = False
        _, _, _, s = self.backend.create_token_response(
                'https://i.b/token',
                body='grant_type=client_credentials')
        self.assertEqual(s, 503)

    def test_invalid_client(self):
        self.validator.authenticate_client.return_value = False
        self.validator.authenticate_client_id.return_value = False

        # Authorization code grant
        _, _, body, _ = self.web.create_token_response('https://i.b/token',
                body='grant_type=authorization_code&code=foo')
        self.assertEqual('invalid_client', json.loads(body)['error'])

        # Password credentials grant
        _, _, body, _ = self.legacy.create_token_response('https://i.b/token',
                body='grant_type=password&username=foo&password=bar')
        self.assertEqual('invalid_client', json.loads(body)['error'])

        # Client credentials grant
        _, _, body, _ = self.legacy.create_token_response('https://i.b/token',
                body='grant_type=client_credentials')
        self.assertEqual('invalid_client', json.loads(body)['error'])

    def test_invalid_grant(self):
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.validator.validate_code.return_value = False
        _, _, body, _ = self.web.create_token_response('https://i.b/token',
                body='grant_type=authorization_code&code=foo')
        self.assertEqual('invalid_grant', json.loads(body)['error'])

        # Password credentials grant
        self.validator.validate_user.return_value = False
        _, _, body, _ = self.legacy.create_token_response('https://i.b/token',
                body='grant_type=password&username=foo&password=bar')
        self.assertEqual('invalid_grant', json.loads(body)['error'])

    def test_unsupported_grant_type(self):
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        _, _, body, _ = self.web.create_token_response('https://i.b/token',
                body='grant_type=bar&code=foo')
        self.assertEqual('unsupported_grant_type', json.loads(body)['error'])

        # Password credentials grant
        _, _, body, _ = self.legacy.create_token_response('https://i.b/token',
                body='grant_type=bar&username=foo&password=bar')
        self.assertEqual('unsupported_grant_type', json.loads(body)['error'])

        # Client credentials grant
        _, _, body, _ = self.backend.create_token_response('https://i.b/token',
                body='grant_type=bar')
        self.assertEqual('unsupported_grant_type', json.loads(body)['error'])
Beispiel #21
0
 def initialize(self):
     self._token_endpoint = LegacyApplicationServer(LegacyValidator())
     self._error_uri = self.reverse_url('legacy-error')
Beispiel #22
0
 def initialize(self):
     # 初始化 oauth2 后端服务
     self._refresh_endpoint = LegacyApplicationServer(LegacyValidator())
     self._error_uri = self.reverse_url('legacy-error')
Beispiel #23
0
                'expiration'] > datetime.now().timestamp()

        def validate_refresh_token(self, refresh_token, client, request, *args,
                                   **kwargs):
            """Ensure the Bearer token is valid and authorized access to scopes."""
            for t in _tokens.values():
                if t['refresh_token'] == refresh_token:
                    return True
            return False

        def get_original_scopes(self, refresh_token, request, *args, **kwargs):
            """Get the list of scopes associated with the refresh token."""
            return []

    validator = SimpleValidator()
    oauth_server = LegacyApplicationServer(
        validator, token_expires_in=QGIS_SERVER_OAUTH2_TOKEN_EXPIRES_IN)

    class OAuth2Filter(QgsServerFilter):
        """This filter provides testing endpoint for OAuth2 Resource Owner Grant Flow

        Available endpoints:
        - /token (returns a new access_token),
                 optionally specify an expiration time in seconds with ?ttl=<int>
        - /refresh (returns a new access_token from a refresh token),
                 optionally specify an expiration time in seconds with ?ttl=<int>
        - /result (check the Bearer token and returns a short sentence if it validates)
        """
        def responseComplete(self):

            handler = self.serverInterface().requestHandler()
Beispiel #24
0
class ErrorResponseTest(TestCase):
    def set_client(self, request):
        request.client = mock.MagicMock()
        request.client.client_id = "mocked"
        return True

    def setUp(self):
        self.validator = mock.MagicMock(spec=RequestValidator)
        self.validator.get_default_redirect_uri.return_value = None
        self.web = WebApplicationServer(self.validator)
        self.mobile = MobileApplicationServer(self.validator)
        self.legacy = LegacyApplicationServer(self.validator)
        self.backend = BackendApplicationServer(self.validator)

    def test_invalid_redirect_uri(self):
        uri = "https://example.com/authorize?client_id=foo&redirect_uri=wrong"
        # Authorization code grant
        self.assertRaises(errors.InvalidRedirectURIError, self.web.validate_authorization_request, uri)
        self.assertRaises(errors.InvalidRedirectURIError, self.web.create_authorization_response, uri, scopes=["foo"])

        # Implicit grant
        self.assertRaises(errors.InvalidRedirectURIError, self.mobile.validate_authorization_request, uri)
        self.assertRaises(
            errors.InvalidRedirectURIError, self.mobile.create_authorization_response, uri, scopes=["foo"]
        )

    def test_missing_redirect_uri(self):
        uri = "https://example.com/authorize?client_id=foo"
        # Authorization code grant
        self.assertRaises(errors.MissingRedirectURIError, self.web.validate_authorization_request, uri)
        self.assertRaises(errors.MissingRedirectURIError, self.web.create_authorization_response, uri, scopes=["foo"])

        # Implicit grant
        self.assertRaises(errors.MissingRedirectURIError, self.mobile.validate_authorization_request, uri)
        self.assertRaises(
            errors.MissingRedirectURIError, self.mobile.create_authorization_response, uri, scopes=["foo"]
        )

    def test_mismatching_redirect_uri(self):
        uri = "https://example.com/authorize?client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback"
        # Authorization code grant
        self.validator.validate_redirect_uri.return_value = False
        self.assertRaises(errors.MismatchingRedirectURIError, self.web.validate_authorization_request, uri)
        self.assertRaises(
            errors.MismatchingRedirectURIError, self.web.create_authorization_response, uri, scopes=["foo"]
        )

        # Implicit grant
        self.assertRaises(errors.MismatchingRedirectURIError, self.mobile.validate_authorization_request, uri)
        self.assertRaises(
            errors.MismatchingRedirectURIError, self.mobile.create_authorization_response, uri, scopes=["foo"]
        )

    def test_missing_client_id(self):
        uri = "https://example.com/authorize?redirect_uri=https%3A%2F%2Fi.b%2Fback"
        # Authorization code grant
        self.validator.validate_redirect_uri.return_value = False
        self.assertRaises(errors.MissingClientIdError, self.web.validate_authorization_request, uri)
        self.assertRaises(errors.MissingClientIdError, self.web.create_authorization_response, uri, scopes=["foo"])

        # Implicit grant
        self.assertRaises(errors.MissingClientIdError, self.mobile.validate_authorization_request, uri)
        self.assertRaises(errors.MissingClientIdError, self.mobile.create_authorization_response, uri, scopes=["foo"])

    def test_invalid_client_id(self):
        uri = "https://example.com/authorize?client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback"
        # Authorization code grant
        self.validator.validate_client_id.return_value = False
        self.assertRaises(errors.InvalidClientIdError, self.web.validate_authorization_request, uri)
        self.assertRaises(errors.InvalidClientIdError, self.web.create_authorization_response, uri, scopes=["foo"])

        # Implicit grant
        self.assertRaises(errors.InvalidClientIdError, self.mobile.validate_authorization_request, uri)
        self.assertRaises(errors.InvalidClientIdError, self.mobile.create_authorization_response, uri, scopes=["foo"])

    def test_empty_parameter(self):
        uri = "https://example.com/authorize?client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback&response_type=code&"

        # Authorization code grant
        self.assertRaises(errors.InvalidRequestError, self.web.validate_authorization_request, uri)

        # Implicit grant
        self.assertRaises(errors.InvalidRequestError, self.mobile.validate_authorization_request, uri)

    def test_invalid_request(self):
        self.validator.get_default_redirect_uri.return_value = "https://i.b/cb"
        token_uri = "https://i.b/token"
        invalid_uris = [
            # Duplicate parameters
            "https://i.b/auth?client_id=foo&client_id=bar&response_type={0}",
            # Missing response type
            "https://i.b/auth?client_id=foo",
        ]

        # Authorization code grant
        for uri in invalid_uris:
            self.assertRaises(errors.InvalidRequestError, self.web.validate_authorization_request, uri.format("code"))
            h, _, s = self.web.create_authorization_response(uri.format("code"), scopes=["foo"])
            self.assertEqual(s, 302)
            self.assertIn("Location", h)
            self.assertIn("error=invalid_request", h["Location"])
        invalid_bodies = [
            # duplicate params
            "grant_type=authorization_code&client_id=nope&client_id=nope&code=foo"
        ]
        for body in invalid_bodies:
            _, body, _ = self.web.create_token_response(token_uri, body=body)
            self.assertEqual("invalid_request", json.loads(body)["error"])

        # Implicit grant
        for uri in invalid_uris:
            self.assertRaises(
                errors.InvalidRequestError, self.mobile.validate_authorization_request, uri.format("token")
            )
            h, _, s = self.mobile.create_authorization_response(uri.format("token"), scopes=["foo"])
            self.assertEqual(s, 302)
            self.assertIn("Location", h)
            self.assertIn("error=invalid_request", h["Location"])

        # Password credentials grant
        invalid_bodies = [
            # duplicate params
            "grant_type=password&username=foo&username=bar&password=baz"
            # missing username
            "grant_type=password&password=baz"
            # missing password
            "grant_type=password&username=foo"
        ]
        self.validator.authenticate_client.side_effect = self.set_client
        for body in invalid_bodies:
            _, body, _ = self.legacy.create_token_response(token_uri, body=body)
            self.assertEqual("invalid_request", json.loads(body)["error"])

        # Client credentials grant
        invalid_bodies = [
            # duplicate params
            "grant_type=client_credentials&scope=foo&scope=bar"
        ]
        for body in invalid_bodies:
            _, body, _ = self.backend.create_token_response(token_uri, body=body)
            self.assertEqual("invalid_request", json.loads(body)["error"])

    def test_unauthorized_client(self):
        self.validator.get_default_redirect_uri.return_value = "https://i.b/cb"
        self.validator.validate_grant_type.return_value = False
        self.validator.validate_response_type.return_value = False
        self.validator.authenticate_client.side_effect = self.set_client
        token_uri = "https://i.b/token"

        # Authorization code grant
        self.assertRaises(
            errors.UnauthorizedClientError,
            self.web.validate_authorization_request,
            "https://i.b/auth?response_type=code&client_id=foo",
        )
        _, body, _ = self.web.create_token_response(token_uri, body="grant_type=authorization_code&code=foo")
        self.assertEqual("unauthorized_client", json.loads(body)["error"])

        # Implicit grant
        self.assertRaises(
            errors.UnauthorizedClientError,
            self.mobile.validate_authorization_request,
            "https://i.b/auth?response_type=token&client_id=foo",
        )

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(token_uri, body="grant_type=password&username=foo&password=bar")
        self.assertEqual("unauthorized_client", json.loads(body)["error"])

        # Client credentials grant
        _, body, _ = self.backend.create_token_response(token_uri, body="grant_type=client_credentials")
        self.assertEqual("unauthorized_client", json.loads(body)["error"])

    def test_access_denied(self):
        self.validator.authenticate_client.side_effect = self.set_client
        self.validator.confirm_redirect_uri.return_value = False
        token_uri = "https://i.b/token"
        # Authorization code grant
        _, body, _ = self.web.create_token_response(token_uri, body="grant_type=authorization_code&code=foo")
        self.assertEqual("access_denied", json.loads(body)["error"])

    def test_unsupported_response_type(self):
        self.validator.get_default_redirect_uri.return_value = "https://i.b/cb"

        # Authorization code grant
        self.assertRaises(
            errors.UnsupportedResponseTypeError,
            self.web.validate_authorization_request,
            "https://i.b/auth?response_type=foo&client_id=foo",
        )

        # Implicit grant
        self.assertRaises(
            errors.UnsupportedResponseTypeError,
            self.mobile.validate_authorization_request,
            "https://i.b/auth?response_type=foo&client_id=foo",
        )

    def test_invalid_scope(self):
        self.validator.get_default_redirect_uri.return_value = "https://i.b/cb"
        self.validator.validate_scopes.return_value = False
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.assertRaises(
            errors.InvalidScopeError,
            self.web.validate_authorization_request,
            "https://i.b/auth?response_type=code&client_id=foo",
        )

        # Implicit grant
        self.assertRaises(
            errors.InvalidScopeError,
            self.mobile.validate_authorization_request,
            "https://i.b/auth?response_type=token&client_id=foo",
        )

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(
            "https://i.b/token", body="grant_type=password&username=foo&password=bar"
        )
        self.assertEqual("invalid_scope", json.loads(body)["error"])

        # Client credentials grant
        _, body, _ = self.backend.create_token_response("https://i.b/token", body="grant_type=client_credentials")
        self.assertEqual("invalid_scope", json.loads(body)["error"])

    def test_server_error(self):
        def raise_error(*args, **kwargs):
            raise ValueError()

        self.validator.validate_client_id.side_effect = raise_error
        self.validator.authenticate_client.side_effect = raise_error
        self.validator.get_default_redirect_uri.return_value = "https://i.b/cb"

        # Authorization code grant
        self.web.catch_errors = True
        _, _, s = self.web.create_authorization_response(
            "https://i.b/auth?client_id=foo&response_type=code", scopes=["foo"]
        )
        self.assertEqual(s, 500)
        _, _, s = self.web.create_token_response(
            "https://i.b/token", body="grant_type=authorization_code&code=foo", scopes=["foo"]
        )
        self.assertEqual(s, 500)

        # Implicit grant
        self.mobile.catch_errors = True
        _, _, s = self.mobile.create_authorization_response(
            "https://i.b/auth?client_id=foo&response_type=token", scopes=["foo"]
        )
        self.assertEqual(s, 500)

        # Password credentials grant
        self.legacy.catch_errors = True
        _, _, s = self.legacy.create_token_response(
            "https://i.b/token", body="grant_type=password&username=foo&password=foo"
        )
        self.assertEqual(s, 500)

        # Client credentials grant
        self.backend.catch_errors = True
        _, _, s = self.backend.create_token_response("https://i.b/token", body="grant_type=client_credentials")
        self.assertEqual(s, 500)

    def test_temporarily_unavailable(self):
        # Authorization code grant
        self.web.available = False
        _, _, s = self.web.create_authorization_response(
            "https://i.b/auth?client_id=foo&response_type=code", scopes=["foo"]
        )
        self.assertEqual(s, 503)
        _, _, s = self.web.create_token_response(
            "https://i.b/token", body="grant_type=authorization_code&code=foo", scopes=["foo"]
        )
        self.assertEqual(s, 503)

        # Implicit grant
        self.mobile.available = False
        _, _, s = self.mobile.create_authorization_response(
            "https://i.b/auth?client_id=foo&response_type=token", scopes=["foo"]
        )
        self.assertEqual(s, 503)

        # Password credentials grant
        self.legacy.available = False
        _, _, s = self.legacy.create_token_response(
            "https://i.b/token", body="grant_type=password&username=foo&password=foo"
        )
        self.assertEqual(s, 503)

        # Client credentials grant
        self.backend.available = False
        _, _, s = self.backend.create_token_response("https://i.b/token", body="grant_type=client_credentials")
        self.assertEqual(s, 503)

    def test_invalid_client(self):
        self.validator.authenticate_client.return_value = False
        self.validator.authenticate_client_id.return_value = False

        # Authorization code grant
        _, body, _ = self.web.create_token_response("https://i.b/token", body="grant_type=authorization_code&code=foo")
        self.assertEqual("invalid_client", json.loads(body)["error"])

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(
            "https://i.b/token", body="grant_type=password&username=foo&password=bar"
        )
        self.assertEqual("invalid_client", json.loads(body)["error"])

        # Client credentials grant
        _, body, _ = self.legacy.create_token_response("https://i.b/token", body="grant_type=client_credentials")
        self.assertEqual("invalid_client", json.loads(body)["error"])

    def test_invalid_grant(self):
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        self.validator.validate_code.return_value = False
        _, body, _ = self.web.create_token_response("https://i.b/token", body="grant_type=authorization_code&code=foo")
        self.assertEqual("invalid_grant", json.loads(body)["error"])

        # Password credentials grant
        self.validator.validate_user.return_value = False
        _, body, _ = self.legacy.create_token_response(
            "https://i.b/token", body="grant_type=password&username=foo&password=bar"
        )
        self.assertEqual("invalid_grant", json.loads(body)["error"])

    def test_unsupported_grant_type(self):
        self.validator.authenticate_client.side_effect = self.set_client

        # Authorization code grant
        _, body, _ = self.web.create_token_response("https://i.b/token", body="grant_type=bar&code=foo")
        self.assertEqual("unsupported_grant_type", json.loads(body)["error"])

        # Password credentials grant
        _, body, _ = self.legacy.create_token_response(
            "https://i.b/token", body="grant_type=bar&username=foo&password=bar"
        )
        self.assertEqual("unsupported_grant_type", json.loads(body)["error"])

        # Client credentials grant
        _, body, _ = self.backend.create_token_response("https://i.b/token", body="grant_type=bar")
        self.assertEqual("unsupported_grant_type", json.loads(body)["error"])