def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant(request_validator=self.mock_validator)
def test_custom_auth_validators_unsupported(self): authval1, authval2 = mock.Mock(), mock.Mock() expected = ('RefreshTokenGrant does not support authorization ' 'validators. Use token validators instead.') with self.assertRaises(ValueError) as caught: RefreshTokenGrant(self.mock_validator, pre_auth=[authval1]) self.assertEqual(caught.exception.args[0], expected) with self.assertRaises(ValueError) as caught: RefreshTokenGrant(self.mock_validator, post_auth=[authval2]) self.assertEqual(caught.exception.args[0], expected) with self.assertRaises(AttributeError): self.auth.custom_validators.pre_auth.append(authval1) with self.assertRaises(AttributeError): self.auth.custom_validators.pre_auth.append(authval2)
def __init__(self, request_validator, oidc_token_handler): implicit_grant = ImplicitGrant(request_validator) refresh_grant = RefreshTokenGrant(request_validator) oidc_code_grant = OIDCAuthorizationCodeGrant(request_validator, oidc_token_handler) oidc_implicit_grant = OIDCImplicitGrant(request_validator, oidc_token_handler) bearer_token_handler = BearerToken(request_validator) AuthorizationEndpoint.__init__(self, default_response_type=oidc_code_grant, default_token_type=bearer_token_handler, response_types={ 'code': oidc_code_grant, 'token': implicit_grant, 'id_token token': oidc_implicit_grant, 'token id_token': oidc_implicit_grant, }) TokenEndpoint.__init__(self, default_grant_type=oidc_code_grant, default_token_type=bearer_token_handler, grant_types={ 'authorization_code': oidc_code_grant, 'refresh_token': refresh_grant, })
def __init__(self, request_validator, token_expires_in=None, token_generator=None, refresh_token_generator=None, *args, **kwargs): auth_grant = OrgAuthorizationCodeGrant(request_validator) implicit_grant = OrgImplicitGrant(request_validator) password_grant = OrgResourceOwnerPasswordCredentialsGrant( request_validator) credentials_grant = ClientCredentialsGrant(request_validator) refresh_grant = RefreshTokenGrant(request_validator) bearer = BearerToken(request_validator, token_generator, token_expires_in, refresh_token_generator) AuthorizationEndpoint.__init__(self, default_response_type='code', response_types={ 'code': auth_grant, 'token': implicit_grant, }, default_token_type=bearer) TokenEndpoint.__init__(self, default_grant_type='authorization_code', grant_types={ 'authorization_code': auth_grant, 'password': password_grant, 'client_credentials': credentials_grant, 'refresh_token': refresh_grant, }, default_token_type=bearer) ResourceEndpoint.__init__(self, default_token='Bearer', token_types={'Bearer': bearer}) RevocationEndpoint.__init__(self, request_validator)
def __init__(self, request_validator, token_generator=None, token_expires_in=None, refresh_token_generator=None, **kwargs): """Construct a new web application server. :param request_validator: An implementation of oauthlib.oauth2.RequestValidator. :param token_expires_in: An int or a function to generate a token expiration offset (in seconds) given a oauthlib.common.Request object. :param token_generator: A function to generate a token from a request. :param refresh_token_generator: A function to generate a token from a request for the refresh token. :param kwargs: Extra parameters to pass to authorization-, token-, resource-, and revocation-endpoint constructors. """ auth_grant = AuthorizationCodeGrant(request_validator) refresh_grant = RefreshTokenGrant(request_validator) bearer = BearerToken(request_validator, token_generator, token_expires_in, refresh_token_generator) AuthorizationEndpoint.__init__(self, default_response_type='code', response_types={'code': auth_grant}, default_token_type=bearer) TokenEndpoint.__init__(self, default_grant_type='authorization_code', grant_types={ 'authorization_code': auth_grant, 'refresh_token': refresh_grant, }, default_token_type=bearer) ResourceEndpoint.__init__(self, default_token='Bearer', token_types={'Bearer': bearer}) RevocationEndpoint.__init__(self, request_validator)
def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant( request_validator=self.mock_validator)
def __init__(self, request_validator, token_expires_in=None, token_generator=None, refresh_token_generator=None, *args, **kwargs): """Construct a new all-grants-in-one server. :param request_validator: An implementation of oauthlib.oauth2.RequestValidator. :param token_expires_in: An int or a function to generate a token expiration offset (in seconds) given a oauthlib.common.Request object. :param token_generator: A function to generate a token from a request. :param refresh_token_generator: A function to generate a token from a request for the refresh token. :param kwargs: Extra parameters to pass to authorization-, token-, resource-, and revocation-endpoint constructors. """ self.auth_grant = OAuth2AuthorizationCodeGrant(request_validator) self.implicit_grant = OAuth2ImplicitGrant(request_validator) self.password_grant = ResourceOwnerPasswordCredentialsGrant( request_validator) self.credentials_grant = ClientCredentialsGrant(request_validator) self.refresh_grant = RefreshTokenGrant(request_validator) self.openid_connect_auth = AuthorizationCodeGrant(request_validator) self.openid_connect_implicit = ImplicitGrant(request_validator) self.openid_connect_hybrid = HybridGrant(request_validator) self.bearer = BearerToken(request_validator, token_generator, token_expires_in, refresh_token_generator) self.jwt = JWTToken(request_validator, token_generator, token_expires_in, refresh_token_generator) self.auth_grant_choice = AuthorizationCodeGrantDispatcher( default_grant=self.auth_grant, oidc_grant=self.openid_connect_auth) self.implicit_grant_choice = ImplicitTokenGrantDispatcher( default_grant=self.implicit_grant, oidc_grant=self.openid_connect_implicit) # See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Combinations for valid combinations # internally our AuthorizationEndpoint will ensure they can appear in any order for any valid combination AuthorizationEndpoint.__init__( self, default_response_type='code', response_types={ 'code': self.auth_grant_choice, 'token': self.implicit_grant_choice, 'id_token': self.openid_connect_implicit, 'id_token token': self.openid_connect_implicit, 'code token': self.openid_connect_hybrid, 'code id_token': self.openid_connect_hybrid, 'code id_token token': self.openid_connect_hybrid, 'none': self.auth_grant }, default_token_type=self.bearer) self.token_grant_choice = AuthorizationTokenGrantDispatcher( request_validator, default_grant=self.auth_grant, oidc_grant=self.openid_connect_auth) TokenEndpoint.__init__(self, default_grant_type='authorization_code', grant_types={ 'authorization_code': self.token_grant_choice, 'password': self.password_grant, 'client_credentials': self.credentials_grant, 'refresh_token': self.refresh_grant, }, default_token_type=self.bearer) ResourceEndpoint.__init__(self, default_token='Bearer', token_types={ 'Bearer': self.bearer, 'JWT': self.jwt }) RevocationEndpoint.__init__(self, request_validator) IntrospectEndpoint.__init__(self, request_validator) UserInfoEndpoint.__init__(self, request_validator)
class RefreshTokenGrantTest(TestCase): def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant(request_validator=self.mock_validator) def test_create_token_response(self): self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_create_token_inherit_scope(self): self.request.scope = None self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo bar') def test_invalid_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_scope') self.assertEqual(status_code, 401) def test_invalid_token(self): self.mock_validator.validate_refresh_token.return_value = False bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_grant') self.assertEqual(status_code, 400) def test_invalid_client(self): self.mock_validator.authenticate_client.return_value = False bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_client') self.assertEqual(status_code, 401)
def __init__(self, request_validator, token_expires_in=None, token_generator=None, refresh_token_generator=None, *args, **kwargs): """Construct a new all-grants-in-one server. :param request_validator: An implementation of oauthlib.oauth2.RequestValidator. :param token_expires_in: An int or a function to generate a token expiration offset (in seconds) given a oauthlib.common.Request object. :param token_generator: A function to generate a token from a request. :param refresh_token_generator: A function to generate a token from a request for the refresh token. :param kwargs: Extra parameters to pass to authorization-, token-, resource-, and revocation-endpoint constructors. """ auth_grant = AuthorizationCodeGrant(request_validator) implicit_grant = ImplicitGrant(request_validator) password_grant = ResourceOwnerPasswordCredentialsGrant( request_validator) credentials_grant = ClientCredentialsGrant(request_validator) refresh_grant = RefreshTokenGrant(request_validator) openid_connect_auth = OpenIDConnectAuthCode(request_validator) openid_connect_implicit = OpenIDConnectImplicit(request_validator) bearer = BearerToken(request_validator, token_generator, token_expires_in, refresh_token_generator) auth_grant_choice = AuthCodeGrantDispatcher( default_auth_grant=auth_grant, oidc_auth_grant=openid_connect_auth) # See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Combinations for valid combinations # noqa # internally our AuthorizationEndpoint will ensure they can appear in any order for any valid combination # noqa AuthorizationEndpoint.__init__( self, default_response_type='code', response_types={ 'code': auth_grant_choice, 'token': implicit_grant, 'id_token': openid_connect_implicit, 'id_token token': openid_connect_implicit, 'code token': openid_connect_auth, 'code id_token': openid_connect_auth, 'code token id_token': openid_connect_auth, 'none': auth_grant }, default_token_type=bearer) TokenEndpoint.__init__( self, default_grant_type='authorization_code', grant_types={ 'authorization_code': openid_connect_auth, 'password': password_grant, 'client_credentials': credentials_grant, 'refresh_token': refresh_grant, 'openid': openid_connect_auth }, default_token_type=bearer) ResourceEndpoint.__init__( self, default_token='Bearer', token_types={'Bearer': bearer}) RevocationEndpoint.__init__(self, request_validator)
class RefreshTokenGrantTest(TestCase): def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant(request_validator=self.mock_validator) def test_create_token_response(self): self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_create_token_inherit_scope(self): self.request.scope = None self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo bar') def test_invalid_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_scope') self.assertEqual(status_code, 401) def test_invalid_token(self): self.mock_validator.validate_refresh_token.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_grant') self.assertEqual(status_code, 400) def test_invalid_client(self): self.mock_validator.authenticate_client.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_client') self.assertEqual(status_code, 401) def test_authentication_required(self): """ ensure client_authentication_required() is properly called """ self.mock_validator.authenticate_client.return_value = False self.mock_validator.authenticate_client_id.return_value = False self.request.code = 'waffles' self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) self.mock_validator.client_authentication_required.assert_called_once_with( self.request) def test_invalid_grant_type(self): self.request.grant_type = 'wrong_type' self.assertRaises(errors.UnsupportedGrantTypeError, self.auth.validate_token_request, self.request) def test_authenticate_client_id(self): self.mock_validator.client_authentication_required.return_value = False self.request.refresh_token = mock.MagicMock() self.mock_validator.authenticate_client_id.return_value = False self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) def test_invalid_refresh_token(self): # invalid refresh token self.mock_validator.authenticate_client_id.return_value = True self.mock_validator.validate_refresh_token.return_value = False self.assertRaises(errors.InvalidGrantError, self.auth.validate_token_request, self.request) # no token provided del self.request.refresh_token self.assertRaises(errors.InvalidRequestError, self.auth.validate_token_request, self.request) def test_invalid_scope(self): self.mock_validator.validate_refresh_token.return_value = True self.assertRaises(errors.InvalidScopeError, self.auth.validate_token_request, self.request) def test_valid_token_request(self): self.request.scope = 'foo bar' self.mock_validator.get_original_scopes = mock.Mock() self.mock_validator.get_original_scopes.return_value = 'foo bar baz' self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, self.request.scope.split()) # all ok but without request.scope del self.request.scope self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, 'foo bar baz'.split())
class RefreshTokenGrantTest(TestCase): def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant( request_validator=self.mock_validator) def test_create_token_response(self): self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 1) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_custom_auth_validators_unsupported(self): authval1, authval2 = mock.Mock(), mock.Mock() expected = ('RefreshTokenGrant does not support authorization ' 'validators. Use token validators instead.') with self.assertRaises(ValueError) as caught: RefreshTokenGrant(self.mock_validator, pre_auth=[authval1]) self.assertEqual(caught.exception.args[0], expected) with self.assertRaises(ValueError) as caught: RefreshTokenGrant(self.mock_validator, post_auth=[authval2]) self.assertEqual(caught.exception.args[0], expected) with self.assertRaises(AttributeError): self.auth.custom_validators.pre_auth.append(authval1) with self.assertRaises(AttributeError): self.auth.custom_validators.pre_auth.append(authval2) def test_custom_token_validators(self): tknval1, tknval2 = mock.Mock(), mock.Mock() self.auth.custom_validators.pre_token.append(tknval1) self.auth.custom_validators.post_token.append(tknval2) bearer = BearerToken(self.mock_validator) self.auth.create_token_response(self.request, bearer) self.assertTrue(tknval1.called) self.assertTrue(tknval2.called) def test_create_token_inherit_scope(self): self.request.scope = None self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 1) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo bar') def test_create_token_within_original_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] self.mock_validator.is_within_original_scope.return_value = True bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 1) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_invalid_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] self.mock_validator.is_within_original_scope.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 0) self.assertEqual(token['error'], 'invalid_scope') self.assertEqual(status_code, 401) def test_invalid_token(self): self.mock_validator.validate_refresh_token.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 0) self.assertEqual(token['error'], 'invalid_grant') self.assertEqual(status_code, 401) def test_invalid_client(self): self.mock_validator.authenticate_client.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 0) self.assertEqual(token['error'], 'invalid_client') self.assertEqual(status_code, 401) def test_authentication_required(self): """ ensure client_authentication_required() is properly called """ self.mock_validator.authenticate_client.return_value = False self.mock_validator.authenticate_client_id.return_value = False self.request.code = 'waffles' self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) self.mock_validator.client_authentication_required.assert_called_once_with(self.request) def test_invalid_grant_type(self): self.request.grant_type = 'wrong_type' self.assertRaises(errors.UnsupportedGrantTypeError, self.auth.validate_token_request, self.request) def test_authenticate_client_id(self): self.mock_validator.client_authentication_required.return_value = False self.request.refresh_token = mock.MagicMock() self.mock_validator.authenticate_client_id.return_value = False self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) def test_invalid_refresh_token(self): # invalid refresh token self.mock_validator.authenticate_client_id.return_value = True self.mock_validator.validate_refresh_token.return_value = False self.assertRaises(errors.InvalidGrantError, self.auth.validate_token_request, self.request) # no token provided del self.request.refresh_token self.assertRaises(errors.InvalidRequestError, self.auth.validate_token_request, self.request) def test_invalid_scope_original_scopes_empty(self): self.mock_validator.validate_refresh_token.return_value = True self.mock_validator.is_within_original_scope.return_value = False self.assertRaises(errors.InvalidScopeError, self.auth.validate_token_request, self.request) def test_valid_token_request(self): self.request.scope = 'foo bar' self.mock_validator.get_original_scopes = mock.Mock() self.mock_validator.get_original_scopes.return_value = 'foo bar baz' self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, self.request.scope.split()) # all ok but without request.scope del self.request.scope self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, 'foo bar baz'.split())
class RefreshTokenGrantTest(TestCase): def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant( request_validator=self.mock_validator) def test_create_token_response(self): self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_create_token_inherit_scope(self): self.request.scope = None self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo bar') def test_invalid_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_scope') self.assertEqual(status_code, 401) def test_invalid_token(self): self.mock_validator.validate_refresh_token.return_value = False bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_grant') self.assertEqual(status_code, 400) def test_invalid_client(self): self.mock_validator.authenticate_client.return_value = False bearer = BearerToken(self.mock_validator) uri, headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_client') self.assertEqual(status_code, 401)
class RefreshTokenGrantTest(TestCase): def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant(request_validator=self.mock_validator) def test_create_token_response(self): self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 1) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_custom_auth_validators_unsupported(self): authval1, authval2 = mock.Mock(), mock.Mock() expected = ('RefreshTokenGrant does not support authorization ' 'validators. Use token validators instead.') with self.assertRaises(ValueError) as caught: RefreshTokenGrant(self.mock_validator, pre_auth=[authval1]) self.assertEqual(caught.exception.args[0], expected) with self.assertRaises(ValueError) as caught: RefreshTokenGrant(self.mock_validator, post_auth=[authval2]) self.assertEqual(caught.exception.args[0], expected) with self.assertRaises(AttributeError): self.auth.custom_validators.pre_auth.append(authval1) with self.assertRaises(AttributeError): self.auth.custom_validators.pre_auth.append(authval2) def test_custom_token_validators(self): tknval1, tknval2 = mock.Mock(), mock.Mock() self.auth.custom_validators.pre_token.append(tknval1) self.auth.custom_validators.post_token.append(tknval2) bearer = BearerToken(self.mock_validator) self.auth.create_token_response(self.request, bearer) self.assertTrue(tknval1.called) self.assertTrue(tknval2.called) def test_create_token_inherit_scope(self): self.request.scope = None self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 1) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo bar') def test_create_token_within_original_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] self.mock_validator.is_within_original_scope.return_value = True bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 1) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_invalid_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] self.mock_validator.is_within_original_scope.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 0) self.assertEqual(token['error'], 'invalid_scope') self.assertEqual(status_code, 401) def test_invalid_token(self): self.mock_validator.validate_refresh_token.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 0) self.assertEqual(token['error'], 'invalid_grant') self.assertEqual(status_code, 401) def test_invalid_client(self): self.mock_validator.authenticate_client.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(self.mock_validator.save_token.call_count, 0) self.assertEqual(token['error'], 'invalid_client') self.assertEqual(status_code, 401) def test_authentication_required(self): """ ensure client_authentication_required() is properly called """ self.mock_validator.authenticate_client.return_value = False self.mock_validator.authenticate_client_id.return_value = False self.request.code = 'waffles' self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) self.mock_validator.client_authentication_required.assert_called_once_with( self.request) def test_invalid_grant_type(self): self.request.grant_type = 'wrong_type' self.assertRaises(errors.UnsupportedGrantTypeError, self.auth.validate_token_request, self.request) def test_authenticate_client_id(self): self.mock_validator.client_authentication_required.return_value = False self.request.refresh_token = mock.MagicMock() self.mock_validator.authenticate_client_id.return_value = False self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) def test_invalid_refresh_token(self): # invalid refresh token self.mock_validator.authenticate_client_id.return_value = True self.mock_validator.validate_refresh_token.return_value = False self.assertRaises(errors.InvalidGrantError, self.auth.validate_token_request, self.request) # no token provided del self.request.refresh_token self.assertRaises(errors.InvalidRequestError, self.auth.validate_token_request, self.request) def test_invalid_scope_original_scopes_empty(self): self.mock_validator.validate_refresh_token.return_value = True self.mock_validator.is_within_original_scope.return_value = False self.assertRaises(errors.InvalidScopeError, self.auth.validate_token_request, self.request) def test_valid_token_request(self): self.request.scope = 'foo bar' self.mock_validator.get_original_scopes = mock.Mock() self.mock_validator.get_original_scopes.return_value = 'foo bar baz' self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, self.request.scope.split()) # all ok but without request.scope del self.request.scope self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, 'foo bar baz'.split())
class RefreshTokenGrantTest(TestCase): def setUp(self): mock_client = mock.MagicMock() mock_client.user.return_value = 'mocked user' self.request = Request('http://a.b/path') self.request.grant_type = 'refresh_token' self.request.refresh_token = 'lsdkfhj230' self.request.client = mock_client self.request.scope = 'foo' self.mock_validator = mock.MagicMock() self.auth = RefreshTokenGrant( request_validator=self.mock_validator) def test_create_token_response(self): self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_create_token_inherit_scope(self): self.request.scope = None self.mock_validator.get_original_scopes.return_value = ['foo', 'bar'] bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo bar') def test_create_token_within_original_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] self.mock_validator.is_within_original_scope.return_value = True bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertIn('access_token', token) self.assertIn('token_type', token) self.assertIn('expires_in', token) self.assertEqual(token['scope'], 'foo') def test_invalid_scope(self): self.mock_validator.get_original_scopes.return_value = ['baz'] self.mock_validator.is_within_original_scope.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_scope') self.assertEqual(status_code, 401) def test_invalid_token(self): self.mock_validator.validate_refresh_token.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_grant') self.assertEqual(status_code, 400) def test_invalid_client(self): self.mock_validator.authenticate_client.return_value = False bearer = BearerToken(self.mock_validator) headers, body, status_code = self.auth.create_token_response( self.request, bearer) token = json.loads(body) self.assertEqual(token['error'], 'invalid_client') self.assertEqual(status_code, 401) def test_authentication_required(self): """ ensure client_authentication_required() is properly called """ self.mock_validator.authenticate_client.return_value = False self.mock_validator.authenticate_client_id.return_value = False self.request.code = 'waffles' self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) self.mock_validator.client_authentication_required.assert_called_once_with(self.request) def test_invalid_grant_type(self): self.request.grant_type = 'wrong_type' self.assertRaises(errors.UnsupportedGrantTypeError, self.auth.validate_token_request, self.request) def test_authenticate_client_id(self): self.mock_validator.client_authentication_required.return_value = False self.request.refresh_token = mock.MagicMock() self.mock_validator.authenticate_client_id.return_value = False self.assertRaises(errors.InvalidClientError, self.auth.validate_token_request, self.request) def test_invalid_refresh_token(self): # invalid refresh token self.mock_validator.authenticate_client_id.return_value = True self.mock_validator.validate_refresh_token.return_value = False self.assertRaises(errors.InvalidGrantError, self.auth.validate_token_request, self.request) # no token provided del self.request.refresh_token self.assertRaises(errors.InvalidRequestError, self.auth.validate_token_request, self.request) def test_invalid_scope_original_scopes_empty(self): self.mock_validator.validate_refresh_token.return_value = True self.mock_validator.is_within_original_scope.return_value = False self.assertRaises(errors.InvalidScopeError, self.auth.validate_token_request, self.request) def test_valid_token_request(self): self.request.scope = 'foo bar' self.mock_validator.get_original_scopes = mock.Mock() self.mock_validator.get_original_scopes.return_value = 'foo bar baz' self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, self.request.scope.split()) # all ok but without request.scope del self.request.scope self.auth.validate_token_request(self.request) self.assertEqual(self.request.scopes, 'foo bar baz'.split())
def __init__(self, request_validator, token_expires_in=None, token_generator=None, refresh_token_generator=None, *args, **kwargs): """Construct a new all-grants-in-one server. :param request_validator: An implementation of oauthlib.oauth2.RequestValidator. :param token_expires_in: An int or a function to generate a token expiration offset (in seconds) given a oauthlib.common.Request object. :param token_generator: A function to generate a token from a request. :param refresh_token_generator: A function to generate a token from a request for the refresh token. :param kwargs: Extra parameters to pass to authorization-, token-, resource-, and revocation-endpoint constructors. """ auth_grant = OAuth2AuthorizationCodeGrant(request_validator) implicit_grant = OAuth2ImplicitGrant(request_validator) password_grant = ResourceOwnerPasswordCredentialsGrant( request_validator) credentials_grant = ClientCredentialsGrant(request_validator) refresh_grant = RefreshTokenGrant(request_validator) openid_connect_auth = AuthorizationCodeGrant(request_validator) openid_connect_implicit = ImplicitGrant(request_validator) openid_connect_hybrid = HybridGrant(request_validator) bearer = BearerToken( request_validator, token_generator, token_expires_in, refresh_token_generator, ) jwt = JWTToken( request_validator, token_generator, token_expires_in, refresh_token_generator, ) auth_grant_choice = AuthorizationCodeGrantDispatcher( default_grant=auth_grant, oidc_grant=openid_connect_auth) implicit_grant_choice = ImplicitTokenGrantDispatcher( default_grant=implicit_grant, oidc_grant=openid_connect_implicit) # See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Combinations for valid combinations # internally our AuthorizationEndpoint will ensure they can appear in any order for any valid combination AuthorizationEndpoint.__init__( self, default_response_type="code", response_types={ "code": auth_grant_choice, "token": implicit_grant_choice, "id_token": openid_connect_implicit, "id_token token": openid_connect_implicit, "code token": openid_connect_hybrid, "code id_token": openid_connect_hybrid, "code id_token token": openid_connect_hybrid, "none": auth_grant, }, default_token_type=bearer, ) token_grant_choice = AuthorizationTokenGrantDispatcher( request_validator, default_grant=auth_grant, oidc_grant=openid_connect_auth) TokenEndpoint.__init__( self, default_grant_type="authorization_code", grant_types={ "authorization_code": token_grant_choice, "password": password_grant, "client_credentials": credentials_grant, "refresh_token": refresh_grant, }, default_token_type=bearer, ) ResourceEndpoint.__init__(self, default_token="Bearer", token_types={ "Bearer": bearer, "JWT": jwt }) RevocationEndpoint.__init__(self, request_validator) IntrospectEndpoint.__init__(self, request_validator) UserInfoEndpoint.__init__(self, request_validator)