def _authn_statement(self, authn_class=None, authn_auth=None, authn_decl=None, authn_decl_ref=None): """ Construct the AuthnStatement :param authn_class: Authentication Context Class reference :param authn_auth: Authenticating Authority :param authn_decl: Authentication Context Declaration :param authn_decl_ref: Authentication Context Declaration reference :return: An AuthnContext instance """ if authn_class: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl( authn_decl, authn_auth)) elif authn_decl_ref: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl_ref( authn_decl_ref, authn_auth)) else: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid())
def _authn_statement(self, authn_class=None, authn_auth=None, authn_decl=None, authn_decl_ref=None): """ Construct the AuthnStatement :param authn_class: Authentication Context Class reference :param authn_auth: Authenticating Authority :param authn_decl: Authentication Context Declaration :param authn_decl_ref: Authentication Context Declaration reference :return: An AuthnContext instance """ if authn_class: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl(authn_decl, authn_auth)) elif authn_decl_ref: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl_ref(authn_decl_ref, authn_auth)) else: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid())
def authn_statement(authn_class=None, authn_auth=None, authn_decl=None, authn_decl_ref=None, authn_instant="", subject_locality="", session_not_on_or_after=None): """ Construct the AuthnStatement :param authn_class: Authentication Context Class reference :param authn_auth: Authenticating Authority :param authn_decl: Authentication Context Declaration :param authn_decl_ref: Authentication Context Declaration reference :param authn_instant: When the Authentication was performed. Assumed to be seconds since the Epoch. :param subject_locality: Specifies the DNS domain name and IP address for the system from which the assertion subject was apparently authenticated. :return: An AuthnContext instance """ if authn_instant: _instant = instant(time_stamp=authn_instant) else: _instant = instant() if authn_class: res = factory(saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: res = factory(saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_decl( authn_decl, authn_auth)) elif authn_decl_ref: res = factory(saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_decl_ref( authn_decl_ref, authn_auth)) else: res = factory(saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after) if subject_locality: res.subject_locality = saml.SubjectLocality(text=subject_locality) return res
def authn_statement(authn_class=None, authn_auth=None, authn_decl=None, authn_decl_ref=None, authn_instant="", subject_locality="", session_not_on_or_after=None): """ Construct the AuthnStatement :param authn_class: Authentication Context Class reference :param authn_auth: Authenticating Authority :param authn_decl: Authentication Context Declaration :param authn_decl_ref: Authentication Context Declaration reference :param authn_instant: When the Authentication was performed. Assumed to be seconds since the Epoch. :param subject_locality: Specifies the DNS domain name and IP address for the system from which the assertion subject was apparently authenticated. :return: An AuthnContext instance """ if authn_instant: _instant = instant(time_stamp=authn_instant) else: _instant = instant() if authn_class: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_decl(authn_decl, authn_auth)) elif authn_decl_ref: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_decl_ref(authn_decl_ref, authn_auth)) else: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after) if subject_locality: res.subject_locality = saml.SubjectLocality(text=subject_locality) return res
def _status_response(self, response_class, issuer, status, sign=False, **kwargs): """ Create a StatusResponse. :param response_class: Which subclass of StatusResponse that should be used :param issuer: The issuer of the response message :param status: The return status of the response operation :param sign: Whether the response should be signed or not :param kwargs: Extra arguments to the response class :return: Class instance or string representation of the instance """ mid = sid() for key in ["destination", "binding"]: try: del kwargs[key] except KeyError: pass if not status: status = success_status_factory() response = response_class(issuer=issuer, id=mid, version=VERSION, issue_instant=instant(), status=status, **kwargs) if sign: return self.sign(response, mid) else: return response
def authz_decision_query(self, entityid, action, evidence=None, resource=None, subject=None, binding=saml2.BINDING_HTTP_REDIRECT, sign=None): """ Creates an authz decision query. :param entityid: The entity ID of the IdP to send the request to :param action: The action you want to perform (has to be at least one) :param evidence: Why you should be able to perform the action :param resource: The resource you want to perform the action on :param subject: Who wants to do the thing :param binding: Which binding to use for sending the request :param sign: Whether the request should be signed or not. :return: AuthzDecisionQuery instance """ spentityid = self._issuer() service_url = self.service_url() my_name = self._my_name() logger.info("spentityid: %s\nservice_url: %s\nmy_name: %s" % ( spentityid, service_url, my_name)) # authen_req = self.authn_request(session_id, location, # service_url, spentityid, my_name, vorg, # scoping, sign) request = samlp.AuthzDecisionQuery(action, evidence, resource, subject=subject, issuer=spentityid, id=sid(), issue_instant=instant(), version=VERSION, destination=entityid) return request
def assertion_factory(**kwargs): assertion = saml.Assertion(version=VERSION, id=sid(), issue_instant=instant()) for key, val in kwargs.items(): setattr(assertion, key, val) return assertion
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 make_logout_response(self, idp_entity_id, request_id, status_code, binding=BINDING_HTTP_REDIRECT): """ Constructs a LogoutResponse :param idp_entity_id: The entityid of the IdP that want to do the logout :param request_id: The Id of the request we are replying to :param status_code: The status code of the response :param binding: The type of binding that will be used for the response :return: A LogoutResponse instance """ destination = self.config.single_logout_services(idp_entity_id, binding)[0] status = samlp.Status(status_code=samlp.StatusCode(value=status_code)) response = samlp.LogoutResponse( id=sid(), version=VERSION, issue_instant=instant(), destination=destination, issuer=self.issuer(), in_response_to=request_id, status=status, ) return response, destination
def make_logout_response(self, idp_entity_id, request_id, status_code, binding=BINDING_HTTP_REDIRECT): """ Constructs a LogoutResponse :param idp_entity_id: The entityid of the IdP that want to do the logout :param request_id: The Id of the request we are replying to :param status_code: The status code of the response :param binding: The type of binding that will be used for the response :return: A LogoutResponse instance """ destination = self.config.single_logout_services( idp_entity_id, binding)[0] status = samlp.Status(status_code=samlp.StatusCode(value=status_code)) response = samlp.LogoutResponse( id=sid(), version=VERSION, issue_instant=instant(), destination=destination, issuer=self._issuer(), in_response_to=request_id, status=status, ) return response, destination
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 _authn_statement(self, authn_class=None, authn_auth=None, authn_decl=None): if authn_class: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_class_ref(authn_class, authn_auth), ) elif authn_decl: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl_ref(authn_decl), ) else: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid())
def _expiration(self, timeout, tformat="%a, %d-%b-%Y %H:%M:%S GMT"): if timeout == "now": return time_util.instant(tformat) elif timeout == "dawn": return time.strftime(tformat, time.gmtime(0)) else: # validity time should match lifetime of assertions return time_util.in_a_while(minutes=timeout, format=tformat)
def _authn_statement(self, authn_class=None, authn_auth=None, authn_decl=None): if authn_class: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl_ref(authn_decl)) else: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid())
def test_valid(): assert valid("2000-01-12T00:00:00Z") == False current_year = datetime.datetime.today().year assert valid("%d-01-12T00:00:00Z" % (current_year + 1)) == True this_instance = instant() time.sleep(1) assert valid(this_instance) == False # unless on a very fast machine :-) soon = in_a_while(seconds=10) assert valid(soon) == True
def message_args(self, message_id=0): if not message_id: message_id = sid(self.seed) return { "id": message_id, "version": VERSION, "issue_instant": instant(), "issuer": self._issuer() }
def _expiration(timeout, tformat=None): # Wed, 06-Jun-2012 01:34:34 GMT if not tformat: tformat = '%a, %d-%b-%Y %T GMT' if timeout == "now": return time_util.instant(tformat) else: # validity time should match lifetime of assertions return time_util.in_a_while(minutes=timeout, format=tformat)
def _expiration(timeout, tformat=None): # Wed, 06-Jun-2012 01:34:34 GMT if not tformat: tformat = "%a, %d-%b-%Y %T GMT" if timeout == "now": return time_util.instant(tformat) else: # validity time should match lifetime of assertions return time_util.in_a_while(minutes=timeout, format=tformat)
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 response_factory(sign=False, encrypt=False, **kwargs): response = samlp.Response(id=sid(), version=VERSION, issue_instant=instant()) if sign: response.signature = pre_signature_part(kwargs["id"]) if encrypt: pass for key, val in kwargs.items(): setattr(response, key, val) return response
def conditions(self, sp_entity_id): """ Return a saml.Condition instance :param sp_entity_id: The SP entity ID :return: A saml.Condition instance """ return factory( saml.Conditions, not_before=instant(), # How long might depend on who's getting it not_on_or_after=self.not_on_or_after(sp_entity_id), audience_restriction=[factory( saml.AudienceRestriction, audience=factory(saml.Audience, text=sp_entity_id))])
def _expiration(timeout, tformat="%a, %d-%b-%Y %H:%M:%S GMT"): """ :param timeout: :param tformat: :return: """ if timeout == "now": return instant(tformat) elif timeout == "dawn": return strftime(tformat, gmtime(0)) else: # validity time should match lifetime of assertions return in_a_while(minutes=timeout, format=tformat)
def _message(self, request_cls, destination=None, id=0, consent=None, extensions=None, sign=False, **kwargs): """ Some parameters appear in all requests so simplify by doing it in one place :param request_cls: The specific request type :param destination: The recipient :param id: A message identifier :param consent: Whether the principal have given her consent :param extensions: Possible extensions :param kwargs: Key word arguments specific to one request type :return: An instance of the request_cls """ if not id: id = sid(self.seed) req = request_cls(id=id, version=VERSION, issue_instant=instant(), issuer=self._issuer(), **kwargs) if destination: req.destination = destination if consent: req.consent = consent if extensions: req.extensions = extensions if sign: req.signature = pre_signature_part(req.id, self.sec.my_cert, 1) to_sign = [(class_name(req), req.id)] else: to_sign = [] logger.info("REQUEST: %s" % req) return signed_instance_factory(req, self.sec, to_sign)
def create_logout_response(self, request, binding, status=None, sign=False, issuer=None): """ Create a LogoutResponse. What is returned depends on which binding is used. :param request: The request this is a response to :param binding: Which binding the request came in over :param status: The return status of the response operation :param issuer: The issuer of the message :return: A logout message. """ mid = sid() if not status: status = success_status_factory() # response and packaging differs depending on binding response = "" if binding in [BINDING_SOAP, BINDING_HTTP_POST]: response = logoutresponse_factory(sign=sign, id = mid, in_response_to = request.id, status = status) elif binding == BINDING_HTTP_REDIRECT: sp_entity_id = request.issuer.text.strip() srvs = self.metadata.single_logout_service(sp_entity_id, "spsso") if not srvs: raise Exception("Nowhere to send the response") destination = destinations(srvs)[0] _issuer = self.issuer(issuer) response = logoutresponse_factory(sign=sign, id = mid, in_response_to = request.id, status = status, issuer = _issuer, destination = destination, sp_entity_id = sp_entity_id, instant=instant()) if sign: to_sign = [(class_name(response), mid)] response = signed_instance_factory(response, self.sec, to_sign) logger.info("Response: %s" % (response,)) return response
def authz_decision_query(self, entityid, action, evidence=None, resource=None, subject=None, binding=saml2.BINDING_HTTP_REDIRECT, sign=None): """ Creates an authz decision query. :param entityid: The entity ID of the IdP to send the request to :param action: The action you want to perform (has to be at least one) :param evidence: Why you should be able to perform the action :param resource: The resource you want to perform the action on :param subject: Who wants to do the thing :param binding: Which binding to use for sending the request :param sign: Whether the request should be signed or not. :return: AuthzDecisionQuery instance """ spentityid = self._issuer() service_url = self.service_url() my_name = self._my_name() logger.info("spentityid: %s\nservice_url: %s\nmy_name: %s" % (spentityid, service_url, my_name)) # authen_req = self.authn_request(session_id, location, # service_url, spentityid, my_name, vorg, # scoping, sign) request = samlp.AuthzDecisionQuery(action, evidence, resource, subject=subject, issuer=spentityid, id=sid(), issue_instant=instant(), version=VERSION, destination=entityid) return request
def make_logout_response(self, idp_entity_id, request_id, status_code, binding=BINDING_HTTP_REDIRECT): """ XXX There were issues with an explicit closing tag on StatusCode. Check wether we still need this. XXX Constructs a LogoutResponse :param idp_entity_id: The entityid of the IdP that want to do the logout :param request_id: The Id of the request we are replying to :param status_code: The status code of the response :param binding: The type of binding that will be used for the response :return: A LogoutResponse instance """ srvs = self.metadata.single_logout_service(idp_entity_id, binding, "idpsso") destination = destinations(srvs)[0] logger.info("destination to provider: %s" % destination) status = samlp.Status( status_code=samlp.StatusCode(value=status_code, text='\n'), status_message=samlp.StatusMessage(text='logout success')) response = samlp.LogoutResponse( id=sid(), version=VERSION, issue_instant=instant(), destination=destination, issuer=saml.Issuer(text=self.config.entityid, format=saml.NAMEID_FORMAT_ENTITY), in_response_to=request_id, status=status, ) return response, destination
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 make_logout_response(self, idp_entity_id, request_id, status_code, binding=BINDING_HTTP_REDIRECT): """ XXX There were issues with an explicit closing tag on StatusCode. Check wether we still need this. XXX Constructs a LogoutResponse :param idp_entity_id: The entityid of the IdP that want to do the logout :param request_id: The Id of the request we are replying to :param status_code: The status code of the response :param binding: The type of binding that will be used for the response :return: A LogoutResponse instance """ srvs = self.metadata.single_logout_service(idp_entity_id, binding, "idpsso") destination = destinations(srvs)[0] logger.info("destination to provider: %s" % destination) status = samlp.Status( status_code=samlp.StatusCode(value=status_code, text='\n'), status_message=samlp.StatusMessage(text='logout success') ) response = samlp.LogoutResponse( id=sid(), version=VERSION, issue_instant=instant(), destination=destination, issuer=saml.Issuer(text=self.config.entityid, format=saml.NAMEID_FORMAT_ENTITY), in_response_to=request_id, status=status, ) return response, destination
class SAML2PluginTests(unittest.TestCase): session_index = 's24d8e3c95e92e861f791016d32f92a8e588686101' attribute_xml = \ """<ns1:AttributeStatement xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion"><ns1:Attribute Name="SSOToken"><ns1:AttributeValue ns2:type="xs:string" """\ """xmlns:ns2="http://www.w3.org/2001/XMLSchema-instance">AQIC5wM2LY4SfcwB-hRxD21HHhBm_8RO3TkGHKhcWmmGaUc.*AAJTSQACMDE.*</ns1:AttributeValue></ns1:Attribute>"""\ """<ns1:Attribute Name="Salutation"><ns1:AttributeValue ns2:type="xs:string" xmlns:ns2="http://www.w3.org/2001/XMLSchema-instance">Herr</ns1:AttributeValue></ns1:Attribute>"""\ """<ns1:Attribute Name="Title"><ns1:AttributeValue ns2:type="xs:string" xmlns:ns2="http://www.w3.org/2001/XMLSchema-instance" /></ns1:Attribute>"""\ """<ns1:Attribute Name="FirstName"><ns1:AttributeValue ns2:type="xs:string" xmlns:ns2="http://www.w3.org/2001/XMLSchema-instance">Thomas</ns1:AttributeValue></ns1:Attribute>"""\ """<ns1:Attribute Name="LastName"><ns1:AttributeValue ns2:type="xs:string" xmlns:ns2="http://www.w3.org/2001/XMLSchema-instance">Schorr</ns1:AttributeValue></ns1:Attribute>"""\ """<ns1:Attribute Name="Email"><ns1:AttributeValue ns2:type="xs:string" xmlns:ns2="http://www.w3.org/2001/XMLSchema-instance">[email protected]</ns1:AttributeValue></ns1:Attribute></ns1:AttributeStatement>""" soap_artifact_response = \ """<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"><soap-env:Body>"""\ """<samlp:ArtifactResponse xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="s2f3c21d52024a3866e44c5f2e2e00e0f28561830a" """\ """InResponseTo="id-912c05fb95f9763132f259422bb26113" Version="2.0" IssueInstant="%s" Destination="https://nohost">"""\ """<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://nohost/auth</saml:Issuer><samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">"""\ """<samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Value="urn:oasis:names:tc:SAML:2.0:status:Success"></samlp:StatusCode></samlp:Status>"""\ """<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="s284dfd45f100f4a7b1ed1cb25a28ab42e63fc3d0a" InResponseTo="id-80c25be5605f68e2aa4e72660d736d7b" Version="2.0" """\ """IssueInstant="2014-04-16T12:04:42Z" Destination="https://nohost"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">"""\ """https://nohost/auth</saml:Issuer><samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" """\ """Value="urn:oasis:names:tc:SAML:2.0:status:Success"></samlp:StatusCode></samlp:Status>"""\ """<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="s208ceb5d27c072d35ca6b2c29211788cb80beea8e" IssueInstant="2014-04-16T12:04:42Z">"""\ """<saml:Issuer>https://nohost/auth</saml:Issuer><saml:Subject><saml:NameID NameQualifier="https://nohost/auth" """\ """Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">3TJes2TmJbwUrxplHOKeFcjty1l7</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">"""\ """<saml:SubjectConfirmationData NotOnOrAfter="2014-04-16T12:14:42Z" InResponseTo="id-80c25be5605f68e2aa4e72660d736d7b" Recipient="https://nohost" >"""\ """</saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2014-04-16T11:54:42Z" NotOnOrAfter="2014-04-16T12:14:42Z">"""\ """<saml:AudienceRestriction><saml:Audience>https://nohost/</saml:Audience></saml:AudienceRestriction></saml:Conditions>"""\ """<saml:AuthnStatement AuthnInstant="2014-04-15T14:52:34Z" SessionIndex="s2d7759b46741a35f5a93a4deb620ed1468e6dc901"><saml:AuthnContext><saml:AuthnContextClassRef>"""\ """urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement>"""\ """<saml:Attribute Name="SSOToken"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">"""\ """AQIC5wM2LY4Sfczx22Y4ngUTZ7fqv3OG9-3jNcSf2NNqpsE.*AAJTSQACMDIAAlMxAAIwMQ..*</saml:AttributeValue></saml:Attribute><saml:Attribute Name="AuthLevel">"""\ """<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">15</saml:AttributeValue></saml:Attribute>"""\ """<saml:Attribute Name="Salutation"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">"""\ """Herr</saml:AttributeValue></saml:Attribute><saml:Attribute Name="FirstName"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">"""\ """Thomas</saml:AttributeValue></saml:Attribute><saml:Attribute Name="LastName"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" """\ """xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Schorr</saml:AttributeValue></saml:Attribute><saml:Attribute Name="Email">"""\ """<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">[email protected]"""\ """</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response></samlp:ArtifactResponse></soap-env:Body></soap-env:Envelope>""" % instant() def setUp(self): self._stored_urlopen = urllib.urlopen self._stored_request = requests.request urllib.urlopen = lambda url: ResponseMock(200, url) requests.request = lambda method, url, **kwargs: ResponseMock( 200, url, method, **kwargs) def tearDown(self): urllib.urlopen = self._stored_urlopen requests.request = self._stored_request def _get_target_class(self): from hl.pas.samlplugin.plugin import SAML2Plugin return SAML2Plugin def _make_one(self): o = self._get_target_class()('saml2') o.saml2_user_properties = ('FirstName', 'LastName', 'Email') o.saml2_idp_configfile = os.path.join(path, 'data', 'idp.xml') o.saml2_sp_url = 'http://nohost/' o.saml2_sp_entityid = 'http://nohost/' o.saml2_xmlsec = '/usr/bin/xmlsec1' o.saml2_login_attribute = 'Email' return o def _make_request(self): environ = {} environ['SERVER_NAME'] = 'foo' environ['SERVER_PORT'] = '80' environ['REQUEST_METHOD'] = 'GET' resp = HTTPResponse(stdout=sys.stdout) req = HTTPRequest(stdin=file, environ=environ, response=resp) session = SessionMock() req.other['SESSION'] = session req['ACTUAL_URL'] = 'http://nohost/' return req def _parse_authn_request(self, enc_request): """ enc_request is an encrypted and base64 encoded request """ xmlstr = decode_base64_and_inflate(urllib.unquote(enc_request)) return authn_request_from_string(xmlstr) def _parse_logout_request(self, enc_request): xmlstr = decode_base64_and_inflate(urllib.unquote(enc_request)) return logout_request_from_string(xmlstr) def _parse_logout_response(self, enc_response): xmlstr = decode_base64_and_inflate(urllib.unquote(enc_response)) return logout_response_from_string(xmlstr) def _create_idp_logout_request(self): """ enc_resp is an encrypted and base64 encoded logout response """ logout_xml = '<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="s26bce413ad43ae7ff430a065122b7b16f31e17802" Version="2.0" IssueInstant="2012-05-08T12:46:11Z" Destination="http://nohost/logout" NotOnOrAfter="2012-05-08T12:56:11Z"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://nohost/auth</saml:Issuer><saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" NameQualifier="http://nohost/auth" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">1kFn6vXCTJ7Uo5v572Z1IsaLK8yQ</saml:NameID><samlp:SessionIndex xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">s26997d5ef9cbf708cc46b732624d90bba15cfb101</samlp:SessionIndex></samlp:LogoutRequest>' return deflate_and_base64_encode(logout_xml) def _create_idp_response( self, authn_request_id='2aaaeb7692471eb4ba00d5546877a7fd', cls=Response): issue_instant = datetime.utcnow().isoformat() + 'Z' not_before = (datetime.utcnow() - timedelta(minutes=5)).isoformat() + 'Z' not_on_or_after = (datetime.utcnow() + timedelta(minutes=5)).isoformat() + 'Z' issuer = Issuer(format=NAMEID_FORMAT_ENTITY, text='http://nohost/auth') signature = pre_signature_part( 's2998eb2e03b5006acb0a931d0fb558b0e4ec360c7') status = Status(status_code=StatusCode(value=STATUS_SUCCESS)) subject_confirmation_data = SubjectConfirmationData( not_on_or_after=not_on_or_after, in_response_to=authn_request_id, recipient='http://nohost/') subject_confirmation = SubjectConfirmation( method=SCM_BEARER, subject_confirmation_data=subject_confirmation_data) subject = Subject(name_id=NameID(text='AABVSVesMLYDiHtowyX4MDu6UopU', format=NAMEID_FORMAT_TRANSIENT), subject_confirmation=subject_confirmation) conditions = Conditions(not_before=not_before, not_on_or_after=not_on_or_after, audience_restriction=AudienceRestriction( Audience('http://nohost/')), one_time_use=OneTimeUse()) authn_context = AuthnContext(authn_context_decl_ref=AuthnContextClassRef( 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' )) authn_statement = AuthnStatement(authn_instant=issue_instant, authn_context=authn_context, session_index=self.session_index) attribute_statement = attribute_statement_from_string( self.attribute_xml) assertion = Assertion( id='s2bb879ef893d1b27fb90903e7c7e2779a3e7502c1', version='2.0', issue_instant=issue_instant, issuer=issuer, subject=subject, conditions=conditions, authn_statement=authn_statement, attribute_statement=attribute_statement, ) return cls(id='s2998eb2e03b5006acb0a931d0fb558b0e4ec360c7', in_response_to=authn_request_id, version='2.0', issue_instant=issue_instant, destination='http://nohost/', issuer=issuer, signature=signature, status=status, assertion=assertion) def sign_response(self, response): response = '%s' % response # Sign assertion in the response xmlsec = CryptoBackendXmlSec1( os.environ.get('SAML2_XMLSEC', '/usr/bin/xmlsec1')) seccont = SecurityContext(xmlsec, key_file=os.path.join( path, 'data', 'test.key')) signed_response = seccont.sign_statement( response, 'urn:oasis:names:tc:SAML:2.0:protocol:Response') return signed_response def test_authenticate(self): creds = {'ssiauth': True, 'login': '******'} plugin = self._make_one() expected = ('*****@*****.**', '*****@*****.**') got = plugin.authenticateCredentials(creds) self.failUnless(expected == got, 'expected %s, got %s' % (expected, got)) creds['ssiauth'] = False got = plugin.authenticateCredentials(creds) self.failUnless( got == None, 'authenticated in spite of invalid credentials, got %s' % got) def test_extract_credentials(self): plugin = self._make_one() req = self._make_request() resp = req.response plugin.extractCredentials(req) self.assertEquals(resp.status, 302, 'Redirect not set, status is: %s' % resp.status) get = resp.getHeader('location') urlvars = {} urlvars.update([tuple(get.split('?')[1].split('='))]) saml_request = urlvars.get('SAMLRequest', '') request = self._parse_authn_request(saml_request) self.assertEquals(request.destination, 'http://nohost/auth/SSORedirect/metaAlias/idp') expected = 'http://nohost/' self.assertEquals( request.assertion_consumer_service_url, expected, 'unexpected assertion consumer service url, expected %s, got %s.' % (expected, request.assertion_consumer_service_url)) def test_response_extraction(self): plugin = self._make_one() req = self._make_request() # Create a SAML2 response response = '%s' % self._create_idp_response( 'id-8201d3b76aa96ecc4317e55ec4f968ee') signed_response = self.sign_response(response) encoded_response = base64.b64encode(signed_response) req.form['SAMLResponse'] = encoded_response req.environ['REQUEST_METHOD'] = 'POST' req.stdin = StringIO( urllib.urlencode({'SAMLResponse': encoded_response})) session = req.SESSION session.set('_saml2_storedurl', 'http://nohost/stored_url') session.set('_saml2_sessid', {'2aaaeb7692471eb4ba00d5546877a7fd': ''}) creds = plugin.extractCredentials(req) self.assertEquals(creds['login'], '*****@*****.**') got = session.get('_saml2_session_index', '') self.assertEquals( got, self.session_index, 'Expected session index %s, got %s' % (self.session_index, got)) def test_passive_artifact_response(self): plugin = self._make_one() req = self._make_request() ResponseMock.text = self.soap_artifact_response req.form[ 'SAMLart'] = 'AAQAAJua9tAo9a1t0STYSpdn907OIx0lhLC5QgJKy9SOtEaeXyj7sON2MDE=' req.environ['REQUEST_METHOD'] = 'GET' session = req.SESSION session.set('_saml2_storedurl', 'http://nohost/stored_url') creds = plugin.passive(req) self.failUnless( type(creds) == dict, 'unexpected credentials: %s' % creds) self.failUnless(creds['login'] == '*****@*****.**', 'unexpected credentials: %s' % creds) self.failUnless(creds['ssiauth'], 'unexpected credentials: %s' % creds) self.failUnless(not req.form.has_key('SAMLart'), 'artifact should have been deleted from request form') def test_active(self): plugin = self._make_one() req = self._make_request() resp = req.response referer = 'http://nohost/referer' req.HTTP_REFERER = referer session = req.SESSION session.set('_saml2_ssi_auth', True) result = plugin.active(req) self.failUnless(result == True, 'challenge failed') got = session.get('_saml2_storedurl', '') self.failUnless( got == referer, 'expected stored url %s in session, got %s' % (referer, got)) # challenge should set the stored saml session id got = session.get('_saml2_sessid', '') self.failUnless(got != '', 'Expected saml session id to be set in local session') self.failUnless( session['_saml2_ssi_auth'] == False, 'challenge should reset the authentication flag in the session.') # the rest should be the same as credentials extraction self.assertEquals(resp.status, 302, 'Redirect not set, status is: %s' % resp.status) get = resp.getHeader('location') urlvars = {} urlvars.update([tuple(get.split('?')[1].split('='))]) saml_request = urlvars.get('SAMLRequest', '') request = self._parse_authn_request(saml_request) self.assertEquals(request.destination, 'http://nohost/auth/SSORedirect/metaAlias/idp') expected = 'http://nohost/' self.assertEquals( request.assertion_consumer_service_url, expected, 'unexpected assertion consumer service url, expected %s, got %s.' % (expected, request.assertion_consumer_service_url)) def test_challenge(self): request = self._make_request() response = request.response test_url = request['ACTUAL_URL'] helper = self._make_one() helper.challenge(request, response) self.assertEqual(response.status, 302) self.assertEqual(len(response.headers), 3) self.failUnless(response.headers['location'].endswith( urllib.quote(test_url))) self.assertEqual(response.headers['cache-control'], 'no-cache') self.assertEqual(response.headers['expires'], 'Sat, 01 Jan 2000 00:00:00 GMT') def test_reset_credentials(self): req = self._make_request() plugin = self._make_one() resp = req.RESPONSE session = req.SESSION session.set('_saml2_uid', 'testtest') session.set('_saml2_ssi_auth', True) session.set('_saml2_session_user_properties', {'foo': 'bar'}) req.URL1 = 'http://nohost/url1' plugin.resetCredentials(req, resp) self.failUnless(not session.get('_saml2_ssi_auth', True), 'not logged out') def test_slo(self): req = self._make_request() plugin = self._make_one() session = req.SESSION session.set('_saml2_uid', 'testtest') session.set('_saml2_ssi_auth', True) session.set('_saml2_session_user_properties', {'foo': 'bar'}) req.URL1 = 'http://nohost/url1' get = plugin.slo(req) urlvars = {} urlvars.update( tuple([kv.split('=') for kv in get.split('?')[1].split('&')])) saml_request = urlvars.get('SAMLRequest', '') request = self._parse_logout_request(saml_request) self.failUnless(request.issuer.text == 'http://nohost/', 'wrong issuer, got: %s' % request.issuer.text) self.failUnless( request.destination == 'http://nohost/auth/IDPSloRedirect/metaAlias/idp', 'wrong destination: %s' % request.destination) self.failUnless(request.name_id.text == 'testtest', 'wrong NameID: %s' % request.name_id.text) self.failUnless(not session.get('_saml2_ssi_auth', True), 'not logged out') def test_redirect_logout_request(self): req = self._make_request() plugin = self._make_one() session = req.SESSION resp = req.RESPONSE session.set('_saml2_ssi_auth', True) session.set('_saml2_session_index', 's26997d5ef9cbf708cc46b732624d90bba15cfb101') req.form['SAMLRequest'] = self._create_idp_logout_request() plugin.redirect_logout_request(req) self.assertEquals(resp.status, 302, 'Redirect not set, status is: %s' % resp.status) get = resp.getHeader('location') urlvars = {} urlvars.update([tuple(get.split('?')[1].split('='))]) saml_response = urlvars.get('SAMLResponse') response = self._parse_logout_response(saml_response) self.failUnless( response.status.status_code.value == 'urn:oasis:names:tc:SAML:2.0:status:Success', 'unexpected logout status: %s' % response.status.status_code.value) session.set('_saml2_session_index', 'invalidsessionidx') plugin.redirect_logout_request(req) self.assertEquals(resp.status, 302, 'Redirect not set, status is: %s' % resp.status) get = resp.getHeader('location') urlvars = {} urlvars.update([tuple(get.split('?')[1].split('='))]) saml_response = urlvars.get('SAMLResponse') response = self._parse_logout_response(saml_response) self.failUnless( response.status.status_code.value == 'urn:oasis:names:tc:SAML:2.0:status:RequestDenied', 'unexpected logout status: %s' % response.status.status_code.value) def test_checksession_passive_with_query(self): """ should be the same as extractCredentials """ plugin = self._make_one() req = self._make_request() req['ACTUAL_URL'] = req.SERVER_URL = 'http://nohost/somepath' qs = 'x=1&y:int=2' req.environ['QUERY_STRING'] = qs req.form.update({'x': '1', 'y': 2}) plugin.checksession(req) expected = 'http://nohost/somepath' session_storedurl_key = plugin.session_storedurl_key address, querystring = req.SESSION.get(session_storedurl_key).split( '?') self.assertEquals( address, expected, 'unexpected stored url in session, expected %s, got %s.' % (expected, address)) expected = dict([item.split('=') for item in qs.split('&')]) paramsOut = dict([item.split('=') for item in querystring.split('&')]) self.assertEquals( paramsOut, expected, 'unexpected querystring in stored url, expected: %s, got: %s' % (expected, paramsOut)) def test_checksession_passive(self): """ should be the same as extractCredentials """ plugin = self._make_one() req = self._make_request() resp = req.response plugin.checksession(req) self.assertEquals(resp.status, 302, 'Redirect not set, status is: %s' % resp.status) get = resp.getHeader('location') urlvars = {} urlvars.update([tuple(get.split('?')[1].split('='))]) saml_request = urlvars.get('SAMLRequest', '') request = self._parse_authn_request(saml_request) self.assertEquals(request.destination, 'http://nohost/auth/SSORedirect/metaAlias/idp') expected = 'http://nohost/' self.assertEquals( request.assertion_consumer_service_url, expected, 'unexpected assertion consumer service url, expected %s, got %s.' % (expected, request.assertion_consumer_service_url)) def test_authn_context(self): plugin = self._make_one() for method in (plugin.active, plugin.passive): for ac in plugin.possible_authn_context_types: req = self._make_request() resp = req.response plugin.saml2_authn_context_class = ac method(req) get = resp.getHeader('location') urlvars = {} urlvars.update([tuple(get.split('?')[1].split('='))]) saml_request = urlvars.get('SAMLRequest', '') request = self._parse_authn_request(saml_request) if ac == 'do not specify': self.failUnless(request.requested_authn_context is None, 'bogus request: %s' % request.to_string()) continue self.failUnless( len(request.requested_authn_context.authn_context_class_ref ) == 1, 'bogus request: %s' % request.requested_authn_context.to_string()) got = request.requested_authn_context.authn_context_class_ref[ 0].text self.failUnless( got == ac, 'unexpected authn context class - got %s, expected %s.' % (got, ac)) def test_interfaces(self): """ interface implementations """ plugin = self._make_one() self.assert_(verifyObject(ISAMLLogoutHandler, plugin)) self.assert_(verifyObject(ISAMLAttributeProvider, plugin)) self.assert_(verifyObject(ISAMLSessionCheck, plugin))
def authn_request( self, query_id, destination, service_url, spentityid, my_name="", vorg="", scoping=None, log=None, sign=None, binding=saml2.BINDING_HTTP_POST, nameid_format=saml.NAMEID_FORMAT_TRANSIENT, ): """ 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 """ request = samlp.AuthnRequest( id=query_id, version=VERSION, issue_instant=instant(), assertion_consumer_service_url=service_url, protocol_binding=binding, ) 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_default 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) if log is None: log = self.logger if log: log.info("REQUEST: %s" % request) return signed_instance_factory(request, self.sec, to_sign)
def logout_response(self, request, bindings, status=None, sign=False, issuer=None): """ Create a LogoutResponse. What is returned depends on which binding is used. :param request: The request this is a response to :param bindings: Which bindings that can be used to send the response :param status: The return status of the response operation :param issuer: The issuer of the message :return: A 3-tuple consisting of HTTP return code, HTTP headers and possibly a message. """ sp_entity_id = request.issuer.text.strip() binding = None destinations = [] for binding in bindings: destinations = self.conf.single_logout_services(sp_entity_id, binding) if destinations: break if not destinations: logger.error("Not way to return a response !!!") return ("412 Precondition Failed", [("Content-type", "text/html")], ["No return way defined"]) # Pick the first destination = destinations[0] logger.info("Logout Destination: %s, binding: %s" % (destination, binding)) if not status: status = success_status_factory() mid = sid() rcode = "200 OK" # response and packaging differs depending on binding if binding == BINDING_SOAP: response = logoutresponse_factory( sign=sign, id = mid, in_response_to = request.id, status = status, ) if sign: to_sign = [(class_name(response), mid)] response = signed_instance_factory(response, self.sec, to_sign) (headers, message) = http_soap_message(response) else: _issuer = self.issuer(issuer) response = logoutresponse_factory( sign=sign, id = mid, in_response_to = request.id, status = status, issuer = _issuer, destination = destination, sp_entity_id = sp_entity_id, instant=instant(), ) if sign: to_sign = [(class_name(response), mid)] response = signed_instance_factory(response, self.sec, to_sign) logger.info("Response: %s" % (response,)) if binding == BINDING_HTTP_REDIRECT: (headers, message) = http_redirect_message(response, destination, typ="SAMLResponse") rcode = "302 Found" else: (headers, message) = http_post_message(response, destination, typ="SAMLResponse") return rcode, headers, message
def _init_request(self, request, destination): # request.id = sid() request.version = VERSION request.issue_instant = instant() request.destination = destination return request
def _expiration(timeout, format=None): if timeout == "now": return time_util.instant(format) else: # validity time should match lifetime of assertions return time_util.in_a_while(minutes=timeout, format=format)
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)
def message_args(self, message_id=0): if not message_id: message_id = sid(self.seed) return {"id": message_id, "version": VERSION, "issue_instant": instant(), "issuer": self._issuer()}
"is_passive":None, "protocol_binding":None, "assertion_consumer_service_index":None, "assertion_consumer_service_url":None, "attribute_consuming_service_index":None, "provider_name":None, #saml.Issuer "issuer":{}, #ds.Signature "signature":{}, #Extensions "extensions":{}, "id":None, "version":None, "issue_instant":None, "destination":None, "consent":None, #text=None, #extension_elements=None, #extension_attributes=None, } request = samlp.AuthnRequest( id= query_id, version= VERSION, issue_instant= instant(), assertion_consumer_service_url= service_url, protocol_binding= binding )
def test_instant(): inst = str_to_time(instant()) now = time.gmtime() assert now >= inst
def _expiration(timeout, time_format=None): if timeout == "now": return time_util.instant(time_format) else: # validity time should match lifetime of assertions return time_util.in_a_while(minutes=timeout, format=time_format)
def logout_response(self, request, bindings, status=None, sign=False, issuer=None): """ Create a LogoutResponse. What is returned depends on which binding is used. :param request: The request this is a response to :param bindings: Which bindings that can be used to send the response :param status: The return status of the response operation :param issuer: The issuer of the message :return: A 3-tuple consisting of HTTP return code, HTTP headers and possibly a message. """ sp_entity_id = request.issuer.text.strip() binding = None destinations = [] for binding in bindings: destinations = self.conf.single_logout_services(sp_entity_id, binding) if destinations: break if not destinations: if self.log: self.log.error("Not way to return a response !!!") return ("412 Precondition Failed", [("Content-type", "text/html")], ["No return way defined"]) # Pick the first destination = destinations[0] if self.log: self.log.info("Logout Destination: %s, binding: %s" % (destination, binding)) if not status: status = success_status_factory() mid = sid() rcode = "200 OK" # response and packaging differs depending on binding if binding == BINDING_SOAP: response = logoutresponse_factory(sign=sign, id=mid, in_response_to=request.id, status=status) if sign: to_sign = [(class_name(response), mid)] response = signed_instance_factory(response, self.sec, to_sign) (headers, message) = http_soap_message(response) else: _issuer = self.issuer(issuer) response = logoutresponse_factory( sign=sign, id=mid, in_response_to=request.id, status=status, issuer=_issuer, destination=destination, sp_entity_id=sp_entity_id, instant=instant(), ) if sign: to_sign = [(class_name(response), mid)] response = signed_instance_factory(response, self.sec, to_sign) if self.log: self.log.info("Response: %s" % (response,)) if binding == BINDING_HTTP_REDIRECT: (headers, message) = http_redirect_message(response, destination, typ="SAMLResponse") rcode = "302 Found" else: (headers, message) = http_post_message(response, destination, typ="SAMLResponse") return rcode, headers, message