def create_attribute_query(self, destination, name_id=None, attribute=None, message_id=0, consent=None, extensions=None, sign=False, sign_prepare=False, **kwargs): """ Constructs an AttributeQuery :param destination: To whom the query should be sent :param name_id: The identifier of the subject :param attribute: A dictionary of attributes and values that is asked for. The key are one of 4 variants: 3-tuple of name_format,name and friendly_name, 2-tuple of name_format and name, 1-tuple with name or just the name as a string. :param sp_name_qualifier: The unique identifier of the service provider or affiliation of providers for whom the identifier was generated. :param name_qualifier: The unique identifier of the identity provider that generated the identifier. :param format: The format of the name ID :param message_id: The identifier of the session :param consent: Whether the principal have given her consent :param extensions: Possible extensions :param sign: Whether the query should be signed or not. :param sign_prepare: Whether the Signature element should be added. :return: Tuple of request ID and an AttributeQuery instance """ if name_id is None: if "subject_id" in kwargs: name_id = saml.NameID(text=kwargs["subject_id"]) for key in ["sp_name_qualifier", "name_qualifier", "format"]: try: setattr(name_id, key, kwargs[key]) except KeyError: pass else: raise AttributeError("Missing required parameter") elif isinstance(name_id, six.string_types): name_id = saml.NameID(text=name_id) for key in ["sp_name_qualifier", "name_qualifier", "format"]: try: setattr(name_id, key, kwargs[key]) except KeyError: pass subject = saml.Subject(name_id=name_id) if attribute: attribute = do_attributes(attribute) try: nsprefix = kwargs["nsprefix"] except KeyError: nsprefix = None return self._message(AttributeQuery, destination, message_id, consent, extensions, sign, sign_prepare, subject=subject, attribute=attribute, nsprefix=nsprefix)
def _getNameID(self): if self.user_name.find('@') >= 0: user_name = self.user_name else: user_name = self.user_name + "@" + self.config.get("apps_domain") return saml.NameID(format=saml.NAMEID_FORMAT_EMAILADDRESS, text=user_name)
def _create_subject(self, user, expiration_time, recipient): """Create an object that represents a SAML Subject. <ns0:Subject> <ns0:NameID> [email protected]</ns0:NameID> <ns0:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <ns0:SubjectConfirmationData NotOnOrAfter="2014-08-19T11:53:57.243106Z" Recipient="http://beta.com/Shibboleth.sso/SAML2/POST" /> </ns0:SubjectConfirmation> </ns0:Subject> :returns: XML <Subject> object """ name_id = saml.NameID() name_id.set_text(user) subject_conf_data = saml.SubjectConfirmationData() subject_conf_data.recipient = recipient subject_conf_data.not_on_or_after = expiration_time subject_conf = saml.SubjectConfirmation() subject_conf.method = saml.SCM_BEARER subject_conf.subject_confirmation_data = subject_conf_data subject = saml.Subject() subject.subject_confirmation = subject_conf subject.name_id = name_id return subject
def do_authz_decision_query(self, entity_id, action, subject_id, nameid_format, evidence=None, resource=None, sp_name_qualifier=None, name_qualifier=None, consent=None, extensions=None, sign=False): subject = saml.Subject( name_id=saml.NameID(text=subject_id, format=nameid_format, sp_name_qualifier=sp_name_qualifier, name_qualifier=name_qualifier)) srvs = self.metadata.authz_service(entity_id, BINDING_SOAP) for dest in locations(srvs): resp = self._use_soap(dest, "authz_decision_query", action=action, evidence=evidence, resource=resource, subject=subject) if resp: return resp return None
def testAccessors(self): """Test for LogoutRequest accessors""" self.lr.id = "request id" self.lr.version = saml2.VERSION self.lr.issue_instant = "2007-09-14T01:05:02Z" self.lr.destination = "http://www.example.com/Destination" self.lr.consent = saml.CONSENT_UNSPECIFIED self.lr.issuer = saml.Issuer() self.lr.signature = ds.Signature() self.lr.extensions = samlp.Extensions() self.lr.not_on_or_after = "2007-10-14T01:05:02Z" self.lr.reason = "http://www.example.com/Reason" self.lr.base_id = saml.BaseID() self.lr.name_id = saml.NameID() self.lr.encrypted_id = saml.EncryptedID() self.lr.session_index = samlp.SessionIndex() new_lr = samlp.logout_request_from_string(self.lr.to_string()) assert new_lr.id == "request id" assert new_lr.version == saml2.VERSION assert new_lr.issue_instant == "2007-09-14T01:05:02Z" assert new_lr.destination == "http://www.example.com/Destination" assert new_lr.consent == saml.CONSENT_UNSPECIFIED assert isinstance(new_lr.issuer, saml.Issuer) assert isinstance(new_lr.signature, ds.Signature) assert isinstance(new_lr.extensions, samlp.Extensions) assert new_lr.not_on_or_after == "2007-10-14T01:05:02Z" assert new_lr.reason == "http://www.example.com/Reason" assert isinstance(new_lr.base_id, saml.BaseID) assert isinstance(new_lr.name_id, saml.NameID) assert isinstance(new_lr.encrypted_id, saml.EncryptedID) assert isinstance(new_lr.session_index[0], samlp.SessionIndex)
def test_authz_decision_query(self): conf = config.SPConfig() conf.load_file("server3_conf") client = Saml2Client(conf) AVA = { 'mail': u'*****@*****.**', 'eduPersonTargetedID': '95e9ae91dbe62d35198fbbd5e1fb0976', 'displayName': u'Roland Hedberg', 'uid': 'http://roland.hedberg.myopenid.com/' } sp_entity_id = "sp_entity_id" in_response_to = "1234" consumer_url = "http://example.com/consumer" name_id = saml.NameID(saml.NAMEID_FORMAT_TRANSIENT, text="name_id") policy = Policy() ava = Assertion(AVA) assertion = ava.construct(sp_entity_id, in_response_to, consumer_url, name_id, conf.attribute_converters, policy, issuer=client._issuer()) adq = client.authz_decision_query_using_assertion( "entity_id", assertion, "read", "http://example.com/text") assert adq print adq assert adq.keyswv() != [] assert adq.destination == "entity_id" assert adq.resource == "http://example.com/text" assert adq.action[0].text == "read"
def create_attribute_query(self, session_id, subject_id, destination, issuer_id=None, attribute=None, sp_name_qualifier=None, name_qualifier=None, nameid_format=None, sign=False): """ Constructs an AttributeQuery :param session_id: The identifier of the session :param subject_id: The identifier of the subject :param destination: To whom the query should be sent :param issuer_id: Identifier of the issuer :param attribute: A dictionary of attributes and values that is asked for. The key are one of 4 variants: 3-tuple of name_format,name and friendly_name, 2-tuple of name_format and name, 1-tuple with name or just the name as a string. :param sp_name_qualifier: The unique identifier of the service provider or affiliation of providers for whom the identifier was generated. :param name_qualifier: The unique identifier of the identity provider that generated the identifier. :param nameid_format: The format of the name ID :param sign: Whether the query should be signed or not. :return: An AttributeQuery instance """ subject = saml.Subject(name_id=saml.NameID( text=subject_id, format=nameid_format, sp_name_qualifier=sp_name_qualifier, name_qualifier=name_qualifier), ) query = samlp.AttributeQuery( id=session_id, version=VERSION, issue_instant=instant(), destination=destination, issuer=self._issuer(issuer_id), subject=subject, ) if sign: query.signature = pre_signature_part(query.id, self.sec.my_cert, 1) if attribute: query.attribute = do_attributes(attribute) if sign: signed_query = self.sec.sign_attribute_query_using_xmlsec("%s" % query) return samlp.attribute_query_from_string(signed_query) else: return query
def test_subject(): subject = utils.factory(saml.Subject, text="_aaa", name_id=saml.NameID( text=saml.NAMEID_FORMAT_TRANSIENT)) assert _eq(subject.keyswv(), ["text", "name_id"]) assert subject.text == "_aaa" assert subject.name_id.text == saml.NAMEID_FORMAT_TRANSIENT
def persistent_nameid(self, sp_name_qualifier, userid): """ Get or create a persistent identifier for this object to be used when communicating with servers using a specific SPNameQualifier :param sp_name_qualifier: An identifier for a 'context' :param userid: The local permanent identifier of the object :return: A persistent random identifier. """ subj_id = self.persistent(sp_name_qualifier, userid) return saml.NameID(format=saml.NAMEID_FORMAT_PERSISTENT, sp_name_qualifier=sp_name_qualifier, text=subj_id)
def create_attribute_query(self, destination, subject_id, attribute=None, sp_name_qualifier=None, name_qualifier=None, nameid_format=None, id=0, consent=None, extensions=None, sign=False, **kwargs): """ Constructs an AttributeQuery :param destination: To whom the query should be sent :param subject_id: The identifier of the subject :param attribute: A dictionary of attributes and values that is asked for. The key are one of 4 variants: 3-tuple of name_format,name and friendly_name, 2-tuple of name_format and name, 1-tuple with name or just the name as a string. :param sp_name_qualifier: The unique identifier of the service provider or affiliation of providers for whom the identifier was generated. :param name_qualifier: The unique identifier of the identity provider that generated the identifier. :param nameid_format: The format of the name ID :param id: The identifier of the session :param consent: Whether the principal have given her consent :param extensions: Possible extensions :param sign: Whether the query should be signed or not. :return: An AttributeQuery instance """ subject = saml.Subject( name_id=saml.NameID(text=subject_id, format=nameid_format, sp_name_qualifier=sp_name_qualifier, name_qualifier=name_qualifier)) if attribute: attribute = do_attributes(attribute) return self._message(AttributeQuery, destination, id, consent, extensions, sign, subject=subject, attribute=attribute)
def _get_vo_identifier(self, sp_name_qualifier, identity): try: vo = self.voconf[sp_name_qualifier] try: subj_id = identity[vo.common_identifier] except KeyError: raise MissingValue("Common identifier") except (KeyError, TypeError): raise UnknownVO("%s" % sp_name_qualifier) nameid_format = vo.nameid_format if not nameid_format: nameid_format = saml.NAMEID_FORMAT_PERSISTENT return saml.NameID(format=nameid_format, sp_name_qualifier=sp_name_qualifier, text=subj_id)
def create_logout_request(subject_id, destination, issuer_entity_id, req_entity_id, sign=True): config = SPConfig() config.load(sp_config) sp_client = Saml2Client(config=config) # construct a request logout_request = samlp.LogoutRequest(id='a123456', version=VERSION, destination=destination, issuer=saml.Issuer( text=req_entity_id, format=saml.NAMEID_FORMAT_ENTITY), name_id=saml.NameID(text=subject_id)) return logout_request
def create_logout_request(self, destination, issuer_entity_id, subject_id=None, name_id=None, reason=None, expire=None, id=0, consent=None, extensions=None, sign=False): """ Constructs a LogoutRequest :param destination: Destination of the request :param issuer_entity_id: The entity ID of the IdP the request is target at. :param subject_id: The identifier of the subject :param name_id: A NameID instance identifying the subject :param reason: An indication of the reason for the logout, in the form of a URI reference. :param expire: The time at which the request expires, after which the recipient may discard the message. :param id: Request identifier :param consent: Whether the principal have given her consent :param extensions: Possible extensions :param sign: Whether the query should be signed or not. :return: A LogoutRequest instance """ if subject_id: name_id = saml.NameID(text=self.users.get_entityid( subject_id, issuer_entity_id, False)) if not name_id: raise Exception("Missing subject identification") return self._message(LogoutRequest, destination, id, consent, extensions, sign, name_id=name_id, reason=reason, not_on_or_after=expire)
def transient_nameid(self, sp_entity_id, userid): """ Returns a random one-time identifier. One-time means it is kept around as long as the session is active. :param sp_entity_id: A qualifier to bind the created identifier to :param userid: The local persistent identifier for the subject. :return: The created identifier, """ temp_id = sid() while True: try: _ = self._get_local("transient", sp_entity_id, temp_id) temp_id = sid() except KeyError: break self._store("transient", sp_entity_id, userid, temp_id) self.map.sync() return saml.NameID(format=saml.NAMEID_FORMAT_TRANSIENT, sp_name_qualifier=sp_entity_id, text=temp_id)
def _get_vo_identifier(self, sp_name_qualifier, userid, identity): try: vo_conf = self.voconf[sp_name_qualifier] if "common_identifier" in vo_conf: try: subj_id = identity[vo_conf["common_identifier"]] except KeyError: raise MissingValue("Common identifier") else: return self.persistent_nameid(sp_name_qualifier, userid) except (KeyError, TypeError): raise UnknownVO("%s" % sp_name_qualifier) try: nameid_format = vo_conf["nameid_format"] except KeyError: nameid_format = saml.NAMEID_FORMAT_PERSISTENT return saml.NameID(format=nameid_format, sp_name_qualifier=sp_name_qualifier, text=subj_id)
def slo(self, request): """ generate a SAML2 logout request; reset session; return IDP URL """ session = request.SESSION session.set(self.session_auth_key, False) del session[self.session_user_properties] config = self._saml2_config() scl = Saml2Client(config) samluid = session.get(self.session_samluid_key, '') entityid = config.metadata.keys()[0] sp_url = self.saml2_sp_url actual_url = request.get("ACTUAL_URL", '') if not actual_url.startswith(sp_url): # the request was made from within a context we cannot handle return None session.set(self.session_storedurl_key, request.URL1) # we cannot simply call global_logout on the client since it doesn't know about our user... srvs = scl.metadata.single_logout_service(entityid, BINDING_HTTP_REDIRECT, "idpsso") destination = destinations(srvs)[0] samlrequest = scl.create_logout_request( destination, entityid, name_id=saml.NameID(text=samluid)) samlrequest.session_index = samlp.SessionIndex( session.get(self.session_samlsessionindex_key)) to_sign = [] samlrequest = signed_instance_factory(samlrequest, scl.sec, to_sign) logger.info('SSO logout request: %s' % samlrequest.to_string()) session_id = samlrequest.id rstate = scl._relay_state(session_id) msg = http_redirect_message(samlrequest, destination, rstate) headers = dict(msg['headers']) location = headers['Location'] logger.info( 'attempting to post: {loc}'.format(loc=headers['Location'])) return location
def construct_logout_request(self, subject_id, destination, issuer_entity_id, reason=None, expire=None): """ Constructs a LogoutRequest :param subject_id: The identifier of the subject :param destination: :param issuer_entity_id: The entity ID of the IdP the request is target at. :param reason: An indication of the reason for the logout, in the form of a URI reference. :param expire: The time at which the request expires, after which the recipient may discard the message. :return: A LogoutRequest instance """ session_id = sid() # create NameID from subject_id name_id = saml.NameID( text=self.users.get_entityid(subject_id, issuer_entity_id, False)) request = samlp.LogoutRequest(id=session_id, version=VERSION, issue_instant=instant(), destination=destination, issuer=self._issuer(), name_id=name_id) if reason: request.reason = reason if expire: request.not_on_or_after = expire return request
def email_nameid(self, sp_name_qualifier, userid): return saml.NameID(format=saml.NAMEID_FORMAT_EMAILADDRESS, sp_name_qualifier=sp_name_qualifier, text=userid)