def create_ecp_authn_request_response(self, acs_url, identity, in_response_to, destination, sp_entity_id, name_id_policy=None, userid=None, name_id=None, authn=None, issuer=None, sign_response=False, sign_assertion=False, **kwargs): # ---------------------------------------- # <ecp:Response # ---------------------------------------- ecp_response = ecp.Response(assertion_consumer_service_url=acs_url) header = soapenv.Header() header.extension_elements = [element_to_extension_element(ecp_response)] # ---------------------------------------- # <samlp:Response # ---------------------------------------- response = self.create_authn_response(identity, in_response_to, destination, sp_entity_id, name_id_policy, userid, name_id, authn, issuer, sign_response, sign_assertion) body = soapenv.Body() body.extension_elements = [element_to_extension_element(response)] soap_envelope = soapenv.Envelope(header=header, body=body) return "%s" % soap_envelope
def ecp_response(target_url, response): # ---------------------------------------- # <ecp:Response # ---------------------------------------- ecp_response = ecp.Response(assertion_consumer_service_url=target_url) header = soapenv.Header() header.extension_elements = [element_to_extension_element(ecp_response)] # ---------------------------------------- # <samlp:Response # ---------------------------------------- body = soapenv.Body() body.extension_elements = [element_to_extension_element(response)] soap_envelope = soapenv.Envelope(header=header, body=body) return "%s" % soap_envelope
def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=""): try: # Picks a binding to use for sending the Request to the IDP _binding, destination = _cli.pick_binding("single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s", _binding, destination) # Binding here is the response binding that is which binding the # IDP should use to return the response. acs = _cli.config.getattr("endpoints", "sp")["assertion_consumer_service"] # just pick one endp, return_binding = acs[0] extensions = None cert = None if _cli.config.generate_cert_func is not None: cert_str, req_key_str = _cli.config.generate_cert_func() cert = {"cert": cert_str, "key": req_key_str} spcertenc = SPCertEnc(x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_str))) extensions = Extensions(extension_elements=[ element_to_extension_element(spcertenc) ]) req_id, req = _cli.create_authn_request( destination, binding=return_binding, extensions=extensions, nameid_format=NAMEID_FORMAT_PERSISTENT, ) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate, sigalg=sigalg) _sid = req_id if cert is not None: self.cache.outstanding_certs[_sid] = cert except Exception as exc: logger.exception(exc) resp = ServiceError("Failed to construct the AuthnRequest: %s" % exc) return resp # remember the request self.cache.outstanding_queries[_sid] = came_from return self.response(_binding, ht_args, do_not_start_response=True)
def create_ecp_authn_request_response(self, acs_url, identity, in_response_to, destination, sp_entity_id, name_id_policy=None, userid=None, name_id=None, authn=None, issuer=None, sign_response=False, sign_assertion=False, **kwargs): # ---------------------------------------- # <ecp:Response # ---------------------------------------- ecp_response = ecp.Response(assertion_consumer_service_url=acs_url) header = soapenv.Header() header.extension_elements = [ element_to_extension_element(ecp_response) ] # ---------------------------------------- # <samlp:Response # ---------------------------------------- response = self.create_authn_response(identity, in_response_to, destination, sp_entity_id, name_id_policy, userid, name_id, authn, issuer, sign_response, sign_assertion) body = soapenv.Body() body.extension_elements = [element_to_extension_element(response)] soap_envelope = soapenv.Envelope(header=header, body=body) return "%s" % soap_envelope
def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=""): try: # Picks a binding to use for sending the Request to the IDP _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id ) logger.debug("binding: %s, destination: %s", _binding, destination) # Binding here is the response binding that is which binding the # IDP should use to return the response. acs = _cli.config.getattr("endpoints", "sp")["assertion_consumer_service"] # just pick one endp, return_binding = acs[0] extensions = None cert = None if _cli.config.generate_cert_func is not None: cert_str, req_key_str = _cli.config.generate_cert_func() cert = {"cert": cert_str, "key": req_key_str} spcertenc = SPCertEnc( x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_str) ) ) extensions = Extensions( extension_elements=[element_to_extension_element(spcertenc)] ) req_id, req = _cli.create_authn_request( destination, binding=return_binding, extensions=extensions, nameid_format=NAMEID_FORMAT_PERSISTENT, ) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding( _binding, "%s" % req, destination, relay_state=_rstate, sigalg=sigalg ) _sid = req_id if cert is not None: self.cache.outstanding_certs[_sid] = cert except Exception as exc: logger.exception(exc) resp = ServiceError("Failed to construct the AuthnRequest: %s" % exc) return resp # remember the request self.cache.outstanding_queries[_sid] = came_from return self.response(_binding, ht_args, do_not_start_response=True)
def test_attribute_element_to_extension_element(): attr = create_class_from_xml_string(Attribute, saml2_data.TEST_ATTRIBUTE) ee = saml2_tophat.element_to_extension_element(attr) print(ee.__dict__) assert ee.tag == "Attribute" assert ee.namespace == 'urn:oasis:names:tc:SAML:2.0:assertion' assert _eq(ee.attributes.keys(), ['FriendlyName', 'Name', 'NameFormat']) assert ee.attributes["FriendlyName"] == 'test attribute' assert ee.attributes["Name"] == "testAttribute" assert ee.attributes["NameFormat"] == \ 'urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified' assert len(ee.children) == 2 for child in ee.children: # children are also extension element instances assert child.namespace == 'urn:oasis:names:tc:SAML:2.0:assertion' assert child.tag == "AttributeValue"
def from_dict(val, onts, mdb_safe=False): """ Converts a dictionary into a pysaml2 object :param val: A dictionary :param onts: Dictionary of schemas to use in the conversion :return: The pysaml2 object instance """ if isinstance(val, dict): if "__class__" in val: ns, typ = val["__class__"].split("&") cls = getattr(onts[ns], typ) if cls is md.Extensions: lv = [] for key, ditems in val.items(): if key in EXP_SKIP: continue for item in ditems: ns, typ = item["__class__"].split("&") cls = getattr(onts[ns], typ) kwargs = _kwa(item, onts, mdb_safe) inst = cls(**kwargs) lv.append(element_to_extension_element(inst)) return lv else: kwargs = _kwa(val, onts, mdb_safe) inst = cls(**kwargs) return inst else: res = {} for key, v in val.items(): if mdb_safe: key = key.replace("__", ".") res[key] = from_dict(v, onts) return res elif isinstance(val, six.string_types): return val elif isinstance(val, list): return [from_dict(v, onts) for v in val] else: return val
def challenge(self, environ, _status, _app_headers, _forget_headers): _cli = self.saml_client if "REMOTE_USER" in environ: name_id = decode(environ["REMOTE_USER"]) _cli = self.saml_client path_info = environ["PATH_INFO"] if "samlsp.logout" in environ: responses = _cli.global_logout(name_id) return self._handle_logout(responses) if "samlsp.pending" in environ: response = environ["samlsp.pending"] if isinstance(response, HTTPRedirection): response.headers += _forget_headers return response # logger = environ.get('repoze.who.logger','') # Which page was accessed to get here came_from = construct_came_from(environ) environ["myapp.came_from"] = came_from logger.debug("[sp.challenge] RelayState >> '%s'", came_from) # Am I part of a virtual organization or more than one ? try: vorg_name = environ["myapp.vo"] except KeyError: try: vorg_name = _cli.vorg._name except AttributeError: vorg_name = "" logger.info("[sp.challenge] VO: %s", vorg_name) # If more than one idp and if none is selected, I have to do wayf (done, response) = self._pick_idp(environ, came_from) # Three cases: -1 something went wrong or Discovery service used # 0 I've got an IdP to send a request to # >0 ECP in progress logger.debug("_idp_pick returned: %s", done) if done == -1: return response elif done > 0: self.outstanding_queries[done] = came_from return ECP_response(response) else: entity_id = response logger.info("[sp.challenge] entity_id: %s", entity_id) # Do the AuthnRequest _binding = BINDING_HTTP_REDIRECT try: srvs = _cli.metadata.single_sign_on_service(entity_id, _binding) logger.debug("srvs: %s", srvs) dest = srvs[0]["location"] logger.debug("destination: %s", dest) extensions = None cert = None if _cli.config.generate_cert_func is not None: cert_str, req_key_str = _cli.config.generate_cert_func() cert = {"cert": cert_str, "key": req_key_str} spcertenc = SPCertEnc( x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_str) ) ) extensions = Extensions( extension_elements=[element_to_extension_element(spcertenc)] ) if _cli.authn_requests_signed: _sid = saml2_tophat.s_utils.sid() req_id, msg_str = _cli.create_authn_request( dest, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, extensions=extensions, ) _sid = req_id else: req_id, req = _cli.create_authn_request( dest, vorg=vorg_name, sign=False, extensions=extensions ) msg_str = "%s" % req _sid = req_id if cert is not None: self.outstanding_certs[_sid] = cert ht_args = _cli.apply_binding( _binding, msg_str, destination=dest, relay_state=came_from, sign=_cli.authn_requests_signed, ) logger.debug("ht_args: %s", ht_args) except Exception as exc: logger.exception(exc) raise Exception("Failed to construct the AuthnRequest: %s" % exc) try: ret = _cli.config.getattr("endpoints", "sp")["discovery_response"][0][0] if (environ["PATH_INFO"]) in ret and ret.split(environ["PATH_INFO"])[ 1 ] == "": query = parse_qs(environ["QUERY_STRING"]) sid = query["sid"][0] came_from = self.outstanding_queries[sid] except: pass # remember the request self.outstanding_queries[_sid] = came_from if not ht_args["data"] and ht_args["headers"][0][0] == "Location": logger.debug("redirect to: %s", ht_args["headers"][0][1]) return HTTPSeeOther(headers=ht_args["headers"]) else: return ht_args["data"]
def ecp_auth_request(cls, entityid=None, relay_state="", sign=False): """ Makes an authentication request. :param entityid: The entity ID of the IdP to send the request to :param relay_state: To where the user should be returned after successfull log in. :param sign: Whether the request should be signed or not. :return: AuthnRequest response """ eelist = [] # ---------------------------------------- # <paos:Request> # ---------------------------------------- my_url = cls.service_urls(BINDING_PAOS)[0] # must_understand and actor according to the standard # paos_request = paos.Request(must_understand="1", actor=ACTOR, response_consumer_url=my_url, service=SERVICE) eelist.append(element_to_extension_element(paos_request)) # ---------------------------------------- # <samlp:AuthnRequest> # ---------------------------------------- logger.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP)) location = cls._sso_location(entityid, binding=BINDING_SOAP) req_id, authn_req = cls.create_authn_request( location, binding=BINDING_PAOS, service_url_binding=BINDING_PAOS) body = soapenv.Body() body.extension_elements = [element_to_extension_element(authn_req)] # ---------------------------------------- # <ecp:Request> # ---------------------------------------- # idp = samlp.IDPEntry( # provider_id = "https://idp.example.org/entity", # name = "Example identity provider", # loc = "https://idp.example.org/saml2/sso", # ) # # idp_list = samlp.IDPList(idp_entry= [idp]) idp_list = None ecp_request = ecp.Request( actor=ACTOR, must_understand="1", provider_name=None, issuer=saml.Issuer(text=authn_req.issuer.text), idp_list=idp_list) eelist.append(element_to_extension_element(ecp_request)) # ---------------------------------------- # <ecp:RelayState> # ---------------------------------------- relay_state = ecp.RelayState(actor=ACTOR, must_understand="1", text=relay_state) eelist.append(element_to_extension_element(relay_state)) header = soapenv.Header() header.extension_elements = eelist # ---------------------------------------- # The SOAP envelope # ---------------------------------------- soap_envelope = soapenv.Envelope(header=header, body=body) return req_id, "%s" % soap_envelope
from pathutils import full_path __author__ = 'roland' conf = config.SPConfig() conf.load_file("server_conf") client = Saml2Client(conf) # place a certificate in an authn request cert = read_cert_from_file(full_path("test.pem"), "pem") spcertenc = SPCertEnc(x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert))) extensions = Extensions( extension_elements=[element_to_extension_element(spcertenc)]) req_id, req = client.create_authn_request( "http://www.example.com/sso", "urn:mace:example.com:it:tek", nameid_format=saml.NAMEID_FORMAT_PERSISTENT, message_id="666", extensions=extensions) print(req) # Get a certificate from an authn request xml = "%s" % req parsed = authn_request_from_string(xml)
def challenge(self, environ, _status, _app_headers, _forget_headers): _cli = self.saml_client if "REMOTE_USER" in environ: name_id = decode(environ["REMOTE_USER"]) _cli = self.saml_client path_info = environ["PATH_INFO"] if "samlsp.logout" in environ: responses = _cli.global_logout(name_id) return self._handle_logout(responses) if "samlsp.pending" in environ: response = environ["samlsp.pending"] if isinstance(response, HTTPRedirection): response.headers += _forget_headers return response # logger = environ.get('repoze.who.logger','') # Which page was accessed to get here came_from = construct_came_from(environ) environ["myapp.came_from"] = came_from logger.debug("[sp.challenge] RelayState >> '%s'", came_from) # Am I part of a virtual organization or more than one ? try: vorg_name = environ["myapp.vo"] except KeyError: try: vorg_name = _cli.vorg._name except AttributeError: vorg_name = "" logger.info("[sp.challenge] VO: %s", vorg_name) # If more than one idp and if none is selected, I have to do wayf (done, response) = self._pick_idp(environ, came_from) # Three cases: -1 something went wrong or Discovery service used # 0 I've got an IdP to send a request to # >0 ECP in progress logger.debug("_idp_pick returned: %s", done) if done == -1: return response elif done > 0: self.outstanding_queries[done] = came_from return ECP_response(response) else: entity_id = response logger.info("[sp.challenge] entity_id: %s", entity_id) # Do the AuthnRequest _binding = BINDING_HTTP_REDIRECT try: srvs = _cli.metadata.single_sign_on_service( entity_id, _binding) logger.debug("srvs: %s", srvs) dest = srvs[0]["location"] logger.debug("destination: %s", dest) extensions = None cert = None if _cli.config.generate_cert_func is not None: cert_str, req_key_str = _cli.config.generate_cert_func() cert = {"cert": cert_str, "key": req_key_str} spcertenc = SPCertEnc(x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_str))) extensions = Extensions(extension_elements=[ element_to_extension_element(spcertenc) ]) if _cli.authn_requests_signed: _sid = saml2_tophat.s_utils.sid() req_id, msg_str = _cli.create_authn_request( dest, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, extensions=extensions, ) _sid = req_id else: req_id, req = _cli.create_authn_request( dest, vorg=vorg_name, sign=False, extensions=extensions) msg_str = "%s" % req _sid = req_id if cert is not None: self.outstanding_certs[_sid] = cert ht_args = _cli.apply_binding( _binding, msg_str, destination=dest, relay_state=came_from, sign=_cli.authn_requests_signed, ) logger.debug("ht_args: %s", ht_args) except Exception as exc: logger.exception(exc) raise Exception("Failed to construct the AuthnRequest: %s" % exc) try: ret = _cli.config.getattr("endpoints", "sp")["discovery_response"][0][0] if (environ["PATH_INFO"]) in ret and ret.split( environ["PATH_INFO"])[1] == "": query = parse_qs(environ["QUERY_STRING"]) sid = query["sid"][0] came_from = self.outstanding_queries[sid] except: pass # remember the request self.outstanding_queries[_sid] = came_from if not ht_args["data"] and ht_args["headers"][0][0] == "Location": logger.debug("redirect to: %s", ht_args["headers"][0][1]) return HTTPSeeOther(headers=ht_args["headers"]) else: return ht_args["data"]
__author__ = 'roland' conf = config.SPConfig() conf.load_file("server_conf") client = Saml2Client(conf) # place a certificate in an authn request cert = read_cert_from_file(full_path("test.pem"), "pem") spcertenc = SPCertEnc( x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert))) extensions = Extensions( extension_elements=[element_to_extension_element(spcertenc)]) req_id, req = client.create_authn_request( "http://www.example.com/sso", "urn:mace:example.com:it:tek", nameid_format=saml.NAMEID_FORMAT_PERSISTENT, message_id="666", extensions=extensions) print(req) # Get a certificate from an authn request xml = "%s" % req
def ecp_auth_request(cls, entityid=None, relay_state="", sign=False): """ Makes an authentication request. :param entityid: The entity ID of the IdP to send the request to :param relay_state: To where the user should be returned after successfull log in. :param sign: Whether the request should be signed or not. :return: AuthnRequest response """ eelist = [] # ---------------------------------------- # <paos:Request> # ---------------------------------------- my_url = cls.service_urls(BINDING_PAOS)[0] # must_understand and actor according to the standard # paos_request = paos.Request(must_understand="1", actor=ACTOR, response_consumer_url=my_url, service=SERVICE) eelist.append(element_to_extension_element(paos_request)) # ---------------------------------------- # <samlp:AuthnRequest> # ---------------------------------------- logger.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP)) location = cls._sso_location(entityid, binding=BINDING_SOAP) req_id, authn_req = cls.create_authn_request( location, binding=BINDING_PAOS, service_url_binding=BINDING_PAOS) body = soapenv.Body() body.extension_elements = [element_to_extension_element(authn_req)] # ---------------------------------------- # <ecp:Request> # ---------------------------------------- # idp = samlp.IDPEntry( # provider_id = "https://idp.example.org/entity", # name = "Example identity provider", # loc = "https://idp.example.org/saml2/sso", # ) # # idp_list = samlp.IDPList(idp_entry= [idp]) idp_list = None ecp_request = ecp.Request(actor=ACTOR, must_understand="1", provider_name=None, issuer=saml.Issuer(text=authn_req.issuer.text), idp_list=idp_list) eelist.append(element_to_extension_element(ecp_request)) # ---------------------------------------- # <ecp:RelayState> # ---------------------------------------- relay_state = ecp.RelayState(actor=ACTOR, must_understand="1", text=relay_state) eelist.append(element_to_extension_element(relay_state)) header = soapenv.Header() header.extension_elements = eelist # ---------------------------------------- # The SOAP envelope # ---------------------------------------- soap_envelope = soapenv.Envelope(header=header, body=body) return req_id, "%s" % soap_envelope