summaryrefslogtreecommitdiff
path: root/src/saml2/client.py
diff options
context:
space:
mode:
authorRoland Hedberg <roland.hedberg@adm.umu.se>2010-10-17 18:41:18 +0200
committerRoland Hedberg <roland.hedberg@adm.umu.se>2010-10-17 18:41:18 +0200
commitdbe1ab18e2bbfe74f5fc40ca24576eb1ce879f3b (patch)
treee550cf3eddb4d41938ecf7600d2c35998c5ac36a /src/saml2/client.py
parent0a6b7828a5cdad0e681f33a4df0265ba4322ff05 (diff)
downloadpysaml2-dbe1ab18e2bbfe74f5fc40ca24576eb1ce879f3b.tar.gz
Lots about logout
Diffstat (limited to 'src/saml2/client.py')
-rw-r--r--src/saml2/client.py91
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 """