summaryrefslogtreecommitdiffstats
path: root/ipsilon/providers
diff options
context:
space:
mode:
Diffstat (limited to 'ipsilon/providers')
-rw-r--r--ipsilon/providers/saml2/sessions.py11
-rw-r--r--ipsilon/providers/saml2idp.py41
2 files changed, 50 insertions, 2 deletions
diff --git a/ipsilon/providers/saml2/sessions.py b/ipsilon/providers/saml2/sessions.py
index fb1f646..5931734 100644
--- a/ipsilon/providers/saml2/sessions.py
+++ b/ipsilon/providers/saml2/sessions.py
@@ -140,12 +140,16 @@ class SAMLSessionsContainer(Log):
self.sessions_logging_out[session.provider_id] = session
- def get_next_logout(self):
+ def get_next_logout(self, remove=True):
"""
Get the next session in the logged-in state and move
it to the logging_out state. Return the session that is
found.
+ :param remove: for IdP-initiated logout we can't remove the
+ session otherwise when the request comes back
+ in the user won't be seen as being logged-on.
+
Return None if no more sessions in login state.
"""
try:
@@ -153,7 +157,10 @@ class SAMLSessionsContainer(Log):
except IndexError:
return None
- session = self.sessions.pop(provider_id)
+ if remove:
+ session = self.sessions.pop(provider_id)
+ else:
+ session = self.sessions.itervalues().next()
if provider_id in self.sessions_logging_out:
self.sessions_logging_out.pop(provider_id)
diff --git a/ipsilon/providers/saml2idp.py b/ipsilon/providers/saml2idp.py
index 8ff512c..9bc75b3 100644
--- a/ipsilon/providers/saml2idp.py
+++ b/ipsilon/providers/saml2idp.py
@@ -298,6 +298,8 @@ Provides SAML 2.0 authentication infrastructure. """
self._debug('Failed to init SAML2 provider: %r' % e)
return None
+ self._root.logout.add_handler(self.name, self.idp_initiated_logout)
+
# Import all known applications
data = self.get_data()
for idval in data:
@@ -320,6 +322,45 @@ Provides SAML 2.0 authentication infrastructure. """
if self.admin:
self.admin.add_sps()
+ def idp_initiated_logout(self):
+ """
+ Logout all SP sessions when the logout comes from the IdP.
+
+ For the current user only.
+ """
+ self._debug("IdP-initiated SAML2 logout")
+ us = UserSession()
+
+ saml_sessions = us.get_provider_data('saml2')
+ if saml_sessions is None:
+ self._debug("No SAML2 sessions to logout")
+ return
+ session = saml_sessions.get_next_logout(remove=False)
+ if session is None:
+ return
+
+ # Add a fake session to indicate where the user should
+ # be redirected to when all SP's are logged out.
+ idpurl = self._root.instance_base_url()
+ saml_sessions.add_session("_idp_initiated_logout",
+ idpurl,
+ "")
+ init_session = saml_sessions.find_session_by_provider(idpurl)
+ init_session.set_logoutstate(idpurl, "idp_initiated_logout", None)
+ saml_sessions.start_logout(init_session)
+
+ logout = self.idp.get_logout_handler()
+ logout.setSessionFromDump(session.session.dump())
+ logout.initRequest(session.provider_id)
+ try:
+ logout.buildRequestMsg()
+ except lasso.Error, e:
+ self.error('failure to build logout request msg: %s' % e)
+ raise cherrypy.HTTPRedirect(400, 'Failed to log out user: %s '
+ % e)
+
+ raise cherrypy.HTTPRedirect(logout.msgUrl)
+
class IdpMetadataGenerator(object):