diff options
| author | Roland Hedberg <roland.hedberg@adm.umu.se> | 2010-10-17 18:41:18 +0200 |
|---|---|---|
| committer | Roland Hedberg <roland.hedberg@adm.umu.se> | 2010-10-17 18:41:18 +0200 |
| commit | dbe1ab18e2bbfe74f5fc40ca24576eb1ce879f3b (patch) | |
| tree | e550cf3eddb4d41938ecf7600d2c35998c5ac36a /src/saml2/client.py | |
| parent | 0a6b7828a5cdad0e681f33a4df0265ba4322ff05 (diff) | |
| download | pysaml2-dbe1ab18e2bbfe74f5fc40ca24576eb1ce879f3b.tar.gz | |
Lots about logout
Diffstat (limited to 'src/saml2/client.py')
| -rw-r--r-- | src/saml2/client.py | 91 |
1 files changed, 62 insertions, 29 deletions
diff --git a/src/saml2/client.py b/src/saml2/client.py index f79644f1..290256ce 100644 --- a/src/saml2/client.py +++ b/src/saml2/client.py @@ -21,10 +21,13 @@ to conclude its tasks. import saml2 import time +import base64 from saml2.time_util import instant, not_on_or_after -from saml2.s_utils import sid, signature +from saml2.s_utils import signature +from saml2.s_utils import sid from saml2.s_utils import do_attributes, factory +from saml2.s_utils import decode_base64_and_inflate from saml2 import samlp, saml, class_name from saml2 import VERSION @@ -155,19 +158,7 @@ class Saml2Client(object): if isinstance(resp, AuthnResponse): self.users.add_information_about_person(resp.session_info()) elif isinstance(resp, LogoutResponse): - status = self.state[resp.in_response_to] - del self.state[resp.in_response_to] - if status["entity_ids"] == [resp.response.issuer]: # done - self.local_logout(status["subject_id"]) - return (0, ["200 Ok"]) - else: - status["entity_ids"].remove(resp.response.issuer) - return self._logout(status["subject_id"], - status["entity_ids"], - status["reason"], - status["not_on_or_after"], - status["sign"], - log, ) + self.handle_logout_response(resp) return resp @@ -254,7 +245,7 @@ class Saml2Client(object): def _my_name(self, name=None): if not name: - return self.config.sp_name() + return self.config.name() else: return name @@ -490,7 +481,7 @@ class Saml2Client(object): if not_on_or_after(expire) == False: # I've run out of time # Do the local logout anyway self.local_logout(subject_id) - return (0, ["504 Gateway Timeout"]) + return (0, "504 Gateway Timeout", [], []) # for all where I can use the SOAP binding, do those first not_done = entity_ids[:] @@ -533,7 +524,8 @@ class Saml2Client(object): not_done.remove(entity_id) log and log.info("OK response from %s" % destination) else: - log and log.info("NOT OK response from %s" % destination) + log and log.info( + "NOT OK response from %s" % destination) else: session_id = request.id @@ -553,53 +545,94 @@ class Saml2Client(object): (head, body) = http_post_message(request, destination, rstate) + code = "200 OK" else: (head, body) = http_redirect_message(request, destination, rstate) + code = "302 Found" - return (session_id, head, body) + return (session_id, code, head, body) if not_done != []: # upstream should try later raise LogoutError("%s" % (entity_ids,)) - return (0, [], response) + return (0, "", [], response) def local_logout(self, subject_id): # Remove the user from the cache, equals local logout self.users.remove_person(subject_id) return True - def logout_response(self, xmlstr, log=None): + def handle_logout_response(self, response): + """ handles a Logout response """ + self.log and self.log.info("state: %s" % (self.state,)) + status = self.state[response.in_response_to] + self.log and self.log.info("status: %s" % (status,)) + issuer = response.issuer() + self.log and self.log.info("issuer: %s" % issuer) + del self.state[response.in_response_to] + if status["entity_ids"] == [issuer]: # done + self.local_logout(status["subject_id"]) + return (0, "200 Ok", [("Content-type","text/html")], []) + else: + status["entity_ids"].remove(issuer) + return self._logout(status["subject_id"], + status["entity_ids"], + status["reason"], + status["not_on_or_after"], + status["sign"], + log, ) + + def logout_response(self, xmlstr, log=None, binding=BINDING_SOAP): """ Deal with a LogoutResponse :param xmlstr: The response as a xml string :param subject_id: the id of the user that initiated the logout + :param log: logging function + :param binding: What type of binding this message came through. :return: None if the reply doesn't contain a valid SAML LogoutResponse, - otherwise True if the logout was successful and False if it + otherwise the reponse if the logout was successful and None if it was not. """ - success = False + response = None if xmlstr: - response = LogoutResponse(self.sec, debug=True, log=log) - # arrived by SOAP+HTTP so no base64+zip done + try: + return_addr = self.config.endpoint("sp", + "single_logout_service", + binding=binding)[0] + except Exception: + log and log.info("Not supposed to handle this!") + return None + + response = LogoutResponse(self.sec, return_addr, debug=True, + log=log) + + if binding == BINDING_HTTP_REDIRECT: + xmlstr = decode_base64_and_inflate(xmlstr) + elif binding == BINDING_HTTP_POST: + xmlstr = base64.b64decode(xmlstr) + + if self.debug and log: + log.info("XMLSTR: %s" % xmlstr) + response = response.loads(xmlstr, False) + if response: response = response.verify() if not response: - return False + return None if self.debug and log: log.info(response) + + return self.handle_logout_response(response) - if response.response.status.status_code.value == samlp.STATUS_SUCCESS: - success = True - - return success + return response def add_vo_information_about_user(self, subject_id): """ Add information to the knowledge I have about the user """ |
