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)
示例#2
0
    def unauthenticated_userid(self, request):
        validator = RequestValidator(request)

        token_generator = generate_token
        server = BackendApplicationServer(validator, token_generator)

        # bw compat
        token = request.environ.get(self.environ_key)
        if token is not None:
            request.authorization = 'Bearer %s' % token

        try:
            valid, r = server.verify_request(
                request.url,
                request.method,
                None,
                request.headers,
                ['annotations'],
            )
        except:
            valid = False

        if valid:
            return r.user

        # bw compat
        personas = request.session.get('personas', [])
        if len(personas):
            return personas[0]

        return None
示例#3
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'})
示例#4
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)
示例#5
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.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'})
示例#6
0
    def server(self):
        """
        All in one endpoints. This property is created automaticly
        if you have implemented all the getters and setters.

        However, if you are not satisfied with the getter and setter,
        you can create a validator with :class:`OAuth2RequestValidator`::

            class MyValidator(OAuth2RequestValidator):
                def validate_client_id(self, client_id):
                    # do something
                    return True

        And assign the validator for the provider::

            oauth._validator = MyValidator()
        """
        expires_in = self.app.config.get('OAUTH2_PROVIDER_TOKEN_EXPIRES_IN')
        token_generator = self.app.config.get(
            'OAUTH2_PROVIDER_TOKEN_GENERATOR', None)
        if token_generator and not callable(token_generator):
            token_generator = import_string(token_generator)

        refresh_token_generator = self.app.config.get(
            'OAUTH2_PROVIDER_REFRESH_TOKEN_GENERATOR', None)
        if refresh_token_generator and not callable(refresh_token_generator):
            refresh_token_generator = import_string(refresh_token_generator)

        if hasattr(self, '_validator'):
            return BackendApplicationServer(
                self._validator,
                token_expires_in=expires_in,
                token_generator=token_generator,
                refresh_token_generator=refresh_token_generator,
            )

        if hasattr(self, '_clientgetter') and \
                hasattr(self, '_tokengetter') and \
                hasattr(self, '_tokensetter') and \
                hasattr(self, '_revoketoken'):

            validator = OAuth2RequestValidator(
                clientgetter=self._clientgetter,
                tokengetter=self._tokengetter,
                tokensetter=self._tokensetter,
                revoketoken=self._revoketoken,
            )
            self._validator = validator
            return BackendApplicationServer(
                validator,
                token_expires_in=expires_in,
                token_generator=token_generator,
                refresh_token_generator=refresh_token_generator,
            )
        raise RuntimeError('application not bound to required getters')
示例#7
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 __init__(self, **kwargs):
     super(BackendAuthentication, self).__init__(**kwargs)
     self.validator = BackendValidator()
     self.server = BackendApplicationServer(self.validator)
     self.provider = OAuth2ProviderDecorator('/error', self.server)
     # FIXME Must be given by the ressource
     self.scopes = ['ham', 'jam']
示例#9
0
 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)
示例#10
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)
示例#11
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)
 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:"}
示例#13
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)
示例#15
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"])
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')
示例#17
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'])
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'])
示例#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')
示例#20
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')
示例#21
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')
示例#22
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')
import sys

from oauthlib.oauth2 import BackendApplicationServer
from oauthlib.oauth2.ext.django import OAuth2ProviderDecorator

from django.http import HttpResponse

from endpoint.backend_provider.validators import BackendValidator

log = logging.getLogger('endpoint')
log.addHandler(logging.StreamHandler(sys.stdout))
log.setLevel(logging.DEBUG)


validator = BackendValidator()
server = BackendApplicationServer(validator)
provider = OAuth2ProviderDecorator('/backendprovider/error', server)    # See next section


@provider.access_token_view
def create_token(request):
    # Not much too do here for you, return a dict with extra credentials
    # you want appended to request.credentials passed to the save_bearer_token
    # method of the validator.
    return {}


@provider.protected_resource_view(scopes=['ham'])
def protected_resource(request, client=None, user=None, scopes=None):
    # One of your many OAuth 2 protected resource views
    # Returns whatever you fancy