def test_unavailability(self): validator = RequestValidator() server = Server(validator) server.available = False h, b, s = server.create_authorization_response('https://example.com') self.assertIn("temporarily_unavailable", b) self.assertEqual(s, 503)
def server(self): """All in one endpoints.""" app = self.get_app() expires_in = app.config.get('OAUTH_PROVIDER_TOKEN_EXPIRES_IN') if hasattr(self, '_validator'): return Server(self._validator, token_expires_in=expires_in) if hasattr(self, '_clientgetter') and \ hasattr(self, '_tokengetter') and \ hasattr(self, '_tokensetter') and \ hasattr(self, '_grantgetter') and \ hasattr(self, '_grantsetter'): usergetter = None if hasattr(self, '_usergetter'): usergetter = self._usergetter validator = OAuth2RequestValidator( clientgetter=self._clientgetter, tokengetter=self._tokengetter, grantgetter=self._grantgetter, usergetter=usergetter, tokensetter=self._tokensetter, grantsetter=self._grantsetter, ) return Server(validator, token_expires_in=expires_in) raise RuntimeError('application not bound to required getters')
def test_error_catching(self): validator = RequestValidator() server = Server(validator) server.catch_errors = True h, b, s = server.create_authorization_response('https://example.com') self.assertIn("server_error", b) self.assertEqual(s, 500)
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 Server( 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, '_grantgetter') and \ hasattr(self, '_grantsetter'): usergetter = None if hasattr(self, '_usergetter'): usergetter = self._usergetter validator = OAuth2RequestValidator( clientgetter=self._clientgetter, tokengetter=self._tokengetter, grantgetter=self._grantgetter, usergetter=usergetter, tokensetter=self._tokensetter, grantsetter=self._grantsetter, ) self._validator = validator return Server( validator, token_expires_in=expires_in, token_generator=token_generator, refresh_token_generator=refresh_token_generator, ) raise RuntimeError('application not bound to required getters')
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.server = Server(self.validator) self.web = WebApplicationServer(self.validator) self.mobile = MobileApplicationServer(self.validator) self.legacy = LegacyApplicationServer(self.validator) self.backend = BackendApplicationServer(self.validator)
def test_error_catching(self): validator = RequestValidator() server = Server(validator) server.catch_errors = True h, b, s = server.create_token_response( 'https://example.com', body='grant_type=authorization_code&code=abc' ) self.assertIn("server_error", b) self.assertEqual(s, 500)
def token_endpoint(request): validator = RequestValidator() server = Server(validator) uri, http_method, body, headers = extract_params(request) server_response = server.create_token_response( uri, http_method, body, headers, {}, ) return create_response(*server_response)
def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = TestClaimsHandling.DEFAULT_REDIRECT_URI self.validator.authenticate_client.side_effect = self.set_client self.validator.save_authorization_code.side_effect = self.save_claims_with_code self.validator.validate_code.side_effect = self.retrieve_claims_saved_with_code self.validator.save_token.side_effect = self.save_claims_with_bearer_token self.server = Server(self.validator)
class AuthorizationView(View): def __init__(self): validator = DjangoValidator() # TODO: this should probably be tunable through settings self._authorization_endpoint = Server(validator) self._error_uri = reverse('oauth2_error') def get(self, request, *args, **kwargs): uri, http_method, body, headers = extract_params(request) redirect_uri = request.GET.get('redirect_uri', None) log.debug('Found redirect uri %s.', redirect_uri) try: scopes, credentials = self._authorization_endpoint.validate_authorization_request( uri, http_method, body, headers) log.debug('Saving credentials to session, %r.', credentials) request.session['oauth2_credentials'] = credentials kwargs['scopes'] = scopes kwargs.update(credentials) actual_view = get_actual_authorization_view(request) log.debug('Invoking actual view method, %r.', actual_view) return actual_view(request, *args, **kwargs) except errors.FatalClientError as e: log.debug('Fatal client error, redirecting to error page.') return HttpResponseRedirect(e.in_uri(self._error_uri)) except errors.OAuth2Error as e: log.debug('Client error, redirecting back to client.') # TODO: remove after federico PR e.redirect_uri = redirect_uri or 'https://localhost' return HttpResponseRedirect(e.in_uri(e.redirect_uri)) @csrf_exempt def post(self, request, *args, **kwargs): uri, http_method, body, headers = extract_params(request) scopes, credentials = get_authorization(request) log.debug('Fetched credentials view, %r.', credentials) credentials.update(request.session.get('oauth2_credentials', {})) log.debug('Fetched credentials from session, %r.', credentials) redirect_uri = credentials.get('redirect_uri') log.debug('Found redirect uri %s.', redirect_uri) try: url, headers, body, status = self._authorization_endpoint.create_authorization_response( uri, http_method, body, headers, scopes, credentials) log.debug('Authorization successful, redirecting to client.') return HttpResponseRedirect(url) except errors.FatalClientError as e: log.debug('Fatal client error, redirecting to error page.') return HttpResponseRedirect(e.in_uri(self._error_uri)) except errors.OAuth2Error as e: log.debug('Client error, redirecting back to client.') return HttpResponseRedirect(e.in_uri(redirect_uri))
def verify_request(request, scopes): validator = RequestValidator() server = Server(validator) uri, http_method, body, headers = extract_params(request) valid, r = server.verify_request( uri, http_method, body, headers, scopes, ) if not valid: raise HTTPUnauthorized() return r.user
def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) oauth2 = JSONOAuthLibCore(Server(OAuth2V1Validator())) uri, headers, body, status = oauth2.create_token_response(request) return Response(json.loads(body), status=status)
class IamRequestValidator(IRequestValidator): def __init__(self, validator: OauthlibRequestValidator): self._server = Server(validator) def validate_pre_auth_request(self, request: ff.Message): http_request = request.headers.get('http_request') return self._server.validate_authorization_request( f'{http_request["headers"]["Host"]}{http_request["url"]}', http_request['method'], '', http_request['headers']) def validate_post_auth_request(self, request: ff.Message): pass def create_response(self, request: ff.Message): return self._server.create_authorization_response( request.headers.get('uri'), request.headers.get('http_method'), request.to_dict(), request.headers)
def setUp(self): super().setUp() self.oauth = BottleOAuth2(self.app) self.validator = mock.MagicMock() self.server = Server(self.validator) self.oauth.initialize(self.server) self.fake_response = ({}, "", "200 fooOK")
def get_oauthlib_core(): """ Utility function that take a request and returns an instance of `oauth2_provider.backends.OAuthLibCore` """ from oauthlib.oauth2 import Server server = Server(oauth2_settings.OAUTH2_VALIDATOR_CLASS()) return OAuthLibCore(server)
def get_oauthlib_core(): """ Utility function that take a request and returns an instance of `oauth2_provider.backends.OAuthLibCore` """ from oauth2_provider.oauth2_validators import OAuth2Validator from oauthlib.oauth2 import Server server = Server(OAuth2Validator()) return OAuthLibCore(server)
def _validate(request, *args, **kwargs): validator = OAuth2Validator() core = OAuthLibCore(Server(validator)) valid, oauthlib_req = core.verify_request(request, scopes = _scopes) if valid: request.client = oauthlib_req.client request.resource_owner = oauthlib_req.user return view_func(request, *args, **kwargs) return HttpResponseForbidden()
def get_response(self): oauth2 = JSONOAuthLibCore(Server(OAuth2V1Validator())) url, headers, body, status = oauth2.create_revocation_response( self.request) if status != 200: result = json.loads(body) else: result = {"detail": _("success logout")} return Response(result, status=status)
def _validate(request, *args, **kwargs): core = OAuthLibCore(Server(OAuth2Validator())) valid, oauthlib_req = core.verify_request(request, scopes=[]) if valid: # Note, resource_owner is not a very good name for this request.resource_owner = oauthlib_req.user request.oauth = oauthlib_req return view_func(request, *args, **kwargs) return build_error_response(401, 'The token authentication failed.')
def setUp(self): super().setUp() self.oauth = BottleOAuth2(self.app) self.validator = mock.MagicMock() self.server = Server(self.validator) self.oauth.initialize(self.server) self.fake_response = ({ "Content-Type": "application/x-www-form-urlencoded" }, "a=b&c=d", "200 FooOK")
def setUp(self): super().setUp() self.oauth = BottleOAuth2(self.app) self.validator = mock.MagicMock() self.server = Server(self.validator) self.oauth.initialize(self.server) self.fake_response = ({ "Content-Type": "application/json" }, "{'valid': true, 'foo': 'bar'}", "200 FooOK")
def setUp(self): super().setUp() self.oauth = BottleOAuth2(self.app) self.validator = mock.MagicMock() self.server = Server(self.validator) self.oauth.initialize(self.server) self.fake_request = AttrDict(client="foo", user="******", scopes=['banana', 'pinapple'])
def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) data = self.request.data oauth2 = JSONOAuthLibCore(Server(OAuth2V1Validator())) uri, headers, body, status = oauth2.create_token_response(request) data = json.loads(body) if status != 200: raise ValidationError({'username': [data['error']]}) return Response(data, status=status)
def authenticate(self, request): """ Authenticate the request """ server = Server(OAuthValidator()) handler = OAuthHandler(server) valid, r = handler.verify_request(request, scopes=[]) if valid: return r.user, r.access_token else: return None
def validator(request, *args, **kwargs): from oauth2_provider.oauth2_validators import OAuth2Validator from oauth2_provider.oauth2_backends import OAuthLibCore from oauthlib.oauth2 import Server core = OAuthLibCore(Server(OAuth2Validator())) valid, oauthlib_req = core.verify_request(request, scopes=scopes) if valid: request.token = oauthlib_req.access_token return f(request, *args, **kwargs) return JsonResponseForbidden({ "error": "invalid token", "code": "INVALID_TOKEN" })
def test_server_metadata(self): endpoint = Server(None) metadata = MetadataEndpoint( [endpoint], { "issuer": 'https://foo.bar', "authorization_endpoint": "https://foo.bar/authorize", "introspection_endpoint": "https://foo.bar/introspect", "revocation_endpoint": "https://foo.bar/revoke", "token_endpoint": "https://foo.bar/token", "jwks_uri": "https://foo.bar/certs", "scopes_supported": ["email", "profile"] }) expected_claims = { "issuer": "https://foo.bar", "authorization_endpoint": "https://foo.bar/authorize", "introspection_endpoint": "https://foo.bar/introspect", "revocation_endpoint": "https://foo.bar/revoke", "token_endpoint": "https://foo.bar/token", "jwks_uri": "https://foo.bar/certs", "scopes_supported": ["email", "profile"], "grant_types_supported": [ "authorization_code", "password", "client_credentials", "refresh_token", "implicit" ], "token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], "response_types_supported": ["code", "token"], "response_modes_supported": ["query", "fragment"], "code_challenge_methods_supported": ["plain", "S256"], "revocation_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], "introspection_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"] } def sort_list(claims): for k in claims.keys(): claims[k] = sorted(claims[k]) sort_list(metadata.claims) sort_list(expected_claims) self.assertEqual(sorted(metadata.claims.items()), sorted(expected_claims.items()))
def server(self): validator_key = '_validator' if hasattr(self, validator_key): return Server( getattr(self, validator_key), token_expires_in=self._token_expires_in, token_generator=self._token_generator, refresh_token_generator=self._refresh_token_generator, ) if hasattr(self, '_clientgetter') and \ hasattr(self, '_tokengetter') and \ hasattr(self, '_tokensetter') and \ hasattr(self, '_grantgetter') and \ hasattr(self, '_grantsetter'): usergetter = None if hasattr(self, '_usergetter'): usergetter = self._usergetter validator = self.oauth_validator( service=self.service, clientgetter=getattr(self, '_clientgetter'), tokengetter=getattr(self, '_tokengetter'), grantgetter=getattr(self, '_grantgetter'), usergetter=usergetter, tokensetter=getattr(self, '_tokensetter'), grantsetter=getattr(self, '_grantsetter')) setattr(self, validator_key, validator) return Server( validator, token_expires_in=self._token_expires_in, token_generator=self._token_generator, refresh_token_generator=self._refresh_token_generator, ) raise RuntimeError('application not bound to required getters')
def server(self): """ All in one endpoints. This property is created automaticaly 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() """ if not self._server: if not self._validator: accessors = [ '_clientgetter', '_tokengetter', '_tokensetter', '_grantgetter', '_grantsetter' ] for accessor in accessors: if not hasattr(self, accessor): raise RuntimeError( 'Missing required accessor {}'.format(accessor)) self._validator = OAuthValidator( clientgetter=self._clientgetter, tokengetter=self._tokengetter, grantgetter=self._grantgetter, usergetter=self._usergetter, tokensetter=self._tokensetter, grantsetter=self._grantsetter, ) self._server = Server( self._validator, token_expires_in=self._expires_in, token_generator=self._token_generator, refresh_token_generator=self._refresh_token_generator, ) return self._server
def __call__(self, request): # 正式环境下要检查AccessToken if not settings.DEBUG: if "account_spider" in request.path: authorization = request.META.get("HTTP_AUTHORIZATION", "") token = request.GET.get("token", "") authorization_session = request.session.get("authorization") if token: request.META["HTTP_AUTHORIZATION"] = "Bearer %s" % token request.session['authorization'] = "Bearer %s" % token elif authorization: request.session['authorization'] = authorization elif authorization_session: request.META["HTTP_AUTHORIZATION"] = authorization_session validator = OAuth2Validator() core = OAuthLibCore(Server(validator)) valid, oauthlib_req = core.verify_request(request, scopes=[]) if not valid: return HttpResponseForbidden() request.resource_owner = oauthlib_req.user return self.get_response(request)
class AuthorizationEndpoint(object): def __init__(self, request): self.request = request self.validator = RequestValidator() self.server = Server(self.validator) @view_config(route_name='oauth2_authorization_endpoint', renderer='templates/application_authorization.pt', permission='add-authorized-app', request_method='GET') def get(self): uri, http_method, body, headers = extract_params(self.request) try: scopes, credentials = self.server.validate_authorization_request( uri, http_method, body, headers, ) app = self.validator.get_client(credentials['client_id']) try: auth_app = Session.query(AuthorizedApplication).filter( AuthorizedApplication.user == self.request.user, AuthorizedApplication.scope == scopes, AuthorizedApplication.redirect_uri == credentials['redirect_uri'], AuthorizedApplication.response_type == credentials['response_type'], AuthorizedApplication.application == app, ).one() except NoResultFound: auth_app = None if auth_app is not None: credentials['user'] = self.request.user server_response = self.server.create_authorization_response( uri, http_method, body, headers, scopes, credentials, ) return create_response(*server_response) else: authorship_information = app.user.email pretty_scopes = self.validator.get_pretty_scopes(scopes) return { 'response_type': credentials['response_type'], 'client_id': credentials['client_id'], 'redirect_uri': credentials['redirect_uri'], 'state': credentials['state'], 'scope': ' '.join(scopes), 'app': app, 'scopes': pretty_scopes, 'authorship_information': authorship_information, } except FatalClientError as e: return response_from_error(e) except OAuth2Error as e: return HTTPFound(e.in_uri(e.redirect_uri)) @view_config(route_name='oauth2_authorization_endpoint', permission='add-authorized-app', request_method='POST') def post(self): uri, http_method, body, headers = extract_params(self.request) redirect_uri = self.request.POST.get('redirect_uri') if 'submit' in self.request.POST: scope = self.request.POST.get('scope', '') scopes = scope.split() credentials = { 'client_id': self.request.POST.get('client_id'), 'redirect_uri': redirect_uri, 'response_type': self.request.POST.get('response_type'), 'state': self.request.POST.get('state'), 'user': self.request.user, } try: server_response = self.server.create_authorization_response( uri, http_method, body, headers, scopes, credentials, ) app = Session.query(Application).filter( Application.id == credentials['client_id'], ).one() try: auth_app = Session.query(AuthorizedApplication).filter( AuthorizedApplication.user == self.request.user, AuthorizedApplication.application == app, ).one() except NoResultFound: auth_app = AuthorizedApplication( user=self.request.user, application=app, ) auth_app.redirect_uri = credentials['redirect_uri'] auth_app.response_type = credentials['response_type'] auth_app.scope = scopes Session.add(auth_app) return create_response(*server_response) except FatalClientError as e: return response_from_error(e) elif 'cancel' in self.request.POST: e = AccessDeniedError() return HTTPFound(e.in_uri(redirect_uri))
def __init__(self): validator = DjangoValidator() # TODO: this should probably be tunable through settings self._authorization_endpoint = Server(validator) self._error_uri = reverse('oauth2_error')
class TestClaimsHandling(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 save_claims_with_code(self, client_id, code, request, *args, **kwargs): # a real validator would save the claims with the code during save_authorization_code() self.claims_from_auth_code_request = request.claims self.scopes = request.scopes.split() def retrieve_claims_saved_with_code(self, client_id, code, client, request, *args, **kwargs): request.claims = self.claims_from_auth_code_request request.scopes = self.scopes return True def save_claims_with_bearer_token(self, token, request, *args, **kwargs): # a real validator would save the claims with the access token during save_bearer_token() self.claims_saved_with_bearer_token = request.claims def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = TestClaimsHandling.DEFAULT_REDIRECT_URI self.validator.authenticate_client.side_effect = self.set_client self.validator.save_authorization_code.side_effect = self.save_claims_with_code self.validator.validate_code.side_effect = self.retrieve_claims_saved_with_code self.validator.save_token.side_effect = self.save_claims_with_bearer_token self.server = Server(self.validator) def test_claims_stored_on_code_creation(self): claims = { "id_token": { "claim_1": None, "claim_2": { "essential": True } }, "userinfo": { "claim_3": { "essential": True }, "claim_4": None } } claims_urlquoted = '%7B%22id_token%22%3A%20%7B%22claim_2%22%3A%20%7B%22essential%22%3A%20true%7D%2C%20%22claim_1%22%3A%20null%7D%2C%20%22userinfo%22%3A%20%7B%22claim_4%22%3A%20null%2C%20%22claim_3%22%3A%20%7B%22essential%22%3A%20true%7D%7D%7D' uri = 'http://example.com/path?client_id=abc&scope=openid+test_scope&response_type=code&claims=%s' h, b, s = self.server.create_authorization_response( uri % claims_urlquoted, scopes='openid test_scope') self.assertDictEqual(self.claims_from_auth_code_request, claims) code = get_query_credentials(h['Location'])['code'][0] token_uri = 'http://example.com/path' _, body, _ = self.server.create_token_response( token_uri, body='grant_type=authorization_code&code=%s' % code) self.assertDictEqual(self.claims_saved_with_bearer_token, claims) def test_invalid_claims(self): uri = 'http://example.com/path?client_id=abc&scope=openid+test_scope&response_type=code&claims=this-is-not-json' h, b, s = self.server.create_authorization_response( uri, scopes='openid test_scope') error = get_query_credentials(h['Location'])['error'][0] error_desc = get_query_credentials( h['Location'])['error_description'][0] self.assertEqual(error, 'invalid_request') self.assertEqual(error_desc, "Malformed claims parameter")
class TestClaimsHandling(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 save_claims_with_code(self, client_id, code, request, *args, **kwargs): # a real validator would save the claims with the code during save_authorization_code() self.claims_from_auth_code_request = request.claims self.scopes = request.scopes.split() def retrieve_claims_saved_with_code(self, client_id, code, client, request, *args, **kwargs): request.claims = self.claims_from_auth_code_request request.scopes = self.scopes return True def save_claims_with_bearer_token(self, token, request, *args, **kwargs): # a real validator would save the claims with the access token during save_bearer_token() self.claims_saved_with_bearer_token = request.claims def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = TestClaimsHandling.DEFAULT_REDIRECT_URI self.validator.authenticate_client.side_effect = self.set_client self.validator.save_authorization_code.side_effect = self.save_claims_with_code self.validator.validate_code.side_effect = self.retrieve_claims_saved_with_code self.validator.save_token.side_effect = self.save_claims_with_bearer_token self.server = Server(self.validator) def test_claims_stored_on_code_creation(self): claims = { "id_token": { "claim_1": None, "claim_2": { "essential": True } }, "userinfo": { "claim_3": { "essential": True }, "claim_4": None } } claims_urlquoted='%7B%22id_token%22%3A%20%7B%22claim_2%22%3A%20%7B%22essential%22%3A%20true%7D%2C%20%22claim_1%22%3A%20null%7D%2C%20%22userinfo%22%3A%20%7B%22claim_4%22%3A%20null%2C%20%22claim_3%22%3A%20%7B%22essential%22%3A%20true%7D%7D%7D' uri = 'http://example.com/path?client_id=abc&scope=openid+test_scope&response_type=code&claims=%s' h, b, s = self.server.create_authorization_response(uri % claims_urlquoted, scopes='openid test_scope') self.assertDictEqual(self.claims_from_auth_code_request, claims) code = get_query_credentials(h['Location'])['code'][0] token_uri = 'http://example.com/path' _, body, _ = self.server.create_token_response(token_uri, body='grant_type=authorization_code&code=%s' % code) self.assertDictEqual(self.claims_saved_with_bearer_token, claims) def test_invalid_claims(self): uri = 'http://example.com/path?client_id=abc&scope=openid+test_scope&response_type=code&claims=this-is-not-json' h, b, s = self.server.create_authorization_response(uri, scopes='openid test_scope') error = get_query_credentials(h['Location'])['error'][0] error_desc = get_query_credentials(h['Location'])['error_description'][0] self.assertEqual(error, 'invalid_request') self.assertEqual(error_desc, "Malformed claims parameter")
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.server = Server(self.validator) 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']), ('images+videos+openid', ['images', 'videos', 'openid']), ('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) scopes, _ = self.server.validate_authorization_request( uri % (scope, 'code')) 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 for backend_server_type in ['web', 'server']: h, _, s = getattr(self, backend_server_type).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, _ = getattr(self, backend_server_type).create_token_response(token_uri, body='grant_type=authorization_code&code=%s' % code) self.assertEqual(json.loads(body)['scope'], decoded_scope) # implicit grant for backend_server_type in ['mobile', 'server']: h, _, s = getattr(self, backend_server_type).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 for backend_server_type in ['legacy', 'server']: body = 'grant_type=password&username=abc&password=secret&scope=%s' _, body, _ = getattr(self, backend_server_type).create_token_response(token_uri, body=body % scope) self.assertEqual(json.loads(body)['scope'], decoded_scope) # client credentials grant for backend_server_type in ['backend', 'server']: body = 'grant_type=client_credentials&scope=%s' self.validator.authenticate_client.side_effect = self.set_user _, body, _ = getattr(self, backend_server_type).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')
def __init__(self, validator: OauthlibRequestValidator): self._server = Server(validator)
def __init__(self, request): self.request = request self.validator = RequestValidator() self.server = Server(self.validator)