示例#1
0
    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]
示例#2
0
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