Exemplo n.º 1
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=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_url"]
            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()

        # 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", "scoping"]:
            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:
                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, **args)
        return self._message(AuthnRequest, destination, message_id, consent,
                             extensions, sign, sign_prepare,
                             protocol_binding=binding,
                             scoping=scoping, nsprefix=nsprefix, **args)
Exemplo n.º 2
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)
Exemplo n.º 3
0
def test_flow():
    sp = Saml2Client(config_file="servera_conf")

    with closing(Server(config_file="idp_all_conf")) as idp:
        relay_state = "FOO"
        # -- dummy request ---
        orig_req = AuthnRequest(issuer=sp._issuer(),
                                name_id_policy=NameIDPolicy(
                                    allow_create="true",
                                    format=NAMEID_FORMAT_TRANSIENT))

        # == Create an AuthnRequest response

        name_id = idp.ident.transient_nameid(sp.config.entityid, "id12")
        binding, destination = idp.pick_binding("assertion_consumer_service",
                                                entity_id=sp.config.entityid)
        resp = idp.create_authn_response(
            {
                "eduPersonEntitlement": "Short stop",
                "surName": "Jeter",
                "givenName": "Derek",
                "mail": "*****@*****.**",
                "title": "The man"
            },
            "id-123456789",
            destination,
            sp.config.entityid,
            name_id=name_id,
            authn=AUTHN)

        hinfo = idp.apply_binding(binding, "%s" % resp, destination,
                                  relay_state)

        # ------- @SP ----------

        xmlstr = get_msg(hinfo, binding)
        aresp = sp.parse_authn_request_response(xmlstr, binding,
                                                {resp.in_response_to: "/"})

        binding, destination = sp.pick_binding("authn_query_service",
                                               entity_id=idp.config.entityid)

        authn_context = requested_authn_context(INTERNETPROTOCOLPASSWORD)

        subject = aresp.assertion.subject

        aq_id, aq = sp.create_authn_query(subject, destination, authn_context)

        print(aq)

        assert isinstance(aq, AuthnQuery)
        binding = BINDING_SOAP

        hinfo = sp.apply_binding(binding, "%s" % aq, destination, "state2")

        # -------- @IDP ----------

        xmlstr = get_msg(hinfo, binding)

        pm = idp.parse_authn_query(xmlstr, binding)

        msg = pm.message
        assert msg.id == aq.id

        p_res = idp.create_authn_query_response(msg.subject, msg.session_index,
                                                msg.requested_authn_context)

        print(p_res)

        hinfo = idp.apply_binding(binding,
                                  "%s" % p_res,
                                  "",
                                  "state2",
                                  response=True)

        # ------- @SP ----------

        xmlstr = get_msg(hinfo, binding)

        final = sp.parse_authn_query_response(xmlstr, binding)

        print(final)

        assert final.response.id == p_res.id
Exemplo n.º 4
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)
Exemplo n.º 5
0
def test_basic_flow():
    sp = Saml2Client(config_file="servera_conf")
    idp = Server(config_file="idp_all_conf")

    # -------- @IDP -------------

    relay_state = "FOO"
    # -- dummy request ---
    orig_req = AuthnRequest(issuer=sp._issuer(),
                            name_id_policy=NameIDPolicy(
                                allow_create="true",
                                format=NAMEID_FORMAT_TRANSIENT))

    # == Create an AuthnRequest response

    name_id = idp.ident.transient_nameid("id12", sp.config.entityid)

    binding, destination = idp.pick_binding("assertion_consumer_service",
                                            entity_id=sp.config.entityid)
    resp = idp.create_authn_response(
        {
            "eduPersonEntitlement": "Short stop",
            "surName": "Jeter",
            "givenName": "Derek",
            "mail": "*****@*****.**",
            "title": "The man"
        },
        "id-123456789",
        destination,
        sp.config.entityid,
        name_id=name_id,
        authn=AUTHN)

    hinfo = idp.apply_binding(binding, "%s" % resp, destination, relay_state)

    # --------- @SP -------------

    xmlstr = get_msg(hinfo, binding)

    aresp = sp.parse_authn_request_response(xmlstr, binding,
                                            {resp.in_response_to: "/"})

    # == Look for assertion X

    asid = aresp.assertion.id

    binding, destination = sp.pick_binding("assertion_id_request_service",
                                           entity_id=idp.config.entityid)

    hinfo = sp.apply_binding(binding, asid, destination)

    # ---------- @IDP ------------

    aid = get_msg(hinfo, binding, response=False)

    # == construct response

    resp = idp.create_assertion_id_request_response(aid)

    hinfo = idp.apply_binding(binding, "%s" % resp, None, "", response=True)

    # ----------- @SP -------------

    xmlstr = get_msg(hinfo, binding, response=True)

    final = sp.parse_assertion_id_request_response(xmlstr, binding)

    print final.response
    assert isinstance(final.response, Assertion)
Exemplo n.º 6
0
    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)
Exemplo n.º 7
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
Exemplo n.º 8
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: either a tuple of request ID and <samlp:AuthnRequest> instance
                 or a tuple of request ID and str when sign is set to True
        """
        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)