def test_verify_requests_uri(self): self.service_context.provider_info = {'issuer': 'https://example.com/'} url_list = self.service_context.generate_request_uris('/leading') sp = urlsplit(url_list[0]) p = sp.path.split('/') assert p[0] == '' assert p[1] == 'leading' assert len(p) == 3 srvcntx = ServiceContext().load( self.service_context.dump(exclude_attributes=["service_context"])) # different for different OPs srvcntx.provider_info = {'issuer': 'https://op.example.org/'} url_list = srvcntx.generate_request_uris('/leading') sp = urlsplit(url_list[0]) np = sp.path.split('/') assert np[0] == '' assert np[1] == 'leading' assert len(np) == 3 assert np[2] != p[2]
class TestClientInfo(object): @pytest.fixture(autouse=True) def create_client_info_instance(self): config = { 'client_id': 'client_id', 'issuer': 'issuer', 'client_secret': 'longenoughsupersecret', 'base_url': 'https://example.com', 'requests_dir': 'requests' } self.service_context = ServiceContext(config=config) def test_registration_userinfo_sign_enc_algs(self): self.service_context.set( 'behaviour', { "application_type": "web", "redirect_uris": [ "https://client.example.org/callback", "https://client.example.org/callback2" ], "token_endpoint_auth_method": "client_secret_basic", "jwks_uri": "https://client.example.org/my_public_keys.jwks", "userinfo_encrypted_response_alg": "RSA1_5", "userinfo_encrypted_response_enc": "A128CBC-HS256" }) srvcntx = ServiceContext().load( self.service_context.dump(exclude_attributes=["service_context"])) assert srvcntx.get_sign_alg('userinfo') is None assert srvcntx.get_enc_alg_enc('userinfo') == { 'alg': 'RSA1_5', 'enc': 'A128CBC-HS256' } def test_registration_request_object_sign_enc_algs(self): self.service_context.behaviour = { "application_type": "web", "redirect_uris": [ "https://client.example.org/callback", "https://client.example.org/callback2" ], "token_endpoint_auth_method": "client_secret_basic", "jwks_uri": "https://client.example.org/my_public_keys.jwks", "userinfo_encrypted_response_alg": "RSA1_5", "userinfo_encrypted_response_enc": "A128CBC-HS256", "request_object_signing_alg": "RS384" } srvcntx = ServiceContext().load( self.service_context.dump(exclude_attributes=["service_context"])) res = srvcntx.get_enc_alg_enc('userinfo') # 'sign':'RS256' is an added default assert res == {'alg': 'RSA1_5', 'enc': 'A128CBC-HS256'} assert srvcntx.get_sign_alg('request_object') == 'RS384' def test_registration_id_token_sign_enc_algs(self): self.service_context.behaviour = { "application_type": "web", "redirect_uris": [ "https://client.example.org/callback", "https://client.example.org/callback2" ], "token_endpoint_auth_method": "client_secret_basic", "jwks_uri": "https://client.example.org/my_public_keys.jwks", "userinfo_encrypted_response_alg": "RSA1_5", "userinfo_encrypted_response_enc": "A128CBC-HS256", "request_object_signing_alg": "RS384", 'id_token_encrypted_response_alg': 'ECDH-ES', 'id_token_encrypted_response_enc': "A128GCM", 'id_token_signed_response_alg': "ES384", } srvcntx = ServiceContext().load( self.service_context.dump(exclude_attributes=["service_context"])) # 'sign':'RS256' is an added default assert srvcntx.get_enc_alg_enc('userinfo') == { 'alg': 'RSA1_5', 'enc': 'A128CBC-HS256' } assert srvcntx.get_sign_alg('request_object') == 'RS384' assert srvcntx.get_enc_alg_enc('id_token') == { 'alg': 'ECDH-ES', 'enc': 'A128GCM' } def test_verify_alg_support(self): self.service_context.provider_info = { "version": "3.0", "issuer": "https://server.example.com", "authorization_endpoint": "https://server.example.com/connect/authorize", "token_endpoint": "https://server.example.com/connect/token", "token_endpoint_auth_methods_supported": ["client_secret_basic", "private_key_jwt"], "token_endpoint_auth_signing_alg_values_supported": ["RS256", "ES256"], "userinfo_endpoint": "https://server.example.com/connect/userinfo", "check_session_iframe": "https://server.example.com/connect/check_session", "end_session_endpoint": "https://server.example.com/connect/end_session", "jwks_uri": "https://server.example.com/jwks.json", "registration_endpoint": "https://server.example.com/connect/register", "scopes_supported": [ "openid", "profile", "email", "address", "phone", "offline_access" ], "response_types_supported": ["code", "code id_token", "id_token", "token id_token"], "acr_values_supported": ["urn:mace:incommon:iap:silver", "urn:mace:incommon:iap:bronze"], "subject_types_supported": ["public", "pairwise"], "userinfo_signing_alg_values_supported": ["RS256", "ES256", "HS256"], "userinfo_encryption_alg_values_supported": ["RSA1_5", "A128KW"], "userinfo_encryption_enc_values_supported": ["A128CBC+HS256", "A128GCM"], "id_token_signing_alg_values_supported": ["RS256", "ES256", "HS256"], "id_token_encryption_alg_values_supported": ["RSA1_5", "A128KW"], "id_token_encryption_enc_values_supported": ["A128CBC+HS256", "A128GCM"], "request_object_signing_alg_values_supported": ["none", "RS256", "ES256"], "display_values_supported": ["page", "popup"], "claim_types_supported": ["normal", "distributed"], "claims_supported": [ "sub", "iss", "auth_time", "acr", "name", "given_name", "family_name", "nickname", "profile", "picture", "website", "email", "email_verified", "locale", "zoneinfo", "http://example.info/claims/groups" ], "claims_parameter_supported": True, "service_documentation": "http://server.example.com/connect/service_documentation.html", "ui_locales_supported": ["en-US", "en-GB", "en-CA", "fr-FR", "fr-CA"] } srvcntx = ServiceContext().load( self.service_context.dump(exclude_attributes=["service_context"])) assert verify_alg_support(srvcntx, 'RS256', 'id_token', 'signing_alg') assert verify_alg_support(srvcntx, 'RS512', 'id_token', 'signing_alg') is False assert verify_alg_support(srvcntx, 'RSA1_5', 'userinfo', 'encryption_alg') # token_endpoint_auth_signing_alg_values_supported assert verify_alg_support(srvcntx, 'ES256', 'token_endpoint_auth', 'signing_alg') def test_verify_requests_uri(self): self.service_context.provider_info = {'issuer': 'https://example.com/'} url_list = self.service_context.generate_request_uris('/leading') sp = urlsplit(url_list[0]) p = sp.path.split('/') assert p[0] == '' assert p[1] == 'leading' assert len(p) == 3 srvcntx = ServiceContext().load( self.service_context.dump(exclude_attributes=["service_context"])) # different for different OPs srvcntx.provider_info = {'issuer': 'https://op.example.org/'} url_list = srvcntx.generate_request_uris('/leading') sp = urlsplit(url_list[0]) np = sp.path.split('/') assert np[0] == '' assert np[1] == 'leading' assert len(np) == 3 assert np[2] != p[2] def test_import_keys_file(self): # Should only be one and that a symmetric key (client_secret) usable # for signing and encryption assert len(self.service_context.keyjar.get_issuer_keys('')) == 1 file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), 'salesforce.key')) keyspec = {'file': {'rsa': [file_path]}} self.service_context.import_keys(keyspec) srvcntx = ServiceContext().load( self.service_context.dump(exclude_attributes=["service_context"])) # Now there should be 2, the second a RSA key for signing assert len(srvcntx.keyjar.get_issuer_keys('')) == 2 def test_import_keys_file_json(self): # Should only be one and that a symmetric key (client_secret) usable # for signing and encryption assert len(self.service_context.keyjar.get_issuer_keys('')) == 1 file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), 'salesforce.key')) keyspec = {'file': {'rsa': [file_path]}} self.service_context.import_keys(keyspec) _sc_state = self.service_context.dump( exclude_attributes=["service_context"]) _jsc_state = json.dumps(_sc_state) _o_state = json.loads(_jsc_state) srvcntx = ServiceContext().load(_o_state) # Now there should be 2, the second a RSA key for signing assert len(srvcntx.keyjar.get_issuer_keys('')) == 2 def test_import_keys_url(self): assert len(self.service_context.keyjar.get_issuer_keys('')) == 1 # One EC key for signing key_def = [{"type": "EC", "crv": "P-256", "use": ["sig"]}] keyjar = build_keyjar(key_def) with responses.RequestsMock() as rsps: _jwks_url = 'https://foobar.com/jwks.json' rsps.add("GET", _jwks_url, body=keyjar.export_jwks_as_json(), status=200, adding_headers={"Content-Type": "application/json"}) keyspec = {'url': {'https://foobar.com': _jwks_url}} self.service_context.import_keys(keyspec) self.service_context.keyjar.update() srvcntx = ServiceContext().load( self.service_context.dump( exclude_attributes=["service_context"])) # Now there should be one belonging to https://example.com assert len( srvcntx.keyjar.get_issuer_keys('https://foobar.com')) == 1