X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fipsilon.git;a=blobdiff_plain;f=ipsilon%2Fproviders%2Fsaml2idp.py;h=9bc75b39c8d0085339e2874c7988a1832eda51f0;hp=96a7d118b0d37ae20fbc40d30e1757af6227d30e;hb=5497278fab59361c5b6bc5d3c17407128b924b9a;hpb=38bda85cbff4ad9f53bc7ffcbc9e02a46bae79ec diff --git a/ipsilon/providers/saml2idp.py b/ipsilon/providers/saml2idp.py index 96a7d11..9bc75b3 100644 --- a/ipsilon/providers/saml2idp.py +++ b/ipsilon/providers/saml2idp.py @@ -33,6 +33,7 @@ from datetime import timedelta import lasso import os import time +import uuid class Redirect(AuthenticateRequest): @@ -194,6 +195,10 @@ Provides SAML 2.0 authentication infrastructure. """ 'idp key file', 'The IdP Certificate Key genearated at install time.', 'certificate.key'), + pconfig.String( + 'idp nameid salt', + 'The salt used for persistent Name IDs.', + None), pconfig.Condition( 'allow self registration', 'Allow authenticated users to register applications.', @@ -202,12 +207,13 @@ Provides SAML 2.0 authentication infrastructure. """ 'default allowed nameids', 'Default Allowed NameIDs for Service Providers.', metadata.SAML2_NAMEID_MAP.keys(), - ['persistent', 'transient', 'email', 'kerberos', 'x509']), + ['unspecified', 'persistent', 'transient', 'email', + 'kerberos', 'x509']), pconfig.Pick( 'default nameid', 'Default NameID used by Service Providers.', metadata.SAML2_NAMEID_MAP.keys(), - 'persistent'), + 'unspecified'), pconfig.String( 'default email domain', 'Used for users missing the email property.', @@ -252,6 +258,10 @@ Provides SAML 2.0 authentication infrastructure. """ return os.path.join(self.idp_storage_path, self.get_config_value('idp key file')) + @property + def idp_nameid_salt(self): + return self.get_config_value('idp nameid salt') + @property def default_allowed_nameids(self): return self.get_config_value('default allowed nameids') @@ -288,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: @@ -310,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): @@ -323,10 +374,10 @@ class IdpMetadataGenerator(object): '%s/saml2/SSO/Redirect' % url) self.meta.add_service(metadata.SAML2_SERVICE_MAP['logout-redirect'], '%s/saml2/SLO/Redirect' % url) - self.meta.add_allowed_name_format( - lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT) self.meta.add_allowed_name_format( lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT) + self.meta.add_allowed_name_format( + lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT) self.meta.add_allowed_name_format( lasso.SAML2_NAME_IDENTIFIER_FORMAT_EMAIL) @@ -379,7 +430,8 @@ class Installer(ProviderInstaller): config = {'idp storage path': path, 'idp metadata file': 'metadata.xml', 'idp certificate file': cert.cert, - 'idp key file': cert.key} + 'idp key file': cert.key, + 'idp nameid salt': uuid.uuid4().hex} po.save_plugin_config(config) # Update global config to add login plugin