def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = self.DEFAULT_REDIRECT_URI self.validator.get_code_challenge.return_value = None self.validator.authenticate_client.side_effect = self.set_client self.web = WebApplicationServer(self.validator) self.mobile = MobileApplicationServer(self.validator)
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)
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'})
def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = TestScopeHandling.DEFAULT_REDIRECT_URI self.validator.authenticate_client.side_effect = self.set_client self.web = WebApplicationServer(self.validator) self.mobile = MobileApplicationServer(self.validator) self.legacy = LegacyApplicationServer(self.validator) self.backend = BackendApplicationServer(self.validator)
class ExtraCredentialsTest(TestCase): def set_client(self, request): request.client = mock.MagicMock() request.client.client_id = 'mocked' return True def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' self.web = WebApplicationServer(self.validator) self.mobile = MobileApplicationServer(self.validator) self.legacy = LegacyApplicationServer(self.validator) self.backend = BackendApplicationServer(self.validator) def test_post_authorization_request(self): def save_code(client_id, token, request): self.assertEqual('creds', request.extra) def save_token(token, request): self.assertEqual('creds', request.extra) # Authorization code grant self.validator.save_authorization_code.side_effect = save_code self.web.create_authorization_response( 'https://i.b/auth?client_id=foo&response_type=code', scopes=['foo'], credentials={'extra': 'creds'}) # Implicit grant self.validator.save_bearer_token.side_effect = save_token self.mobile.create_authorization_response( 'https://i.b/auth?client_id=foo&response_type=token', scopes=['foo'], credentials={'extra': 'creds'}) def test_token_request(self): def save_token(token, request): self.assertIn('extra', token) self.validator.save_bearer_token.side_effect = save_token self.validator.authenticate_client.side_effect = self.set_client # Authorization code grant self.web.create_token_response('https://i.b/token', body='grant_type=authorization_code&code=foo', credentials={'extra': 'creds'}) # Password credentials grant self.legacy.create_token_response('https://i.b/token', body='grant_type=password&username=foo&password=bar', credentials={'extra': 'creds'}) # Client credentials grant self.backend.create_token_response('https://i.b/token', body='grant_type=client_credentials', credentials={'extra': 'creds'})
def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) 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)
class OAuth2ProviderDecorator(object): def __init__(self): super(OAuth2ProviderDecorator, self).__init__() validator = WebValidator() self._resource_endpoint = WebApplicationServer(validator) def protected_resource_view(self, scopes=None): def decorator(f): @functools.wraps(f) def wrapper(request, *args, **kwargs): try: scopes_list = scopes(request) except TypeError: scopes_list = scopes uri, http_method, body, headers = extract_params(request) valid, r = self._resource_endpoint.verify_request( uri, http_method, body, headers, scopes_list) kwargs.update({ 'client': r.client, 'user': r.user, 'scopes': r.scopes }) if valid: request.request.current_user = kwargs.get('user') return f(request, *args, **kwargs) else: raise tornado.web.HTTPError(403) return wrapper return decorator
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)
class OAuthAuthorizeController(object): def __init__(self, request): self.request = request self.user_svc = self.request.find_service(name='user') validator = self.request.find_service(name='oauth_validator') self.oauth = WebApplicationServer(validator) @view_config(request_method='GET', renderer='h:templates/oauth/authorize.html.jinja2') def get(self): scopes, credentials = self.oauth.validate_authorization_request(self.request.url) if self.request.authenticated_userid is None: raise HTTPFound(self.request.route_url('login', _query={ 'next': self.request.url})) client_id = credentials.get('client_id') state = credentials.get('state') user = self.user_svc.fetch(self.request.authenticated_userid) client = self.request.db.query(models.AuthClient).get(client_id) return {'username': user.username, 'client_name': client.name, 'client_id': client.id, 'response_type': client.response_type.value, 'state': state} @view_config(request_method='POST', effective_principals=security.Authenticated) def post(self): # We don't support scopes at the moment, but oauthlib does need a scope, # so we're explicitly overwriting whatever the client provides. scopes = DEFAULT_SCOPES user = self.user_svc.fetch(self.request.authenticated_userid) credentials = {'user': user} headers, _, status = self.oauth.create_authorization_response( self.request.url, scopes=scopes, credentials=credentials) try: return HTTPFound(location=headers['Location']) except KeyError: client_id = self.request.params.get('client_id') raise RuntimeError('created authorisation code for client "{}" but got no redirect location'.format(client_id))
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)
class WebAuthorizeHandler(tornado.web.RequestHandler): """ oauth 用户授权 """ def initialize(self): # 初始化 oauth2 后端服务 self._authorization_endpoint = WebApplicationServer(WebValidator()) self._error_uri = self.reverse_url('web-error') def get(self): # 解析 request,包装 oauthlib request uri, http_method, body, headers = extract_params(self.request) redirect_uri = self.get_query_argument('redirect_uri', None) try: # 验证client请求,识别client身份 scopes, credentials = self._authorization_endpoint.validate_authorization_request( uri, http_method, body, headers) except errors.FatalClientError as e: logger.error(e.error) self.finish(e.error) self.redirect(self._error_uri) except errors.OAuth2Error as e: e.redirect_uri = redirect_uri logger.error(e.error) self.finish(e.error) self.redirect(e.in_uri(e.redirect_uri)) # 渲染用户认证授权页面 self.write('<h1> Authorize access to %s </h1>' % credentials['client_id']) self.write('<form method="POST" action="">') for scope in scopes or []: self.write('<input type="checkbox" checked="checked" name="scopes" value="%s"/> %s' % (scope, scope)) self.write('<input type="text" name="username" value="username"/>') self.write('<input type="password" name="password" value="password"/>') self.write('<input type="submit" value="Authorize"/>') def post(self, *args, **kwargs): uri, http_method, body, headers = extract_params(self.request) try: headers, body, status = self._token_endpoint.create_token_response(uri, http_method, body, headers) except errors.FatalClientError as e: logger.error(e) print e self.redirect(self._error_uri) except errors.OAuth2Error as e: logger.error(e) print e self.redirect(self._error_uri) self.set_header('Content-Type', 'application/json') self.finish(body)
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 setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) 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)
class WebRefreshHandler(tornado.web.RequestHandler): def initialize(self): # 初始化 oauth2 后端服务 self._refresh_endpoint = WebApplicationServer(WebValidator()) self._error_uri = self.reverse_url('web-error') def post(self, *args, **kwargs): uri, http_method, body, headers = extract_params(self.request) try: headers, body, status = self._refresh_endpoint.create_token_response( uri, http_method, body, headers) except errors.FatalClientError as e: logger.error(e) self.redirect(self._error_uri) except errors.OAuth2Error as e: logger.error(e) self.redirect(self._error_uri) self.set_header('Content-Type', 'application/json') self.finish(body)
class ErrorResponseTest(TestCase): def set_client(self, request): request.client = mock.MagicMock() request.client.client_id = 'mocked' return True def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = None self.web = WebApplicationServer(self.validator) self.mobile = MobileApplicationServer(self.validator) self.legacy = LegacyApplicationServer(self.validator) self.backend = BackendApplicationServer(self.validator) def test_invalid_redirect_uri(self): uri = 'https://example.com/authorize?response_type={0}&client_id=foo&redirect_uri=wrong' # Authorization code grant self.assertRaises(errors.InvalidRedirectURIError, self.web.validate_authorization_request, uri.format('code')) self.assertRaises(errors.InvalidRedirectURIError, self.web.create_authorization_response, uri.format('code'), scopes=['foo']) # Implicit grant self.assertRaises(errors.InvalidRedirectURIError, self.mobile.validate_authorization_request, uri.format('token')) self.assertRaises(errors.InvalidRedirectURIError, self.mobile.create_authorization_response, uri.format('token'), scopes=['foo']) def test_invalid_default_redirect_uri(self): uri = 'https://example.com/authorize?response_type={0}&client_id=foo' self.validator.get_default_redirect_uri.return_value = "wrong" # Authorization code grant self.assertRaises(errors.InvalidRedirectURIError, self.web.validate_authorization_request, uri.format('code')) self.assertRaises(errors.InvalidRedirectURIError, self.web.create_authorization_response, uri.format('code'), scopes=['foo']) # Implicit grant self.assertRaises(errors.InvalidRedirectURIError, self.mobile.validate_authorization_request, uri.format('token')) self.assertRaises(errors.InvalidRedirectURIError, self.mobile.create_authorization_response, uri.format('token'), scopes=['foo']) def test_missing_redirect_uri(self): uri = 'https://example.com/authorize?response_type={0}&client_id=foo' # Authorization code grant self.assertRaises(errors.MissingRedirectURIError, self.web.validate_authorization_request, uri.format('code')) self.assertRaises(errors.MissingRedirectURIError, self.web.create_authorization_response, uri.format('code'), scopes=['foo']) # Implicit grant self.assertRaises(errors.MissingRedirectURIError, self.mobile.validate_authorization_request, uri.format('token')) self.assertRaises(errors.MissingRedirectURIError, self.mobile.create_authorization_response, uri.format('token'), scopes=['foo']) def test_mismatching_redirect_uri(self): uri = 'https://example.com/authorize?response_type={0}&client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback' # Authorization code grant self.validator.validate_redirect_uri.return_value = False self.assertRaises(errors.MismatchingRedirectURIError, self.web.validate_authorization_request, uri.format('code')) self.assertRaises(errors.MismatchingRedirectURIError, self.web.create_authorization_response, uri.format('code'), scopes=['foo']) # Implicit grant self.assertRaises(errors.MismatchingRedirectURIError, self.mobile.validate_authorization_request, uri.format('token')) self.assertRaises(errors.MismatchingRedirectURIError, self.mobile.create_authorization_response, uri.format('token'), scopes=['foo']) def test_missing_client_id(self): uri = 'https://example.com/authorize?response_type={0}&redirect_uri=https%3A%2F%2Fi.b%2Fback' # Authorization code grant self.validator.validate_redirect_uri.return_value = False self.assertRaises(errors.MissingClientIdError, self.web.validate_authorization_request, uri.format('code')) self.assertRaises(errors.MissingClientIdError, self.web.create_authorization_response, uri.format('code'), scopes=['foo']) # Implicit grant self.assertRaises(errors.MissingClientIdError, self.mobile.validate_authorization_request, uri.format('token')) self.assertRaises(errors.MissingClientIdError, self.mobile.create_authorization_response, uri.format('token'), scopes=['foo']) def test_invalid_client_id(self): uri = 'https://example.com/authorize?response_type={0}&client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback' # Authorization code grant self.validator.validate_client_id.return_value = False self.assertRaises(errors.InvalidClientIdError, self.web.validate_authorization_request, uri.format('code')) self.assertRaises(errors.InvalidClientIdError, self.web.create_authorization_response, uri.format('code'), scopes=['foo']) # Implicit grant self.assertRaises(errors.InvalidClientIdError, self.mobile.validate_authorization_request, uri.format('token')) self.assertRaises(errors.InvalidClientIdError, self.mobile.create_authorization_response, uri.format('token'), scopes=['foo']) def test_empty_parameter(self): uri = 'https://example.com/authorize?client_id=foo&redirect_uri=https%3A%2F%2Fi.b%2Fback&response_type=code&' # Authorization code grant self.assertRaises(errors.InvalidRequestFatalError, self.web.validate_authorization_request, uri) # Implicit grant self.assertRaises(errors.InvalidRequestFatalError, self.mobile.validate_authorization_request, uri) def test_invalid_request(self): self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' token_uri = 'https://i.b/token' invalid_bodies = [ # duplicate params 'grant_type=authorization_code&client_id=nope&client_id=nope&code=foo' ] for body in invalid_bodies: _, body, _ = self.web.create_token_response(token_uri, body=body) self.assertEqual('invalid_request', json.loads(body)['error']) # Password credentials grant invalid_bodies = [ # duplicate params 'grant_type=password&username=foo&username=bar&password=baz' # missing username 'grant_type=password&password=baz' # missing password 'grant_type=password&username=foo' ] self.validator.authenticate_client.side_effect = self.set_client for body in invalid_bodies: _, body, _ = self.legacy.create_token_response(token_uri, body=body) self.assertEqual('invalid_request', json.loads(body)['error']) # Client credentials grant invalid_bodies = [ # duplicate params 'grant_type=client_credentials&scope=foo&scope=bar' ] for body in invalid_bodies: _, body, _ = self.backend.create_token_response(token_uri, body=body) self.assertEqual('invalid_request', json.loads(body)['error']) def test_invalid_request_duplicate_params(self): self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' uri = 'https://i.b/auth?client_id=foo&client_id=bar&response_type={0}' description = 'Duplicate client_id parameter.' # Authorization code self.assertRaisesRegexp(errors.InvalidRequestFatalError, description, self.web.validate_authorization_request, uri.format('code')) self.assertRaisesRegexp(errors.InvalidRequestFatalError, description, self.web.create_authorization_response, uri.format('code'), scopes=['foo']) # Implicit grant self.assertRaisesRegexp(errors.InvalidRequestFatalError, description, self.mobile.validate_authorization_request, uri.format('token')) self.assertRaisesRegexp(errors.InvalidRequestFatalError, description, self.mobile.create_authorization_response, uri.format('token'), scopes=['foo']) def test_invalid_request_missing_response_type(self): self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' uri = 'https://i.b/auth?client_id=foo' # Authorization code self.assertRaises(errors.MissingResponseTypeError, self.web.validate_authorization_request, uri.format('code')) h, _, s = self.web.create_authorization_response(uri, scopes=['foo']) self.assertEqual(s, 302) self.assertIn('Location', h) self.assertIn('error=invalid_request', h['Location']) # Implicit grant self.assertRaises(errors.MissingResponseTypeError, self.mobile.validate_authorization_request, uri.format('token')) h, _, s = self.mobile.create_authorization_response(uri, scopes=['foo']) self.assertEqual(s, 302) self.assertIn('Location', h) self.assertIn('error=invalid_request', h['Location']) def test_unauthorized_client(self): self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' self.validator.validate_grant_type.return_value = False self.validator.validate_response_type.return_value = False self.validator.authenticate_client.side_effect = self.set_client token_uri = 'https://i.b/token' # Authorization code grant self.assertRaises(errors.UnauthorizedClientError, self.web.validate_authorization_request, 'https://i.b/auth?response_type=code&client_id=foo') _, body, _ = self.web.create_token_response( token_uri, body='grant_type=authorization_code&code=foo') self.assertEqual('unauthorized_client', json.loads(body)['error']) # Implicit grant self.assertRaises( errors.UnauthorizedClientError, self.mobile.validate_authorization_request, 'https://i.b/auth?response_type=token&client_id=foo') # Password credentials grant _, body, _ = self.legacy.create_token_response( token_uri, body='grant_type=password&username=foo&password=bar') self.assertEqual('unauthorized_client', json.loads(body)['error']) # Client credentials grant _, body, _ = self.backend.create_token_response( token_uri, body='grant_type=client_credentials') self.assertEqual('unauthorized_client', json.loads(body)['error']) def test_access_denied(self): self.validator.authenticate_client.side_effect = self.set_client self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' self.validator.confirm_redirect_uri.return_value = False token_uri = 'https://i.b/token' # Authorization code grant _, body, _ = self.web.create_token_response( token_uri, body='grant_type=authorization_code&code=foo') self.assertEqual('invalid_request', json.loads(body)['error']) def test_access_denied_no_default_redirecturi(self): self.validator.authenticate_client.side_effect = self.set_client self.validator.get_default_redirect_uri.return_value = None token_uri = 'https://i.b/token' # Authorization code grant _, body, _ = self.web.create_token_response( token_uri, body='grant_type=authorization_code&code=foo') self.assertEqual('invalid_request', json.loads(body)['error']) def test_unsupported_response_type(self): self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' # Authorization code grant self.assertRaises(errors.UnsupportedResponseTypeError, self.web.validate_authorization_request, 'https://i.b/auth?response_type=foo&client_id=foo') # Implicit grant self.assertRaises(errors.UnsupportedResponseTypeError, self.mobile.validate_authorization_request, 'https://i.b/auth?response_type=foo&client_id=foo') def test_invalid_scope(self): self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' self.validator.validate_scopes.return_value = False self.validator.authenticate_client.side_effect = self.set_client # Authorization code grant self.assertRaises(errors.InvalidScopeError, self.web.validate_authorization_request, 'https://i.b/auth?response_type=code&client_id=foo') # Implicit grant self.assertRaises( errors.InvalidScopeError, self.mobile.validate_authorization_request, 'https://i.b/auth?response_type=token&client_id=foo') # Password credentials grant _, body, _ = self.legacy.create_token_response( 'https://i.b/token', body='grant_type=password&username=foo&password=bar') self.assertEqual('invalid_scope', json.loads(body)['error']) # Client credentials grant _, body, _ = self.backend.create_token_response( 'https://i.b/token', body='grant_type=client_credentials') self.assertEqual('invalid_scope', json.loads(body)['error']) def test_server_error(self): def raise_error(*args, **kwargs): raise ValueError() self.validator.validate_client_id.side_effect = raise_error self.validator.authenticate_client.side_effect = raise_error self.validator.get_default_redirect_uri.return_value = 'https://i.b/cb' # Authorization code grant self.web.catch_errors = True _, _, s = self.web.create_authorization_response( 'https://i.b/auth?client_id=foo&response_type=code', scopes=['foo']) self.assertEqual(s, 500) _, _, s = self.web.create_token_response( 'https://i.b/token', body='grant_type=authorization_code&code=foo', scopes=['foo']) self.assertEqual(s, 500) # Implicit grant self.mobile.catch_errors = True _, _, s = self.mobile.create_authorization_response( 'https://i.b/auth?client_id=foo&response_type=token', scopes=['foo']) self.assertEqual(s, 500) # Password credentials grant self.legacy.catch_errors = True _, _, s = self.legacy.create_token_response( 'https://i.b/token', body='grant_type=password&username=foo&password=foo') self.assertEqual(s, 500) # Client credentials grant self.backend.catch_errors = True _, _, s = self.backend.create_token_response( 'https://i.b/token', body='grant_type=client_credentials') self.assertEqual(s, 500) def test_temporarily_unavailable(self): # Authorization code grant self.web.available = False _, _, s = self.web.create_authorization_response( 'https://i.b/auth?client_id=foo&response_type=code', scopes=['foo']) self.assertEqual(s, 503) _, _, s = self.web.create_token_response( 'https://i.b/token', body='grant_type=authorization_code&code=foo', scopes=['foo']) self.assertEqual(s, 503) # Implicit grant self.mobile.available = False _, _, s = self.mobile.create_authorization_response( 'https://i.b/auth?client_id=foo&response_type=token', scopes=['foo']) self.assertEqual(s, 503) # Password credentials grant self.legacy.available = False _, _, s = self.legacy.create_token_response( 'https://i.b/token', body='grant_type=password&username=foo&password=foo') self.assertEqual(s, 503) # Client credentials grant self.backend.available = False _, _, s = self.backend.create_token_response( 'https://i.b/token', body='grant_type=client_credentials') self.assertEqual(s, 503) def test_invalid_client(self): self.validator.authenticate_client.return_value = False self.validator.authenticate_client_id.return_value = False # Authorization code grant _, body, _ = self.web.create_token_response( 'https://i.b/token', body='grant_type=authorization_code&code=foo') self.assertEqual('invalid_client', json.loads(body)['error']) # Password credentials grant _, body, _ = self.legacy.create_token_response( 'https://i.b/token', body='grant_type=password&username=foo&password=bar') self.assertEqual('invalid_client', json.loads(body)['error']) # Client credentials grant _, body, _ = self.legacy.create_token_response( 'https://i.b/token', body='grant_type=client_credentials') self.assertEqual('invalid_client', json.loads(body)['error']) def test_invalid_grant(self): self.validator.authenticate_client.side_effect = self.set_client # Authorization code grant self.validator.validate_code.return_value = False _, body, _ = self.web.create_token_response( 'https://i.b/token', body='grant_type=authorization_code&code=foo') self.assertEqual('invalid_grant', json.loads(body)['error']) # Password credentials grant self.validator.validate_user.return_value = False _, body, _ = self.legacy.create_token_response( 'https://i.b/token', body='grant_type=password&username=foo&password=bar') self.assertEqual('invalid_grant', json.loads(body)['error']) def test_unsupported_grant_type(self): self.validator.authenticate_client.side_effect = self.set_client # Authorization code grant _, body, _ = self.web.create_token_response( 'https://i.b/token', body='grant_type=bar&code=foo') self.assertEqual('unsupported_grant_type', json.loads(body)['error']) # Password credentials grant _, body, _ = self.legacy.create_token_response( 'https://i.b/token', body='grant_type=bar&username=foo&password=bar') self.assertEqual('unsupported_grant_type', json.loads(body)['error']) # Client credentials grant _, body, _ = self.backend.create_token_response('https://i.b/token', body='grant_type=bar') self.assertEqual('unsupported_grant_type', json.loads(body)['error'])
def __init__(self, request): self.request = request self.user_svc = self.request.find_service(name='user') validator = self.request.find_service(name='oauth_validator') self.oauth = WebApplicationServer(validator)
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')
def __init__(self): super(OAuth2ProviderDecorator, self).__init__() validator = WebValidator() self._resource_endpoint = WebApplicationServer(validator)
# request.client. The two former will be set when you validate # the authorization code. Don't forget to save both the # access_token and the refresh_token and set expiration for the # access_token to now + expires_in seconds. pass def invalidate_authorization_code(self, client_id, code, request, *args, **kwargs): # Authorization codes are use once, invalidate it when a Bearer token # has been acquired. pass # Protected resource request def validate_bearer_token(self, token, scopes, request): # Remember to check expiration and scope membership pass # Token refresh request def get_original_scopes(self, refresh_token, request, *args, **kwargs): # Obtain the token associated with the given refresh_token and # return its scopes, these will be passed on to the refreshed # access token if the client did not specify a scope during the # request. pass validator = SkeletonValidator() server = WebApplicationServer(validator)
class PreservationTest(TestCase): DEFAULT_REDIRECT_URI = "http://i.b./path" def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = self.DEFAULT_REDIRECT_URI self.validator.authenticate_client.side_effect = self.set_client self.web = WebApplicationServer(self.validator) self.mobile = MobileApplicationServer(self.validator) def set_state(self, state): def set_request_state(client_id, code, client, request): request.state = state return True return set_request_state def set_client(self, request): request.client = mock.MagicMock() request.client.client_id = "mocked" return True def test_state_preservation(self): auth_uri = "http://example.com/path?state=xyz&client_id=abc&response_type=" token_uri = "http://example.com/path" # authorization grant h, _, s = self.web.create_authorization_response(auth_uri + "code", scopes=["random"]) self.assertEqual(s, 302) self.assertIn("Location", h) code = get_query_credentials(h["Location"])["code"][0] self.validator.validate_code.side_effect = self.set_state("xyz") _, body, _ = self.web.create_token_response(token_uri, body="grant_type=authorization_code&code=%s" % code) self.assertEqual(json.loads(body)["state"], "xyz") # implicit grant h, _, s = self.mobile.create_authorization_response(auth_uri + "token", scopes=["random"]) self.assertEqual(s, 302) self.assertIn("Location", h) self.assertEqual(get_fragment_credentials(h["Location"])["state"][0], "xyz") def test_redirect_uri_preservation(self): auth_uri = "http://example.com/path?redirect_uri=http%3A%2F%2Fi.b%2Fpath&client_id=abc" redirect_uri = "http://i.b/path" token_uri = "http://example.com/path" # authorization grant h, _, s = self.web.create_authorization_response(auth_uri + "&response_type=code", scopes=["random"]) self.assertEqual(s, 302) self.assertIn("Location", h) self.assertTrue(h["Location"].startswith(redirect_uri)) # confirm_redirect_uri should return false if the redirect uri # was given in the authorization but not in the token request. self.validator.confirm_redirect_uri.return_value = False 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)["error"], "access_denied") # implicit grant h, _, s = self.mobile.create_authorization_response(auth_uri + "&response_type=token", scopes=["random"]) self.assertEqual(s, 302) self.assertIn("Location", h) self.assertTrue(h["Location"].startswith(redirect_uri)) def test_invalid_redirect_uri(self): auth_uri = "http://example.com/path?redirect_uri=http%3A%2F%2Fi.b%2Fpath&client_id=abc" self.validator.validate_redirect_uri.return_value = False # authorization grant self.assertRaises( errors.MismatchingRedirectURIError, self.web.create_authorization_response, auth_uri + "&response_type=code", scopes=["random"], ) # implicit grant self.assertRaises( errors.MismatchingRedirectURIError, self.mobile.create_authorization_response, auth_uri + "&response_type=token", scopes=["random"], ) def test_default_uri(self): auth_uri = "http://example.com/path?state=xyz&client_id=abc" self.validator.get_default_redirect_uri.return_value = None # authorization grant self.assertRaises( errors.MissingRedirectURIError, self.web.create_authorization_response, auth_uri + "&response_type=code", scopes=["random"], ) # implicit grant self.assertRaises( errors.MissingRedirectURIError, self.mobile.create_authorization_response, auth_uri + "&response_type=token", scopes=["random"], )
body = urllib.parse.urlencode(req.params) else: body = req.stream.read() uri = url_fix(req.uri) return uri, req.method, body, req.headers def patch_response(resp: falcon.Response, headers, body, status): if body: resp.body = body resp.set_headers(headers) if isinstance(status, int): status = getattr(falcon, 'HTTP_{}'.format(status)) resp.status = status return resp auth_endpoint = WebApplicationServer(SimpleRequestValidator()) app = falcon.API() app.add_route('/oauth/authorize', AuthorizeHandler(authorization_endpoint=auth_endpoint)) app.add_route('/oauth/token', TokenHandler(authorization_endpoint=auth_endpoint)) app.add_route('/oauth/callback', CallbackHandler()) app.add_route('/oauth/error', CallbackHandler()) if __name__ == '__main__': from wsgiref.simple_server import make_server service = make_server('localhost', 8000, app) service.serve_forever()
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')
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')
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'])
from benwaonline_auth.database import db from benwaonline_auth.models import User from benwaonline_auth.schemas import UserSchema from benwaonline_auth.oauth import twitter from benwaonline_auth.bwoauth import auth from benwaonline_auth.bwoauth.core import ( BenwaValidator, generate_jwt_token, generate_refresh_token, ) validator = BenwaValidator() server = WebApplicationServer( validator, token_generator=generate_jwt_token, refresh_token_generator=generate_refresh_token, ) @auth.errorhandler(errors.FatalClientError) def handle_invalid_usage(error): """Error handler.""" response = dict(error.twotuples) params = { "redirect_uri": error.redirect_uri, "client_id": error.client_id, "scopes": error.scopes, } return jsonify({**response, **params}), 500
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')
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')
def initialize(self): # 初始化 oauth2 后端服务 self._refresh_endpoint = WebApplicationServer(WebValidator()) self._error_uri = self.reverse_url('web-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.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) 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 set_username(self, username, password, client, request): 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_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')
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.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) 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 set_username(self, username, password, client, request): 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_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')
import tornado.web from oauthlib.oauth2 import WebApplicationServer from tornado_oauth_manager.oauth import SkeletonValidator server = WebApplicationServer(SkeletonValidator()) class AuthorizationHandler(tornado.web.RequestHandler): def get(self): client_id = self.get_argument('client_id') scopes, credentials = server.validate_authorization_request( self.request.uri, self.request.method, self.request.body, self.request.headers) self.write('<h1> Authorize access to %s </h1>' % client_id) self.write('<form method="POST" action="/authorize">') for scope in scopes or []: self.write('<input type="checkbox" name="scopes" ' 'value="%s"/> %s' % (scope, scope)) self.write('<input type="submit" value="Authorize"/>') def post(self): scopes = self.get_arguments('scopes') credentials = {'user': '******'} headers, body, status = server.create_authorization_response( self.request.uri, self.request.method, self.request.body, self.request.headers, scopes, credentials) self.write(repr((headers, body, status)))
class PreservationTest(TestCase): DEFAULT_REDIRECT_URI = 'http://i.b./path' def setUp(self): self.validator = mock.MagicMock(spec=RequestValidator) self.validator.get_default_redirect_uri.return_value = self.DEFAULT_REDIRECT_URI self.validator.authenticate_client.side_effect = self.set_client self.web = WebApplicationServer(self.validator) self.mobile = MobileApplicationServer(self.validator) def set_state(self, state): def set_request_state(client_id, code, client, request): request.state = state return True return set_request_state def set_client(self, request): request.client = mock.MagicMock() request.client.client_id = 'mocked' return True def test_state_preservation(self): auth_uri = 'http://example.com/path?state=xyz&client_id=abc&response_type=' token_uri = 'http://example.com/path' # authorization grant h, _, s = self.web.create_authorization_response( auth_uri + 'code', scopes=['random']) self.assertEqual(s, 302) self.assertIn('Location', h) code = get_query_credentials(h['Location'])['code'][0] self.validator.validate_code.side_effect = self.set_state('xyz') _, body, _ = self.web.create_token_response(token_uri, body='grant_type=authorization_code&code=%s' % code) self.assertEqual(json.loads(body)['state'], 'xyz') # implicit grant h, _, s = self.mobile.create_authorization_response( auth_uri + 'token', scopes=['random']) self.assertEqual(s, 302) self.assertIn('Location', h) self.assertEqual(get_fragment_credentials(h['Location'])['state'][0], 'xyz') def test_redirect_uri_preservation(self): auth_uri = 'http://example.com/path?redirect_uri=http%3A%2F%2Fi.b%2Fpath&client_id=abc' redirect_uri = 'http://i.b/path' token_uri = 'http://example.com/path' # authorization grant h, _, s = self.web.create_authorization_response( auth_uri + '&response_type=code', scopes=['random']) self.assertEqual(s, 302) self.assertIn('Location', h) self.assertTrue(h['Location'].startswith(redirect_uri)) # confirm_redirect_uri should return false if the redirect uri # was given in the authorization but not in the token request. self.validator.confirm_redirect_uri.return_value = False 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)['error'], 'invalid_request') # implicit grant h, _, s = self.mobile.create_authorization_response( auth_uri + '&response_type=token', scopes=['random']) self.assertEqual(s, 302) self.assertIn('Location', h) self.assertTrue(h['Location'].startswith(redirect_uri)) def test_invalid_redirect_uri(self): auth_uri = 'http://example.com/path?redirect_uri=http%3A%2F%2Fi.b%2Fpath&client_id=abc' self.validator.validate_redirect_uri.return_value = False # authorization grant self.assertRaises(errors.MismatchingRedirectURIError, self.web.create_authorization_response, auth_uri + '&response_type=code', scopes=['random']) # implicit grant self.assertRaises(errors.MismatchingRedirectURIError, self.mobile.create_authorization_response, auth_uri + '&response_type=token', scopes=['random']) def test_default_uri(self): auth_uri = 'http://example.com/path?state=xyz&client_id=abc' self.validator.get_default_redirect_uri.return_value = None # authorization grant self.assertRaises(errors.MissingRedirectURIError, self.web.create_authorization_response, auth_uri + '&response_type=code', scopes=['random']) # implicit grant self.assertRaises(errors.MissingRedirectURIError, self.mobile.create_authorization_response, auth_uri + '&response_type=token', scopes=['random'])
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"])