Add end-to-end OIDC binding test
This commit is contained in:
		
							parent
							
								
									d47696b69c
								
							
						
					
					
						commit
						6736e69ebd
					
				
					 2 changed files with 39 additions and 9 deletions
				
			
		|  | @ -9,10 +9,23 @@ from Crypto.PublicKey import RSA | ||||||
| from httmock import urlmatch, HTTMock | from httmock import urlmatch, HTTMock | ||||||
| from jwkest.jwk import RSAKey | from jwkest.jwk import RSAKey | ||||||
| 
 | 
 | ||||||
| from app import app | from app import app, authentication | ||||||
| from data import model | from data import model | ||||||
| from endpoints.oauthlogin import oauthlogin as oauthlogin_bp | from endpoints.oauthlogin import oauthlogin as oauthlogin_bp | ||||||
| from test.test_endpoints import EndpointTestCase | from test.test_endpoints import EndpointTestCase | ||||||
|  | from test.test_ldap import mock_ldap | ||||||
|  | 
 | ||||||
|  | class AuthForTesting(object): | ||||||
|  |   def __init__(self, auth_engine): | ||||||
|  |     self.auth_engine = auth_engine | ||||||
|  |     self.existing_state = None | ||||||
|  | 
 | ||||||
|  |   def __enter__(self): | ||||||
|  |     self.existing_state = authentication.state | ||||||
|  |     authentication.state = self.auth_engine | ||||||
|  | 
 | ||||||
|  |   def __exit__(self, type, value, traceback): | ||||||
|  |     authentication.state = self.existing_state | ||||||
| 
 | 
 | ||||||
| try: | try: | ||||||
|   app.register_blueprint(oauthlogin_bp, url_prefix='/oauth2') |   app.register_blueprint(oauthlogin_bp, url_prefix='/oauth2') | ||||||
|  | @ -22,16 +35,18 @@ except ValueError: | ||||||
| 
 | 
 | ||||||
| class OAuthLoginTestCase(EndpointTestCase): | class OAuthLoginTestCase(EndpointTestCase): | ||||||
|   def invoke_oauth_tests(self, callback_endpoint, attach_endpoint, service_name, service_ident, |   def invoke_oauth_tests(self, callback_endpoint, attach_endpoint, service_name, service_ident, | ||||||
|                          new_username): |                          new_username, test_attach=True): | ||||||
|     # Test callback. |     # Test callback. | ||||||
|     created = self.invoke_oauth_test(callback_endpoint, service_name, service_ident, new_username) |     created = self.invoke_oauth_test(callback_endpoint, service_name, service_ident, new_username) | ||||||
| 
 | 
 | ||||||
|     # Delete the created user. |     # Delete the created user. | ||||||
|  |     self.assertNotEquals(created.username, 'devtable') | ||||||
|     model.user.delete_user(created, []) |     model.user.delete_user(created, []) | ||||||
| 
 | 
 | ||||||
|     # Test attach. |     # Test attach. | ||||||
|     self.login('devtable', 'password') |     if test_attach: | ||||||
|     self.invoke_oauth_test(attach_endpoint, service_name, service_ident, 'devtable') |       self.login('devtable', 'password') | ||||||
|  |       self.invoke_oauth_test(attach_endpoint, service_name, service_ident, 'devtable') | ||||||
| 
 | 
 | ||||||
|   def invoke_oauth_test(self, endpoint_name, service_name, service_ident, username): |   def invoke_oauth_test(self, endpoint_name, service_name, service_ident, username): | ||||||
|     # No CSRF. |     # No CSRF. | ||||||
|  | @ -111,7 +126,7 @@ class OAuthLoginTestCase(EndpointTestCase): | ||||||
|       self.invoke_oauth_tests('github_oauth_callback', 'github_oauth_attach', 'github', |       self.invoke_oauth_tests('github_oauth_callback', 'github_oauth_attach', 'github', | ||||||
|                               'someid', 'someusername') |                               'someid', 'someusername') | ||||||
| 
 | 
 | ||||||
|   def test_oidc_auth(self): |   def _get_oidc_mocks(self): | ||||||
|     private_key = RSA.generate(2048) |     private_key = RSA.generate(2048) | ||||||
|     generatedjwk = RSAKey(key=private_key.publickey()).serialize() |     generatedjwk = RSAKey(key=private_key.publickey()).serialize() | ||||||
|     kid = 'somekey' |     kid = 'somekey' | ||||||
|  | @ -123,7 +138,7 @@ class OAuthLoginTestCase(EndpointTestCase): | ||||||
|       'nbf': int(time.time()), |       'nbf': int(time.time()), | ||||||
|       'iat': int(time.time()), |       'iat': int(time.time()), | ||||||
|       'exp': int(time.time() + 600), |       'exp': int(time.time() + 600), | ||||||
|       'sub': 'cooluser', |       'sub': 'cool.user', | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     token_headers = { |     token_headers = { | ||||||
|  | @ -143,7 +158,7 @@ class OAuthLoginTestCase(EndpointTestCase): | ||||||
|     @urlmatch(netloc=r'fakeoidc', path='/user') |     @urlmatch(netloc=r'fakeoidc', path='/user') | ||||||
|     def user_handler(_, __): |     def user_handler(_, __): | ||||||
|       content = { |       content = { | ||||||
|         'sub': 'cooluser', |         'sub': 'cool.user', | ||||||
|         'preferred_username': 'someusername', |         'preferred_username': 'someusername', | ||||||
|         'email': 'someemail@example.com', |         'email': 'someemail@example.com', | ||||||
|         'email_verified': True, |         'email_verified': True, | ||||||
|  | @ -169,9 +184,23 @@ class OAuthLoginTestCase(EndpointTestCase): | ||||||
|       } |       } | ||||||
|       return py_json.dumps(content) |       return py_json.dumps(content) | ||||||
| 
 | 
 | ||||||
|     with HTTMock(discovery_handler, jwks_handler, token_handler, user_handler): |     return (discovery_handler, jwks_handler, token_handler, user_handler) | ||||||
|  | 
 | ||||||
|  |   def test_oidc_database_auth(self): | ||||||
|  |     oidc_mocks = self._get_oidc_mocks() | ||||||
|  |     with HTTMock(*oidc_mocks): | ||||||
|       self.invoke_oauth_tests('testoidc_oauth_callback', 'testoidc_oauth_attach', 'testoidc', |       self.invoke_oauth_tests('testoidc_oauth_callback', 'testoidc_oauth_attach', 'testoidc', | ||||||
|                               'cooluser', 'someusername') |                               'cool.user', 'someusername') | ||||||
|  | 
 | ||||||
|  |   def test_oidc_ldap_auth(self): | ||||||
|  |     # Test with database auth. | ||||||
|  |     oidc_mocks = self._get_oidc_mocks() | ||||||
|  |     with mock_ldap() as ldap: | ||||||
|  |       with AuthForTesting(ldap): | ||||||
|  |         with HTTMock(*oidc_mocks): | ||||||
|  |           self.invoke_oauth_tests('testoidc_oauth_callback', 'testoidc_oauth_attach', 'testoidc', | ||||||
|  |                                   'cool.user', 'cool_user', test_attach=False) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|   unittest.main() |   unittest.main() | ||||||
|  |  | ||||||
|  | @ -87,6 +87,7 @@ class TestConfig(DefaultConfig): | ||||||
|     'CLIENT_SECRET': 'bar', |     'CLIENT_SECRET': 'bar', | ||||||
|     'OIDC_SERVER': 'http://fakeoidc', |     'OIDC_SERVER': 'http://fakeoidc', | ||||||
|     'DEBUGGING': True, |     'DEBUGGING': True, | ||||||
|  |     'LOGIN_BINDING_FIELD': 'sub', | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   RECAPTCHA_SITE_KEY = 'somekey' |   RECAPTCHA_SITE_KEY = 'somekey' | ||||||
|  |  | ||||||
		Reference in a new issue