Exemple #1
0
    def test_identify(self):

        # Create a SAMLResponse
        ava = {
            "givenName": ["Derek"],
            "surname": ["Jeter"],
            "mail": ["*****@*****.**"]
        }

        resp_str = "\n".join(
            self.server.authn_response(
                ava, "id1", "http://lingon.catalogix.se:8087/",
                "urn:mace:example.com:saml:roland:sp",
                samlp.NameIDPolicy(format=saml.NAMEID_FORMAT_TRANSIENT,
                                   allow_create="true"),
                "*****@*****.**"))

        resp_str = base64.encodestring(resp_str)
        self.sp.outstanding_queries = {"id1": "http://www.example.com/service"}
        session_info = self.sp._eval_authn_response({},
                                                    {"SAMLResponse": resp_str})

        assert len(session_info) > 1
        assert session_info["came_from"] == 'http://www.example.com/service'
        assert session_info["ava"] == {
            'givenName': ['Derek'],
            'mail': ['*****@*****.**'],
            'sn': ['Jeter']
        }
Exemple #2
0
    def test_sign_then_encrypt_assertion2(self):
        # Begin with the IdPs side
        _sec = self.server.sec

        nameid_policy = samlp.NameIDPolicy(
            allow_create="false", format=saml.NAMEID_FORMAT_PERSISTENT)

        asser = Assertion({"givenName": "Derek", "surName": "Jeter"})
        assertion = asser.construct(
            self.client.config.entityid,
            "_012345",
            "http://lingon.catalogix.se:8087/",
            factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT),
            policy=self.server.config.getattr("policy", "idp"),
            issuer=self.server._issuer(),
            attrconvs=self.server.config.attribute_converters,
            authn_class=INTERNETPROTOCOLPASSWORD,
            authn_auth="http://www.example.com/login")

        assertion.signature = sigver.pre_signature_part(
            assertion.id, _sec.my_cert, 1)

        sigass = _sec.sign_statement(assertion,
                                     class_name(assertion),
                                     key_file=self.client.sec.key_file,
                                     node_id=assertion.id)

        sigass = rm_xmltag(sigass)

        response = sigver.response_factory(
            in_response_to="_012345",
            destination="http://lingon.catalogix.se:8087/",
            status=s_utils.success_status_factory(),
            issuer=self.server._issuer(),
            encrypted_assertion=EncryptedAssertion())

        xmldoc = "%s" % response
        # strangely enough I get different tags if I run this test separately
        # or as part of a bunch of tests.
        xmldoc = add_subelement(xmldoc, "EncryptedAssertion", sigass)

        enctext = _sec.crypto.encrypt_assertion(xmldoc, _sec.cert_file,
                                                pre_encryption_part())

        #seresp = samlp.response_from_string(enctext)

        resp_str = base64.encodestring(enctext)
        # Now over to the client side
        resp = self.client.parse_authn_request_response(
            resp_str, BINDING_HTTP_POST,
            {"_012345": "http://foo.example.com/service"})

        #assert resp.encrypted_assertion == []
        assert resp.assertion
        assert resp.ava == {'givenName': ['Derek'], 'sn': ['Jeter']}
Exemple #3
0
    def test_unsolicited_response(self):
        """

        """
        self.server = Server("idp_conf")

        conf = config.SPConfig()
        conf.load_file("server_conf")
        self.client = Saml2Client(conf)

        for subject in self.client.users.subjects():
            self.client.users.remove_person(subject)

        IDP = "urn:mace:example.com:saml:roland:idp"

        ava = {
            "givenName": ["Derek"],
            "surname": ["Jeter"],
            "mail": ["*****@*****.**"]
        }

        resp_str = "\n".join(
            self.server.authn_response(
                identity=ava,
                in_response_to="id1",
                destination="http://lingon.catalogix.se:8087/",
                sp_entity_id="urn:mace:example.com:saml:roland:sp",
                name_id_policy=samlp.NameIDPolicy(
                    format=saml.NAMEID_FORMAT_PERSISTENT),
                userid="*****@*****.**"))

        resp_str = base64.encodestring(resp_str)

        self.client.allow_unsolicited = True
        authn_response = self.client.response({"SAMLResponse": resp_str}, ())

        assert authn_response is not None
        assert authn_response.issuer() == IDP
        assert authn_response.response.assertion[0].issuer.text == IDP
        session_info = authn_response.session_info()

        print session_info
        assert session_info["ava"] == {
            'mail': ['*****@*****.**'],
            'givenName': ['Derek'],
            'sn': ['Jeter']
        }
        assert session_info["issuer"] == IDP
        assert session_info["came_from"] == ""
        response = samlp.response_from_string(authn_response.xmlstr)
        assert response.destination == "http://lingon.catalogix.se:8087/"

        # One person in the cache
        assert len(self.client.users.subjects()) == 1
Exemple #4
0
    def test_sign_then_encrypt_assertion2(self):
        # Begin with the IdPs side
        _sec = self.server.sec

        nameid_policy = samlp.NameIDPolicy(
            allow_create="false", format=saml.NAMEID_FORMAT_PERSISTENT)

        asser = Assertion({"givenName": "Derek", "surName": "Jeter"})
        assertion = asser.construct(
            self.client.config.entityid,
            "_012345",
            "http://lingon.catalogix.se:8087/",
            factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT),
            policy=self.server.config.getattr("policy", "idp"),
            issuer=self.server._issuer(),
            attrconvs=self.server.config.attribute_converters,
            authn_class=INTERNETPROTOCOLPASSWORD,
            authn_auth="http://www.example.com/login")

        assertion.signature = sigver.pre_signature_part(
            assertion.id, _sec.my_cert, 1)

        sigass = _sec.sign_statement(
            assertion,
            class_name(assertion),
            #key_file="pki/mykey.pem",
            key_file="test.key",
            node_id=assertion.id)
        # Create an Assertion instance from the signed assertion
        _ass = saml.assertion_from_string(sigass)

        response = sigver.response_factory(
            in_response_to="_012345",
            destination="https://www.example.com",
            status=s_utils.success_status_factory(),
            issuer=self.server._issuer(),
            assertion=_ass)

        enctext = _sec.crypto.encrypt_assertion(response, _sec.cert_file,
                                                pre_encryption_part())

        #seresp = samlp.response_from_string(enctext)

        resp_str = base64.encodestring(enctext)
        # Now over to the client side
        resp = self.client.parse_authn_request_response(
            resp_str, BINDING_HTTP_POST,
            {"_012345": "http://foo.example.com/service"})

        #assert resp.encrypted_assertion == []
        assert resp.assertion
        assert resp.ava == {'givenName': ['Derek'], 'sn': ['Jeter']}
    def testAccessors(self):
        """Test for AuthnRequest accessors"""
        self.ar.id = "request id"
        self.ar.version = saml2.VERSION
        self.ar.issue_instant = "2007-09-14T01:05:02Z"
        self.ar.destination = "http://www.example.com/Destination"
        self.ar.consent = saml.CONSENT_UNSPECIFIED
        self.ar.issuer = saml.Issuer()
        self.ar.signature = ds.Signature()
        self.ar.extensions = samlp.Extensions()

        self.ar.subject = saml.Subject()
        self.ar.name_id_policy = samlp.NameIDPolicy()
        self.ar.conditions = saml.Conditions()
        self.ar.requested_authn_context = samlp.RequestedAuthnContext()
        self.ar.scoping = samlp.Scoping()
        self.ar.force_authn = 'true'
        self.ar.is_passive = 'true'
        self.ar.assertion_consumer_service_index = "1"
        self.ar.assertion_consumer_service_url = "http://www.example.com/acs"
        self.ar.protocol_binding = saml2.BINDING_HTTP_POST
        self.ar.attribute_consuming_service_index = "2"
        self.ar.provider_name = "provider name"

        new_ar = samlp.authn_request_from_string(self.ar.to_string())
        assert new_ar.id == "request id"
        assert new_ar.version == saml2.VERSION
        assert new_ar.issue_instant == "2007-09-14T01:05:02Z"
        assert new_ar.destination == "http://www.example.com/Destination"
        assert new_ar.consent == saml.CONSENT_UNSPECIFIED
        assert isinstance(new_ar.issuer, saml.Issuer)
        assert isinstance(new_ar.signature, ds.Signature)
        assert isinstance(new_ar.extensions, samlp.Extensions)

        assert isinstance(new_ar.subject, saml.Subject)
        assert isinstance(new_ar.name_id_policy, samlp.NameIDPolicy)
        assert isinstance(new_ar.conditions, saml.Conditions)
        assert isinstance(new_ar.requested_authn_context,
                          samlp.RequestedAuthnContext)
        assert isinstance(new_ar.scoping, samlp.Scoping)
        assert new_ar.force_authn == 'true'
        assert new_ar.is_passive == 'true'
        assert new_ar.assertion_consumer_service_index == '1'
        assert new_ar.assertion_consumer_service_url == \
                                 'http://www.example.com/acs'
        assert new_ar.protocol_binding == saml2.BINDING_HTTP_POST
        assert new_ar.attribute_consuming_service_index == '2'
        assert new_ar.provider_name == "provider name"
Exemple #6
0
    def test_authn_response_0(self):
        self.server = Server("idp_conf")

        conf = config.SPConfig()
        conf.load_file("server_conf")
        self.client = client.Saml2Client(conf)

        ava = {
            "givenName": ["Derek"],
            "surName": ["Jeter"],
            "mail": ["*****@*****.**"],
            "title": "The man"
        }

        npolicy = samlp.NameIDPolicy(format=saml.NAMEID_FORMAT_TRANSIENT,
                                     allow_create="true")
        resp_str = "%s" % self.server.create_authn_response(
            ava,
            "id1",
            "http://*****:*****@example.com",
            authn=AUTHN)

        response = samlp.response_from_string(resp_str)
        print((response.keyswv()))
        assert _eq(response.keyswv(), [
            'status', 'destination', 'assertion', 'in_response_to',
            'issue_instant', 'version', 'issuer', 'id'
        ])
        print((response.assertion[0].keyswv()))
        assert len(response.assertion) == 1
        assert _eq(response.assertion[0].keyswv(), [
            'attribute_statement', 'issue_instant', 'version', 'subject',
            'conditions', 'id', 'issuer', 'authn_statement'
        ])
        assertion = response.assertion[0]
        assert len(assertion.attribute_statement) == 1
        astate = assertion.attribute_statement[0]
        print(astate)
        assert len(astate.attribute) == 4
Exemple #7
0
    def test_sign_then_encrypt_assertion_advice(self):
        # Begin with the IdPs side
        _sec = self.server.sec

        nameid_policy = samlp.NameIDPolicy(
            allow_create="false", format=saml.NAMEID_FORMAT_PERSISTENT)

        asser = Assertion({"givenName": "Derek", "surName": "Jeter"})
        assertion = asser.construct(
            self.client.config.entityid,
            "_012345",
            "http://lingon.catalogix.se:8087/",
            factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT),
            policy=self.server.config.getattr("policy", "idp"),
            issuer=self.server._issuer(),
            attrconvs=self.server.config.attribute_converters,
            authn_class=INTERNETPROTOCOLPASSWORD,
            authn_auth="http://www.example.com/login")

        a_asser = Assertion({
            "uid": "test01",
            "email": "*****@*****.**"
        })
        a_assertion = a_asser.construct(
            self.client.config.entityid,
            "_012345",
            "http://lingon.catalogix.se:8087/",
            factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT),
            policy=self.server.config.getattr("policy", "idp"),
            issuer=self.server._issuer(),
            attrconvs=self.server.config.attribute_converters,
            authn_class=INTERNETPROTOCOLPASSWORD,
            authn_auth="http://www.example.com/login")

        a_assertion.signature = sigver.pre_signature_part(
            a_assertion.id, _sec.my_cert, 1)

        assertion.advice = Advice()

        assertion.advice.encrypted_assertion = []
        assertion.advice.encrypted_assertion.append(EncryptedAssertion())

        assertion.advice.encrypted_assertion[0].add_extension_element(
            a_assertion)

        response = sigver.response_factory(
            in_response_to="_012345",
            destination="http://lingon.catalogix.se:8087/",
            status=s_utils.success_status_factory(),
            issuer=self.server._issuer())

        response.assertion.append(assertion)

        response = _sec.sign_statement("%s" % response,
                                       class_name(a_assertion),
                                       key_file=self.client.sec.key_file,
                                       node_id=a_assertion.id)

        #xmldoc = "%s" % response
        # strangely enough I get different tags if I run this test separately
        # or as part of a bunch of tests.
        #xmldoc = add_subelement(xmldoc, "EncryptedAssertion", sigass)

        node_xpath = ''.join([
            "/*[local-name()=\"%s\"]" % v for v in [
                "Response", "Assertion", "Advice", "EncryptedAssertion",
                "Assertion"
            ]
        ])

        enctext = _sec.crypto.encrypt_assertion(response,
                                                _sec.cert_file,
                                                pre_encryption_part(),
                                                node_xpath=node_xpath)

        #seresp = samlp.response_from_string(enctext)

        resp_str = base64.encodestring(enctext)
        # Now over to the client side
        resp = self.client.parse_authn_request_response(
            resp_str, BINDING_HTTP_POST,
            {"_012345": "http://foo.example.com/service"})

        #assert resp.encrypted_assertion == []
        assert resp.assertion
        assert resp.assertion.advice
        assert resp.assertion.advice.assertion
        assert resp.ava == \
               {'sn': ['Jeter'], 'givenName': ['Derek'], 'uid': ['test01'], 'email': ['*****@*****.**']}
Exemple #8
0
    def test_response(self):
        IDP = "urn:mace:example.com:saml:roland:idp"

        ava = {
            "givenName": ["Derek"],
            "surName": ["Jeter"],
            "mail": ["*****@*****.**"],
            "title": ["The man"]
        }

        nameid_policy = samlp.NameIDPolicy(
            allow_create="false", format=saml.NAMEID_FORMAT_PERSISTENT)

        resp = self.server.create_authn_response(
            identity=ava,
            in_response_to="id1",
            destination="http://lingon.catalogix.se:8087/",
            sp_entity_id="urn:mace:example.com:saml:roland:sp",
            name_id_policy=nameid_policy,
            userid="*****@*****.**",
            authn=AUTHN)

        resp_str = "%s" % resp

        resp_str = base64.encodestring(resp_str)

        authn_response = self.client.parse_authn_request_response(
            resp_str, BINDING_HTTP_POST,
            {"id1": "http://foo.example.com/service"})

        assert authn_response is not None
        assert authn_response.issuer() == IDP
        assert authn_response.response.assertion[0].issuer.text == IDP
        session_info = authn_response.session_info()

        print session_info
        assert session_info["ava"] == {
            'mail': ['*****@*****.**'],
            'givenName': ['Derek'],
            'sn': ['Jeter'],
            'title': ["The man"]
        }
        assert session_info["issuer"] == IDP
        assert session_info["came_from"] == "http://foo.example.com/service"
        response = samlp.response_from_string(authn_response.xmlstr)
        assert response.destination == "http://lingon.catalogix.se:8087/"

        # One person in the cache
        assert len(self.client.users.subjects()) == 1
        subject_id = self.client.users.subjects()[0]
        print "||||", self.client.users.get_info_from(subject_id, IDP)
        # The information I have about the subject comes from one source
        assert self.client.users.issuers_of_info(subject_id) == [IDP]

        # --- authenticate another person

        ava = {
            "givenName": ["Alfonson"],
            "surName": ["Soriano"],
            "mail": ["*****@*****.**"],
            "title": ["outfielder"]
        }

        resp_str = "%s" % self.server.create_authn_response(
            identity=ava,
            in_response_to="id2",
            destination="http://lingon.catalogix.se:8087/",
            sp_entity_id="urn:mace:example.com:saml:roland:sp",
            name_id_policy=nameid_policy,
            userid="*****@*****.**",
            authn=AUTHN)

        resp_str = base64.encodestring(resp_str)

        self.client.parse_authn_request_response(
            resp_str, BINDING_HTTP_POST,
            {"id2": "http://foo.example.com/service"})

        # Two persons in the cache
        assert len(self.client.users.subjects()) == 2
        issuers = [
            self.client.users.issuers_of_info(s)
            for s in self.client.users.subjects()
        ]
        # The information I have about the subjects comes from the same source
        print issuers
        assert issuers == [[IDP], [IDP]]
Exemple #9
0
    def create_authn_request(self,
                             destination,
                             vorg="",
                             scoping=None,
                             binding=saml2.BINDING_HTTP_POST,
                             nameid_format=None,
                             service_url_binding=None,
                             message_id=0,
                             consent=None,
                             extensions=None,
                             sign=None,
                             allow_create=None,
                             sign_prepare=False,
                             sign_alg=None,
                             digest_alg=None,
                             **kwargs):
        """ Creates an authentication request.

        :param destination: Where the request should be sent.
        :param vorg: The virtual organization the service belongs to.
        :param scoping: The scope of the request
        :param binding: The protocol to use for the Response !!
        :param nameid_format: Format of the NameID
        :param service_url_binding: Where the reply should be sent dependent
            on reply binding.
        :param message_id: The identifier for this request
        :param consent: Whether the principal have given her consent
        :param extensions: Possible extensions
        :param sign: Whether the request should be signed or not.
        :param sign_prepare: Whether the signature should be prepared or not.
        :param allow_create: If the identity provider is allowed, in the course
            of fulfilling the request, to create a new identifier to represent
            the principal.
        :param kwargs: Extra key word arguments
        :return: tuple of request ID and <samlp:AuthnRequest> instance
        """
        client_crt = None
        if "client_crt" in kwargs:
            client_crt = kwargs["client_crt"]

        args = {}

        if self.config.getattr('hide_assertion_consumer_service', 'sp'):
            args["assertion_consumer_service_url"] = None
            binding = None
        else:
            try:
                args["assertion_consumer_service_url"] = kwargs[
                    "assertion_consumer_service_urls"][0]
                del kwargs["assertion_consumer_service_urls"]
            except KeyError:
                try:
                    args["assertion_consumer_service_url"] = kwargs[
                        "assertion_consumer_service_url"]
                    del kwargs["assertion_consumer_service_url"]
                except KeyError:
                    try:
                        args["assertion_consumer_service_index"] = str(
                            kwargs["assertion_consumer_service_index"])
                        del kwargs["assertion_consumer_service_index"]
                    except KeyError:
                        if service_url_binding is None:
                            service_urls = self.service_urls(binding)
                        else:
                            service_urls = self.service_urls(
                                service_url_binding)
                        args["assertion_consumer_service_url"] = service_urls[
                            0]

        try:
            args["provider_name"] = kwargs["provider_name"]
        except KeyError:
            if binding == BINDING_PAOS:
                pass
            else:
                args["provider_name"] = self._my_name()

        # Allow argument values either as class instances or as dictionaries
        # all of these have cardinality 0..1
        _msg = AuthnRequest()
        for param in [
                "scoping", "requested_authn_context", "conditions", "subject"
        ]:
            try:
                _item = kwargs[param]
            except KeyError:
                pass
            else:
                del kwargs[param]
                # either class instance or argument dictionary
                if isinstance(_item, _msg.child_class(param)):
                    args[param] = _item
                elif isinstance(_item, dict):
                    args[param] = RequestedAuthnContext(**_item)
                else:
                    raise ValueError("%s or wrong type expected %s" %
                                     (_item, param))

        try:
            args["name_id_policy"] = kwargs["name_id_policy"]
            del kwargs["name_id_policy"]
        except KeyError:
            if allow_create is None:
                allow_create = self.config.getattr(
                    "name_id_format_allow_create", "sp")
                if allow_create is None:
                    allow_create = "false"
                else:
                    if allow_create is True:
                        allow_create = "true"
                    else:
                        allow_create = "false"

            if nameid_format == "":
                name_id_policy = None
            else:
                if nameid_format is None:
                    nameid_format = self.config.getattr("name_id_format", "sp")

                    # If no nameid_format has been set in the configuration
                    # or passed in then transient is the default.
                    if nameid_format is None:
                        nameid_format = NAMEID_FORMAT_TRANSIENT

                    # If a list has been configured or passed in choose the
                    # first since NameIDPolicy can only have one format specified.
                    elif isinstance(nameid_format, list):
                        nameid_format = nameid_format[0]

                    # Allow a deployer to signal that no format should be specified
                    # in the NameIDPolicy by passing in or configuring the string 'None'.
                    elif nameid_format == 'None':
                        nameid_format = None

                name_id_policy = samlp.NameIDPolicy(allow_create=allow_create,
                                                    format=nameid_format)

            if name_id_policy and vorg:
                try:
                    name_id_policy.sp_name_qualifier = vorg
                    name_id_policy.format = saml.NAMEID_FORMAT_PERSISTENT
                except KeyError:
                    pass
            args["name_id_policy"] = name_id_policy

        try:
            nsprefix = kwargs["nsprefix"]
        except KeyError:
            nsprefix = None

        try:
            force_authn = kwargs['force_authn']
        except KeyError:
            force_authn = self.config.getattr('force_authn', 'sp')
        finally:
            if force_authn:
                args['force_authn'] = 'true'

        conf_sp_type = self.config.getattr('sp_type', 'sp')
        conf_sp_type_in_md = self.config.getattr('sp_type_in_metadata', 'sp')
        if conf_sp_type and conf_sp_type_in_md is False:
            if not extensions:
                extensions = Extensions()
            item = sp_type.SPType(text=conf_sp_type)
            extensions.add_extension_element(item)

        requested_attrs = self.config.getattr('requested_attributes', 'sp')
        if requested_attrs:
            if not extensions:
                extensions = Extensions()

            attributemapsmods = []
            for modname in attributemaps.__all__:
                attributemapsmods.append(getattr(attributemaps, modname))

            items = []
            for attr in requested_attrs:
                friendly_name = attr.get('friendly_name')
                name = attr.get('name')
                name_format = attr.get('name_format')
                is_required = str(attr.get('required', False)).lower()

                if not name and not friendly_name:
                    raise ValueError(
                        "Missing required attribute: '{}' or '{}'".format(
                            'name', 'friendly_name'))

                if not name:
                    for mod in attributemapsmods:
                        try:
                            name = mod.MAP['to'][friendly_name]
                        except KeyError:
                            continue
                        else:
                            if not name_format:
                                name_format = mod.MAP['identifier']
                            break

                if not friendly_name:
                    for mod in attributemapsmods:
                        try:
                            friendly_name = mod.MAP['fro'][name]
                        except KeyError:
                            continue
                        else:
                            if not name_format:
                                name_format = mod.MAP['identifier']
                            break

                items.append(
                    requested_attributes.RequestedAttribute(
                        is_required=is_required,
                        name_format=name_format,
                        friendly_name=friendly_name,
                        name=name))

            item = requested_attributes.RequestedAttributes(
                extension_elements=items)
            extensions.add_extension_element(item)

        if kwargs:
            _args, extensions = self._filter_args(AuthnRequest(), extensions,
                                                  **kwargs)
            args.update(_args)

        try:
            del args["id"]
        except KeyError:
            pass

        if sign is None:
            sign = self.authn_requests_signed

        if (sign and self.sec.cert_handler.generate_cert()) or \
                        client_crt is not None:
            with self.lock:
                self.sec.cert_handler.update_cert(True, client_crt)
                if client_crt is not None:
                    sign_prepare = True
                return self._message(AuthnRequest,
                                     destination,
                                     message_id,
                                     consent,
                                     extensions,
                                     sign,
                                     sign_prepare,
                                     protocol_binding=binding,
                                     scoping=scoping,
                                     nsprefix=nsprefix,
                                     sign_alg=sign_alg,
                                     digest_alg=digest_alg,
                                     **args)
        return self._message(AuthnRequest,
                             destination,
                             message_id,
                             consent,
                             extensions,
                             sign,
                             sign_prepare,
                             protocol_binding=binding,
                             scoping=scoping,
                             nsprefix=nsprefix,
                             sign_alg=sign_alg,
                             digest_alg=digest_alg,
                             **args)
Exemple #10
0
    def create_authn_request(self,
                             destination,
                             vorg="",
                             scoping=None,
                             binding=saml2.BINDING_HTTP_POST,
                             nameid_format=None,
                             service_url_binding=None,
                             message_id=0,
                             consent=None,
                             extensions=None,
                             sign=None,
                             allow_create=None,
                             sign_prepare=False,
                             sign_alg=None,
                             digest_alg=None,
                             **kwargs):
        """ Creates an authentication request.

        :param destination: Where the request should be sent.
        :param vorg: The virtual organization the service belongs to.
        :param scoping: The scope of the request
        :param binding: The protocol to use for the Response !!
        :param nameid_format: Format of the NameID
        :param service_url_binding: Where the reply should be sent dependent
            on reply binding.
        :param message_id: The identifier for this request
        :param consent: Whether the principal have given her consent
        :param extensions: Possible extensions
        :param sign: Whether the request should be signed or not.
        :param sign_prepare: Whether the signature should be prepared or not.
        :param allow_create: If the identity provider is allowed, in the course
            of fulfilling the request, to create a new identifier to represent
            the principal.
        :param kwargs: Extra key word arguments
        :return: tuple of request ID and <samlp:AuthnRequest> instance
        """
        client_crt = None
        if "client_crt" in kwargs:
            client_crt = kwargs["client_crt"]

        args = {}

        try:
            args["assertion_consumer_service_url"] = kwargs[
                "assertion_consumer_service_urls"][0]
            del kwargs["assertion_consumer_service_urls"]
        except KeyError:
            try:
                args["assertion_consumer_service_url"] = kwargs[
                    "assertion_consumer_service_url"]
                del kwargs["assertion_consumer_service_url"]
            except KeyError:
                try:
                    args["assertion_consumer_service_index"] = str(
                        kwargs["assertion_consumer_service_index"])
                    del kwargs["assertion_consumer_service_index"]
                except KeyError:
                    if service_url_binding is None:
                        service_urls = self.service_urls(binding)
                    else:
                        service_urls = self.service_urls(service_url_binding)
                    args["assertion_consumer_service_url"] = service_urls[0]

        try:
            args["provider_name"] = kwargs["provider_name"]
        except KeyError:
            if binding == BINDING_PAOS:
                pass
            else:
                args["provider_name"] = self._my_name()

        # Allow argument values either as class instances or as dictionaries
        # all of these have cardinality 0..1
        _msg = AuthnRequest()
        for param in [
                "scoping", "requested_authn_context", "conditions", "subject"
        ]:
            try:
                _item = kwargs[param]
            except KeyError:
                pass
            else:
                del kwargs[param]
                # either class instance or argument dictionary
                if isinstance(_item, _msg.child_class(param)):
                    args[param] = _item
                elif isinstance(_item, dict):
                    args[param] = RequestedAuthnContext(**_item)
                else:
                    raise ValueError("%s or wrong type expected %s" %
                                     (_item, param))

        try:
            args["name_id_policy"] = kwargs["name_id_policy"]
            del kwargs["name_id_policy"]
        except KeyError:
            if allow_create is None:
                allow_create = self.config.getattr(
                    "name_id_format_allow_create", "sp")
                if allow_create is None:
                    allow_create = "false"
                else:
                    if allow_create is True:
                        allow_create = "true"
                    else:
                        allow_create = "false"

            if nameid_format == "":
                name_id_policy = None
            else:
                if nameid_format is None:
                    nameid_format = self.config.getattr("name_id_format", "sp")

                    if nameid_format is None:
                        nameid_format = NAMEID_FORMAT_TRANSIENT
                    elif isinstance(nameid_format, list):
                        # NameIDPolicy can only have one format specified
                        nameid_format = nameid_format[0]

                name_id_policy = samlp.NameIDPolicy(allow_create=allow_create,
                                                    format=nameid_format)

            if name_id_policy and vorg:
                try:
                    name_id_policy.sp_name_qualifier = vorg
                    name_id_policy.format = saml.NAMEID_FORMAT_PERSISTENT
                except KeyError:
                    pass
            args["name_id_policy"] = name_id_policy

        try:
            nsprefix = kwargs["nsprefix"]
        except KeyError:
            nsprefix = None

        if kwargs:
            _args, extensions = self._filter_args(AuthnRequest(), extensions,
                                                  **kwargs)
            args.update(_args)

        try:
            del args["id"]
        except KeyError:
            pass

        if sign is None:
            sign = self.authn_requests_signed

        if (sign and self.sec.cert_handler.generate_cert()) or \
                        client_crt is not None:
            with self.lock:
                self.sec.cert_handler.update_cert(True, client_crt)
                if client_crt is not None:
                    sign_prepare = True
                return self._message(AuthnRequest,
                                     destination,
                                     message_id,
                                     consent,
                                     extensions,
                                     sign,
                                     sign_prepare,
                                     protocol_binding=binding,
                                     scoping=scoping,
                                     nsprefix=nsprefix,
                                     sign_alg=sign_alg,
                                     digest_alg=digest_alg,
                                     **args)
        return self._message(AuthnRequest,
                             destination,
                             message_id,
                             consent,
                             extensions,
                             sign,
                             sign_prepare,
                             protocol_binding=binding,
                             scoping=scoping,
                             nsprefix=nsprefix,
                             sign_alg=sign_alg,
                             digest_alg=digest_alg,
                             **args)
    def create_authn_request(self,
                             destination,
                             vorg="",
                             scoping=None,
                             binding=saml2.BINDING_HTTP_POST,
                             nameid_format=NAMEID_FORMAT_TRANSIENT,
                             service_url_binding=None,
                             message_id=0,
                             consent=None,
                             extensions=None,
                             sign=None,
                             allow_create=False,
                             sign_prepare=False,
                             **kwargs):
        """ Creates an authentication request.
        
        :param destination: Where the request should be sent.
        :param vorg: The virtual organization the service belongs to.
        :param scoping: The scope of the request
        :param binding: The protocol to use for the Response !!
        :param nameid_format: Format of the NameID
        :param service_url_binding: Where the reply should be sent dependent
            on reply binding.
        :param message_id: The identifier for this request
        :param consent: Whether the principal have given her consent
        :param extensions: Possible extensions
        :param sign: Whether the request should be signed or not.
        :param sign_prepare: Whether the signature should be prepared or not.
        :param allow_create: If the identity provider is allowed, in the course
            of fulfilling the request, to create a new identifier to represent
            the principal.
        :param kwargs: Extra key word arguments
        :return: tuple of request ID and <samlp:AuthnRequest> instance
        """

        client_crt = None
        if "client_crt" in kwargs:
            client_crt = kwargs["client_crt"]

        args = {}
        try:
            args["assertion_consumer_service_url"] = kwargs[
                "assertion_consumer_service_urls"][0]
            del kwargs["assertion_consumer_service_urls"]
        except KeyError:
            try:
                args["assertion_consumer_service_url"] = kwargs[
                    "assertion_consumer_service_url"]
                del kwargs["assertion_consumer_service_urls"]
            except KeyError:
                try:
                    args["attribute_consuming_service_index"] = str(
                        kwargs["attribute_consuming_service_index"])
                    del kwargs["attribute_consuming_service_index"]
                except KeyError:
                    if service_url_binding is None:
                        service_urls = self.service_urls(binding)
                    else:
                        service_urls = self.service_urls(service_url_binding)
                    args["assertion_consumer_service_url"] = service_urls[0]

        try:
            args["provider_name"] = kwargs["provider_name"]
        except KeyError:
            if binding == BINDING_PAOS:
                pass
            else:
                args["provider_name"] = self._my_name()

        try:
            args["name_id_policy"] = kwargs["name_id_policy"]
            del kwargs["name_id_policy"]
        except KeyError:
            if allow_create:
                allow_create = "true"
            else:
                allow_create = "false"

            # Profile stuff, should be configurable
            if nameid_format is None:
                name_id_policy = samlp.NameIDPolicy(
                    allow_create=allow_create, format=NAMEID_FORMAT_TRANSIENT)
            elif nameid_format == "":
                name_id_policy = None
            else:
                name_id_policy = samlp.NameIDPolicy(allow_create=allow_create,
                                                    format=nameid_format)

            if name_id_policy and vorg:
                try:
                    name_id_policy.sp_name_qualifier = vorg
                    name_id_policy.format = saml.NAMEID_FORMAT_PERSISTENT
                except KeyError:
                    pass
            args["name_id_policy"] = name_id_policy

        if kwargs:
            _args, extensions = self._filter_args(AuthnRequest(), extensions,
                                                  **kwargs)
            args.update(_args)

        try:
            del args["id"]
        except KeyError:
            pass

        if (sign and self.sec.cert_handler.generate_cert()) or \
                client_crt is not None:
            with self.lock:
                self.sec.cert_handler.update_cert(True, client_crt)
                if client_crt is not None:
                    sign_prepare = True
                return self._message(AuthnRequest,
                                     destination,
                                     message_id,
                                     consent,
                                     extensions,
                                     sign,
                                     sign_prepare,
                                     protocol_binding=binding,
                                     scoping=scoping,
                                     **args)
        return self._message(AuthnRequest,
                             destination,
                             message_id,
                             consent,
                             extensions,
                             sign,
                             sign_prepare,
                             protocol_binding=binding,
                             scoping=scoping,
                             **args)
Exemple #12
0
    def create_authn_request(self,
                             destination,
                             vorg="",
                             scoping=None,
                             binding=saml2.BINDING_HTTP_POST,
                             nameid_format=None,
                             service_url_binding=None,
                             message_id=0,
                             consent=None,
                             extensions=None,
                             sign=None,
                             allow_create=None,
                             sign_prepare=False,
                             sign_alg=None,
                             digest_alg=None,
                             requested_attributes=None,
                             **kwargs):
        """ Creates an authentication request.

        :param destination: Where the request should be sent.
        :param vorg: The virtual organization the service belongs to.
        :param scoping: The scope of the request
        :param binding: The protocol to use for the Response !!
        :param nameid_format: Format of the NameIDPolicy
        :param service_url_binding: Where the reply should be sent dependent
            on reply binding.
        :param message_id: The identifier for this request
        :param consent: Whether the principal have given her consent
        :param extensions: Possible extensions
        :param sign: Whether the request should be signed or not.
        :param sign_prepare: Whether the signature should be prepared or not.
        :param allow_create: If the identity provider is allowed, in the course
            of fulfilling the request, to create a new identifier to represent
            the principal.
        :param requested_attributes: A list of dicts which define attributes to
            be used as eIDAS Requested Attributes for this request. If not
            defined the configuration option requested_attributes will be used,
            if defined. The format is the same as the requested_attributes
            configuration option.
        :param kwargs: Extra key word arguments
        :return: either a tuple of request ID and <samlp:AuthnRequest> instance
                 or a tuple of request ID and str when sign is set to True
        """
        args = {}

        # AssertionConsumerServiceURL
        # AssertionConsumerServiceIndex
        hide_assertion_consumer_service = self.config.getattr(
            'hide_assertion_consumer_service', 'sp')
        assertion_consumer_service_url = (
            kwargs.pop("assertion_consumer_service_urls", [None])[0]
            or kwargs.pop("assertion_consumer_service_url", None))
        assertion_consumer_service_index = kwargs.pop(
            "assertion_consumer_service_index", None)
        service_url = (self.service_urls(service_url_binding or binding)
                       or [None])[0]
        if hide_assertion_consumer_service:
            args["assertion_consumer_service_url"] = None
            binding = None
        elif assertion_consumer_service_url:
            args[
                "assertion_consumer_service_url"] = assertion_consumer_service_url
        elif assertion_consumer_service_index:
            args[
                "assertion_consumer_service_index"] = assertion_consumer_service_index
        elif service_url:
            args["assertion_consumer_service_url"] = service_url

        # ProviderName
        provider_name = kwargs.get("provider_name")
        if not provider_name and binding != BINDING_PAOS:
            provider_name = self._my_name()
        args["provider_name"] = provider_name

        # Allow argument values either as class instances or as dictionaries
        # all of these have cardinality 0..1
        _msg = AuthnRequest()
        for param in [
                "scoping", "requested_authn_context", "conditions", "subject"
        ]:
            _item = kwargs.pop(param, None)
            if not _item:
                continue

            if isinstance(_item, _msg.child_class(param)):
                args[param] = _item
            elif isinstance(_item, dict):
                args[param] = RequestedAuthnContext(**_item)
            else:
                raise ValueError(
                    "Wrong type for param {name}".format(name=param))

        # NameIDPolicy
        nameid_policy_format_config = self.config.getattr(
            "name_id_policy_format", "sp")
        nameid_policy_format = (nameid_format or nameid_policy_format_config
                                or None)

        allow_create_config = self.config.getattr(
            "name_id_format_allow_create", "sp")
        allow_create = (
            None
            # SAML 2.0 errata says AllowCreate MUST NOT be used for transient ids
            if nameid_policy_format == NAMEID_FORMAT_TRANSIENT
            else allow_create if allow_create else str(
                bool(allow_create_config)).lower())

        name_id_policy = (
            kwargs.pop("name_id_policy", None) if "name_id_policy" in kwargs
            else None if not nameid_policy_format else samlp.NameIDPolicy(
                allow_create=allow_create, format=nameid_policy_format))

        if name_id_policy and vorg:
            name_id_policy.sp_name_qualifier = vorg
            name_id_policy.format = nameid_policy_format or NAMEID_FORMAT_PERSISTENT

        args["name_id_policy"] = name_id_policy

        # eIDAS SPType
        conf_sp_type = self.config.getattr('sp_type', 'sp')
        conf_sp_type_in_md = self.config.getattr('sp_type_in_metadata', 'sp')
        if conf_sp_type and conf_sp_type_in_md is False:
            if not extensions:
                extensions = Extensions()
            item = sp_type.SPType(text=conf_sp_type)
            extensions.add_extension_element(item)

        # eIDAS RequestedAttributes
        requested_attrs = (requested_attributes
                           or self.config.getattr('requested_attributes', 'sp')
                           or [])
        if requested_attrs:
            req_attrs_node = create_requested_attribute_node(
                requested_attrs, self.config.attribute_converters)
            if not extensions:
                extensions = Extensions()
            extensions.add_extension_element(req_attrs_node)

        # ForceAuthn
        force_authn = str(
            kwargs.pop("force_authn", None)
            or self.config.getattr("force_authn", "sp")).lower() in [
                "true", "1"
            ]
        if force_authn:
            kwargs["force_authn"] = "true"

        if kwargs:
            _args, extensions = self._filter_args(AuthnRequest(), extensions,
                                                  **kwargs)
            args.update(_args)
        args.pop("id", None)

        client_crt = kwargs.get("client_crt")
        nsprefix = kwargs.get("nsprefix")
        sign = self.authn_requests_signed if sign is None else sign

        if (sign and self.sec.cert_handler.generate_cert()
            ) or client_crt is not None:
            with self.lock:
                self.sec.cert_handler.update_cert(True, client_crt)
                if client_crt is not None:
                    sign_prepare = True
                msg = self._message(
                    AuthnRequest,
                    destination,
                    message_id,
                    consent,
                    extensions,
                    sign,
                    sign_prepare,
                    protocol_binding=binding,
                    scoping=scoping,
                    nsprefix=nsprefix,
                    sign_alg=sign_alg,
                    digest_alg=digest_alg,
                    **args,
                )
        else:
            msg = self._message(
                AuthnRequest,
                destination,
                message_id,
                consent,
                extensions,
                sign,
                sign_prepare,
                protocol_binding=binding,
                scoping=scoping,
                nsprefix=nsprefix,
                sign_alg=sign_alg,
                digest_alg=digest_alg,
                **args,
            )

        return msg
 def setup_class(self):
     self.name_id_policy = samlp.NameIDPolicy()
Exemple #14
0
    def authn_request(self,
                      query_id,
                      destination,
                      service_url,
                      spentityid,
                      my_name="",
                      vorg="",
                      scoping=None,
                      log=None,
                      sign=None,
                      binding=BINDING_HTTP_POST,
                      nameid_format=saml.NAMEID_FORMAT_TRANSIENT,
                      **kwargs):
        """ Creates an authentication request.
        
        :param query_id: The identifier for this request
        :param destination: Where the request should be sent.
        :param service_url: Where the reply should be sent.
        :param spentityid: The entity identifier for this service.
        :param my_name: The name of this service.
        :param vorg: The vitual organization the service belongs to.
        :param scoping: The scope of the request
        :param log: A service to which logs should be written
        :param sign: Whether the request should be signed or not.
        :param binding: The protocol to use for the Response !!
        :return: <samlp:AuthnRequest> instance

        added: we want additional kw arguments, namely is_passive
        """
        request = samlp.AuthnRequest(
            id=query_id,
            version=VERSION,
            issue_instant=instant(),
            assertion_consumer_service_url=service_url,
            protocol_binding=binding,
            **kwargs)

        if destination:
            request.destination = destination
        if my_name:
            request.provider_name = my_name
        if scoping:
            request.scoping = scoping

        # Profile stuff, should be configurable
        if nameid_format == saml.NAMEID_FORMAT_TRANSIENT:
            name_id_policy = samlp.NameIDPolicy(allow_create="true",
                                                format=nameid_format)
        else:
            name_id_policy = samlp.NameIDPolicy(format=nameid_format)

        if vorg:
            try:
                name_id_policy.sp_name_qualifier = vorg
                name_id_policy.format = saml.NAMEID_FORMAT_PERSISTENT
            except KeyError:
                pass

        if sign is None:
            sign = self.authn_requests_signed

        if sign:
            request.signature = pre_signature_part(request.id,
                                                   self.sec.my_cert, 1)
            to_sign = [(class_name(request), request.id)]
        else:
            to_sign = []

        request.name_id_policy = name_id_policy
        request.issuer = self._issuer(spentityid)

        logger.info("REQUEST: %s" % request)

        return signed_instance_factory(request, self.sec, to_sign)
Exemple #15
0
    def create_authn_request(self,
                             destination,
                             vorg="",
                             scoping=None,
                             binding=saml2.BINDING_HTTP_POST,
                             nameid_format=NAMEID_FORMAT_TRANSIENT,
                             service_url_binding=None,
                             id=0,
                             consent=None,
                             extensions=None,
                             sign=None,
                             allow_create=False):
        """ Creates an authentication request.
        
        :param destination: Where the request should be sent.
        :param vorg: The virtual organization the service belongs to.
        :param scoping: The scope of the request
        :param binding: The protocol to use for the Response !!
        :param nameid_format: Format of the NameID
        :param service_url_binding: Where the reply should be sent dependent
            on reply binding.
        :param id: The identifier for this request
        :param consent: Whether the principal have given her consent
        :param extensions: Possible extensions
        :param sign: Whether the request should be signed or not.
        :param allow_create: If the identity provider is allowed, in the course
            of fulfilling the request, to create a new identifier to represent
            the principal.
        :return: <samlp:AuthnRequest> instance
        """

        if service_url_binding is None:
            service_url = self.service_url(binding)
        else:
            service_url = self.service_url(service_url_binding)

        if binding == BINDING_PAOS:
            my_name = None
            location = None
        else:
            my_name = self._my_name()

        if allow_create:
            allow_create = "true"
        else:
            allow_create = "false"

        # Profile stuff, should be configurable
        if nameid_format is None or nameid_format == NAMEID_FORMAT_TRANSIENT:
            name_id_policy = samlp.NameIDPolicy(allow_create=allow_create,
                                                format=NAMEID_FORMAT_TRANSIENT)
        else:
            name_id_policy = samlp.NameIDPolicy(allow_create=allow_create,
                                                format=nameid_format)

        if vorg:
            try:
                name_id_policy.sp_name_qualifier = vorg
                name_id_policy.format = saml.NAMEID_FORMAT_PERSISTENT
            except KeyError:
                pass

        return self._message(AuthnRequest,
                             destination,
                             id,
                             consent,
                             extensions,
                             sign,
                             assertion_consumer_service_url=service_url,
                             protocol_binding=binding,
                             name_id_policy=name_id_policy,
                             provider_name=my_name,
                             scoping=scoping)