X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fipsilon.git;a=blobdiff_plain;f=ipsilon%2Fproviders%2Fsaml2%2Fauth.py;h=cc41bb8f3550ef5f4d35b28e04581a8512fc53f0;hp=d856220bc9f6a0baee80617f7bc644c1c103b9a7;hb=a8994fbcbe824b784c6ccefb1acc2cf8d268b90e;hpb=2751451f4158417e66974d6415d2da84f612ab3c diff --git a/ipsilon/providers/saml2/auth.py b/ipsilon/providers/saml2/auth.py index d856220..cc41bb8 100644 --- a/ipsilon/providers/saml2/auth.py +++ b/ipsilon/providers/saml2/auth.py @@ -25,8 +25,8 @@ class UnknownProvider(ProviderException): class AuthenticateRequest(ProviderPageBase): - def __init__(self, *args, **kwargs): - super(AuthenticateRequest, self).__init__(*args, **kwargs) + def __init__(self, site, provider, *args, **kwargs): + super(AuthenticateRequest, self).__init__(site, provider) self.stage = 'init' self.trans = None self.binding = None @@ -99,23 +99,65 @@ class AuthenticateRequest(ProviderPageBase): return login - def saml2login(self, request): + def _idp_initiated_login(self, spidentifier, relaystate): + """ + Perform an Idp-initiated login - if not request: + Exceptions are handled by the caller + """ + login = self.cfg.idp.get_login_handler() + + login.initIdpInitiatedAuthnRequest(spidentifier) + + # Hardcode for now, handle Artifact later + login.request.protocolBinding = lasso.SAML2_METADATA_BINDING_POST + + login.processAuthnRequestMsg() + + if relaystate is not None: + login.msgRelayState = relaystate + else: + provider = ServiceProvider(self.cfg, login.remoteProviderId) + if provider.splink is not None: + login.msgRelayState = provider.splink + else: + login.msgRelayState = login.remoteProviderId + + return login + + def saml2login(self, request, spidentifier=None, relaystate=None): + """ + request: the SAML request + spidentifier: the provider ID for IdP-initiated login + relaystate: optional string to direct user to particular place on + the SP after sending POST. If one is not provided then + the protected site from the SP is used, otherwise it + is set to the remote provider ID. + """ + if not request and not spidentifier: raise cherrypy.HTTPError(400, 'SAML request token missing or empty') - try: - login = self._parse_request(request) - except InvalidRequest, e: - self.debug(str(e)) - raise cherrypy.HTTPError(400, 'Invalid SAML request token') - except UnknownProvider, e: - self.debug(str(e)) - raise cherrypy.HTTPError(400, 'Unknown Service Provider') - except Exception, e: # pylint: disable=broad-except - self.debug(str(e)) - raise cherrypy.HTTPError(500) + if spidentifier: + try: + login = self._idp_initiated_login(spidentifier, relaystate) + except lasso.ServerProviderNotFoundError: + raise cherrypy.HTTPError(400, 'Unknown Service Provider') + except Exception, e: # pylint: disable=broad-except + self.debug(str(e)) + raise cherrypy.HTTPError(500) + else: + try: + login = self._parse_request(request) + except InvalidRequest, e: + self.debug(str(e)) + raise cherrypy.HTTPError(400, 'Invalid SAML request token') + except UnknownProvider, e: + self.debug(str(e)) + raise cherrypy.HTTPError(400, 'Unknown Service Provider') + except Exception, e: # pylint: disable=broad-except + self.debug(str(e)) + raise cherrypy.HTTPError(500) return login @@ -211,6 +253,8 @@ class AuthenticateRequest(ProviderPageBase): login.assertion.subject.nameId.content = nameid else: self.trans.wipe() + self.error('Authentication succeeded but it was not ' + + 'provided by NameID %s' % nameidfmt) raise AuthenticationError("Unavailable Name ID type", lasso.SAML2_STATUS_CODE_AUTHN_FAILED)