#! /usr/bin/env python # -*- coding: UTF-8 -*- # PyLasso -- Python bindings for Lasso library # # Copyright (C) 2004 Entr'ouvert # http://lasso.entrouvert.org # # Authors: Nicolas Clapies # Valery Febvre # Emmanuel Raviart # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import unittest import sys sys.path.insert(0, '..') sys.path.insert(0, '../.libs') import lasso # FIXME: Replace principal with client in most methods. # FIXME: Rename webUser to userAccount. class HttpRequest(object): client = None # Principal or web site sending the request. body = None header = None method = None # "GET" or "POST" or "PUT" or... url = None def __init__(self, client, method, url, body = None): self.client = client self.method = method self.url = url if body: self.body = body def ask(self): webSite = self.client.internet.getWebSite(self.url) return webSite.doHttpRequest(self) class HttpResponse(object): body = None header = None statusCode = None # 200 or... statusMessage = None def __init__(self, statusCode, statusMessage = None, body = None): self.statusCode = statusCode if statusMessage: self.statusMessage = statusMessage if body: self.body = body class Internet(object): webSites = None def __init__(self): self.webSites = {} def addWebSite(self, webSite): self.webSites[webSite.url] = webSite def getWebSite(self, url): for webSiteUrl, webSite in self.webSites.iteritems(): if url.startswith(webSiteUrl): return webSite raise Exception("Unknown web site: %s" % url) class WebClient(object): internet = None keyring = None webSessionIds = None # Simulate the cookies, stored in user's navigator, and containing the # IDs of sessions already opened by the user. def __init__(self, internet): self.internet = internet self.keyring = {} self.webSessionIds = {} def redirect(self, url): webSite = self.internet.getWebSite(url) return webSite.doHttpRequest(HttpRequest(self, "GET", url)) class Principal(WebClient): """Simulation of a user and its web navigator""" name = None # The user name def __init__(self, internet, name): WebClient.__init__(self, internet) self.name = name class Simulation(object): test = None # The testing instance def __init__(self, test): self.test = test def fail(self, msg = None): return self.test.fail(msg) def failIf(self, expr, msg = None): return self.test.failIf(expr, msg) def failIfAlmostEqual(self, first, second, places = 7, msg = None): return self.test.failIfAlmostEqual(first, second, places, msg) def failIfEqual(self, first, second, msg = None): return self.test.failIfEqual(first, second, msg) def failUnless(self, expr, msg = None): return self.test.failUnless(expr, msg) def failUnlessAlmostEqual(self, first, second, places = 7, msg = None): return self.test.failUnlessAlmostEqual(first, second, places, msg) def failUnlessRaises(self, excClass, callableObj, *args, **kwargs): return self.test.failUnlessRaises(self, excClass, callableObj, *args, **kwargs) def failUnlessEqual(self, first, second, msg = None): return self.test.failUnlessEqual(first, second, msg) class WebSession(object): """Simulation of session of a web site""" expirationTime = None # A sample session variable loginDump = None # Used only by some identity providers uniqueId = None # The session number sessionDump = None webUserId = None # ID of logged user. def __init__(self, uniqueId): self.uniqueId = uniqueId class WebUser(object): """Simulation of user of a web site""" identityDump = None language = 'fr' # A sample user variable uniqueId = None # The user name is used as an ID in this simulation. def __init__(self, uniqueId): self.uniqueId = uniqueId class WebSite(WebClient, Simulation): """Simulation of a web site""" lastWebSessionId = 0 providerId = None # The Liberty providerID of this web site serverDump = None url = None # The main URL of web site webUserIdsByNameIdentifier = None webUsers = None webSessionIdsByNameIdentifier = None webSessions = None def __init__(self, test, internet, url): Simulation.__init__(self, test) WebClient.__init__(self, internet) self.url = url self.webUserIdsByNameIdentifier = {} self.webUsers = {} self.webSessionIdsByNameIdentifier = {} self.webSessions = {} self.internet.addWebSite(self) def addWebUser(self, name): self.webUsers[name] = WebUser(name) def createWebSession(self, client): self.lastWebSessionId += 1 webSession = WebSession(self.lastWebSessionId) self.webSessions[self.lastWebSessionId] = webSession client.webSessionIds[self.url] = self.lastWebSessionId return webSession def doHttpRequest(self, httpRequest): url = httpRequest.url if url.startswith(self.url): url = url[len(self.url):] methodName = url.split("?", 1)[0].replace("/", "") method = getattr(self, methodName) return method(httpRequest) def extractQueryFromUrl(self, url): return url.split("?", 1)[1] def getIdentityDump(self, principal): webSession = self.getWebSession(principal) webUser = self.getWebUserFromWebSession(webSession) if webUser is None: return None return webUser.identityDump def getServer(self): return lasso.Server.new_from_dump(self.serverDump) def getSessionDump(self, principal): webSession = self.getWebSession(principal) if webSession is None: return None return webSession.sessionDump def getWebSession(self, principal): webSessionId = principal.webSessionIds.get(self.url, None) if webSessionId is None: # The user has no web session opened on this site. return None return self.webSessions.get(webSessionId, None) def getWebSessionFromNameIdentifier(self, nameIdentifier): webSessionId = self.webSessionIdsByNameIdentifier.get(nameIdentifier, None) if webSessionId is None: # The user has no federation on this site or has no authentication assertion for this # federation. return None return self.webSessions.get(webSessionId, None) def getWebUserFromNameIdentifier(self, nameIdentifier): webUserId = self.webUserIdsByNameIdentifier.get(nameIdentifier, None) if webUserId is None: # The user has no federation on this site. return None return self.webUsers.get(webUserId, None) def getWebUserFromWebSession(self, webSession): if webSession is None: return None webUserId = webSession.webUserId if webUserId is None: # The user has no account on this site. return None return self.webUsers.get(webUserId, None) class IdpSite(WebSite): soapResponseMsgs = None def __init__(self, test, internet, url): WebSite.__init__(self, test, internet, url) self.soapResponseMsgs = {} def singleSignOn(self, httpRequest): server = self.getServer() login = lasso.Login.new(server) identityDump = self.getIdentityDump(httpRequest.client) if identityDump is not None: login.set_identity_from_dump(identityDump) sessionDump = self.getSessionDump(httpRequest.client) if sessionDump is not None: login.set_session_from_dump(sessionDump) authnRequestQuery = self.extractQueryFromUrl(httpRequest.url) login.init_from_authn_request_msg(authnRequestQuery, lasso.httpMethodRedirect) self.failUnless(login.must_authenticate()) # FIXME: To improve. webSession = self.getWebSession(httpRequest.client) if webSession is None: webSession = self.createWebSession(httpRequest.client) webSession.loginDump = login.dump() # A real identity provider using a HTML form to ask user's login & password would store # idpLoginDump in a session variable and display the HTML login form. webUserId = httpRequest.client.keyring.get(self.url, None) userAuthenticated = webUserId in self.webUsers if userAuthenticated: webSession.webUserId = webUserId authenticationMethod = lasso.samlAuthenticationMethodPassword # FIXME server = self.getServer() webSession = self.getWebSession(httpRequest.client) loginDump = webSession.loginDump del webSession.loginDump login = lasso.Login.new_from_dump(server, loginDump) # Set identity & session in login, because loginDump doesn't contain them. identityDump = self.getIdentityDump(httpRequest.client) if identityDump is not None: login.set_identity_from_dump(identityDump) sessionDump = self.getSessionDump(httpRequest.client) if sessionDump is not None: login.set_session_from_dump(sessionDump) self.failUnlessEqual(login.protocolProfile, lasso.loginProtocolProfileBrwsArt) # FIXME login.build_artifact_msg( userAuthenticated, authenticationMethod, "FIXME: reauthenticateOnOrAfter", lasso.httpMethodRedirect) webUser = self.getWebUserFromWebSession(webSession) if login.is_identity_dirty(): identityDump = login.get_identity().dump() self.failUnless(identityDump) webUser.identityDump = identityDump self.failUnless(login.is_session_dirty()) sessionDump = login.get_session().dump() self.failUnless(sessionDump) webSession.sessionDump = sessionDump nameIdentifier = login.nameIdentifier self.failUnless(nameIdentifier) self.webUserIdsByNameIdentifier[nameIdentifier] = webUser.uniqueId self.webSessionIdsByNameIdentifier[nameIdentifier] = webSession.uniqueId artifact = login.assertionArtifact self.failUnless(artifact) soapResponseMsg = login.response_dump self.failUnless(soapResponseMsg) self.soapResponseMsgs[artifact] = soapResponseMsg responseUrl = login.msg_url self.failUnless(responseUrl) return httpRequest.client.redirect(responseUrl) def soapEndpoint(self, httpRequest): soapRequestMsg = httpRequest.body requestType = lasso.get_request_type_from_soap_msg(soapRequestMsg) if requestType == lasso.requestTypeLogin: server = self.getServer() login = lasso.Login.new(server) login.process_request_msg(soapRequestMsg) artifact = login.assertionArtifact self.failUnless(artifact) soapResponseMsg = self.soapResponseMsgs.get(artifact, None) if soapResponseMsg is None: raise Exception("FIXME: Handle the case when artifact is wrong") return HttpResponse(200, body = soapResponseMsg) elif requestType == lasso.requestTypeLogout: server = self.getServer() logout = lasso.Logout.new(server, lasso.providerTypeIdp) logout.process_request_msg(soapRequestMsg, lasso.httpMethodSoap) nameIdentifier = logout.nameIdentifier self.failUnless(nameIdentifier) # Retrieve session dump and identity dump using name identifier. webSession = self.getWebSessionFromNameIdentifier(nameIdentifier) if webSession is None: raise Exception("FIXME: Handle the case when there is no web session") sessionDump = webSession.sessionDump if sessionDump is None: raise Exception( "FIXME: Handle the case when there is no session dump in web session") logout.set_session_from_dump(sessionDump) webUser = self.getWebUserFromNameIdentifier(nameIdentifier) if webUser is None: raise Exception("FIXME: Handle the case when there is no web user") identityDump = webUser.identityDump if identityDump is None: raise Exception( "FIXME: Handle the case when there is no identity dump in web user") logout.set_identity_from_dump(identityDump) logout.validate_request() self.failIf(logout.is_identity_dirty()) identity = logout.get_identity() self.failUnless(identity) identityDump = identity.dump() self.failUnless(identityDump) self.failUnless(logout.is_session_dirty()) session = logout.get_session() if session is None: del webSession.sessionDump else: sessionDump = session.dump() self.failUnless(sessionDump) webSession.sessionDump = sessionDump nameIdentifier = logout.nameIdentifier self.failUnless(nameIdentifier) del self.webSessionIdsByNameIdentifier[nameIdentifier] # Tell each other service provider to logout the user. otherProviderId = logout.get_next_providerID() while otherProviderId is not None: logout.init_request(otherProviderId) logout.build_request_msg() soapEndpoint = logout.msg_url self.failUnless(soapEndpoint) soapRequestMsg = logout.msg_body self.failUnless(soapRequestMsg) httpResponse = HttpRequest(self, "POST", soapEndpoint, body = soapRequestMsg).ask() self.failUnlessEqual(httpResponse.statusCode, 200) logout.process_response_msg(httpResponse.body, lasso.httpMethodSoap) otherProviderId = logout.get_next_providerID() logout.build_response_msg() soapResponseMsg = logout.msg_body self.failUnless(soapResponseMsg) return HttpResponse(200, body = soapResponseMsg) else: raise Exception("Unknown request type: %s" % requestType) class SpSite(WebSite): idpSite = None # The identity provider, this service provider will use to authenticate users. def assertionConsumer(self, httpRequest): server = self.getServer() login = lasso.Login.new(server) responseQuery = self.extractQueryFromUrl(httpRequest.url) login.init_request(responseQuery, lasso.httpMethodRedirect) login.build_request_msg() soapEndpoint = login.msg_url self.failUnless(soapEndpoint) soapRequestMsg = login.msg_body self.failUnless(soapRequestMsg) httpResponse = HttpRequest(self, "POST", soapEndpoint, body = soapRequestMsg).ask() self.failUnlessEqual(httpResponse.statusCode, 200) login.process_response_msg(httpResponse.body) nameIdentifier = login.nameIdentifier self.failUnless(nameIdentifier) # Retrieve session dump, using name identifier or else try to use the client web session. # If session dump exists, give it to Lasso, so that it updates it. webSession = self.getWebSessionFromNameIdentifier(nameIdentifier) if webSession is None: webSession = self.getWebSession(httpRequest.client) if webSession is not None: sessionDump = webSession.sessionDump if sessionDump is not None: login.set_session_from_dump(sessionDump) # Retrieve identity dump, using name identifier or else try to retrieve him from web # session. If identity dump exists, give it to Lasso, so that it updates it. webUser = self.getWebUserFromNameIdentifier(nameIdentifier) if webUser is None: webUser = self.getWebUserFromWebSession(webSession) if webUser is not None: identityDump = webUser.identityDump if identityDump is not None: login.set_identity_from_dump(sessionDump) login.accept_sso() if webUser is not None and identityDump is None: self.failUnless(login.is_identity_dirty()) identity = login.get_identity() self.failUnless(identity) identityDump = identity.dump() self.failUnless(identityDump) self.failUnless(login.is_session_dirty()) session = login.get_session() self.failUnless(session) sessionDump = session.dump() self.failUnless(sessionDump) nameIdentifier = login.nameIdentifier self.failUnless(nameIdentifier) # User is now authenticated. # If there was no web session yet, create it. Idem for the web user account. if webSession is None: webSession = self.createWebSession(httpRequest.client) if webUser is None: # A real service provider would ask user to login locally to create federation. Or it # would ask user informations to create a local account. webUserId = httpRequest.client.keyring.get(self.url, None) userAuthenticated = webUserId in self.webUsers if not userAuthenticated: return HttpResponse(401, "Access Unauthorized: User has no account.") webSession.webUserId = webUserId webUser = self.webUsers[webUserId] # Store the updated identity dump and session dump. if login.is_identity_dirty(): webUser.identityDump = identityDump webSession.sessionDump = sessionDump self.webUserIdsByNameIdentifier[nameIdentifier] = webUser.uniqueId self.webSessionIdsByNameIdentifier[nameIdentifier] = webSession.uniqueId return HttpResponse(200) def loginUsingRedirect(self, httpRequest): server = self.getServer() login = lasso.Login.new(server) login.init_authn_request(self.idpSite.providerId) self.failUnlessEqual(login.request_type, lasso.messageTypeAuthnRequest) login.request.set_isPassive(False) login.request.set_nameIDPolicy(lasso.libNameIDPolicyTypeFederated) login.request.set_consent(lasso.libConsentObtained) relayState = "fake" login.request.set_relayState(relayState) login.build_authn_request_msg() authnRequestUrl = login.msg_url self.failUnless(authnRequestUrl) return httpRequest.client.redirect(authnRequestUrl) def logoutUsingSoap(self, httpRequest): webSession = self.getWebSession(httpRequest.client) if webSession is None: return HttpResponse(401, "Access Unauthorized: User has no session opened.") webUser = self.getWebUserFromWebSession(webSession) if webUser is None: return HttpResponse(401, "Access Unauthorized: User is not logged in.") server = self.getServer() logout = lasso.Logout.new(server, lasso.providerTypeSp) identityDump = self.getIdentityDump(httpRequest.client) if identityDump is not None: logout.set_identity_from_dump(identityDump) sessionDump = self.getSessionDump(httpRequest.client) if sessionDump is not None: logout.set_session_from_dump(sessionDump) logout.init_request() logout.build_request_msg() soapEndpoint = logout.msg_url self.failUnless(soapEndpoint) soapRequestMsg = logout.msg_body self.failUnless(soapRequestMsg) httpResponse = HttpRequest(self, "POST", soapEndpoint, body = soapRequestMsg).ask() self.failUnlessEqual(httpResponse.statusCode, 200) logout.process_response_msg(httpResponse.body, lasso.httpMethodSoap) self.failIf(logout.is_identity_dirty()) identity = logout.get_identity() self.failUnless(identity) identityDump = identity.dump() self.failUnless(identityDump) self.failUnless(logout.is_session_dirty()) session = logout.get_session() if session is None: del webSession.sessionDump else: sessionDump = session.dump() self.failUnless(sessionDump) webSession.sessionDump = sessionDump nameIdentifier = logout.nameIdentifier self.failUnless(nameIdentifier) del self.webSessionIdsByNameIdentifier[nameIdentifier] return HttpResponse(200) class TestCase(unittest.TestCase): def generateIdpSite(self, internet): site = IdpSite(self, internet, "https://identity-provider/") site.providerId = "https://identity-provider/metadata" server = lasso.Server.new( "../../examples/data/idp-metadata.xml", "../../examples/data/idp-public-key.pem", "../../examples/data/idp-private-key.pem", "../../examples/data/idp-crt.pem", lasso.signatureMethodRsaSha1) server.add_provider( "../../examples/data/sp-metadata.xml", "../../examples/data/sp-public-key.pem", "../../examples/data/ca-crt.pem") site.serverDump = server.dump() self.failUnless(site.serverDump) server.destroy() site.addWebUser('Chantereau') site.addWebUser('Clapies') site.addWebUser('Febvre') site.addWebUser('Nowicki') return site def generateSpSite(self, internet): site = SpSite(self, internet, "https://service-provider/") site.providerId = "https://service-provider/metadata" server = lasso.Server.new( "../../examples/data/sp-metadata.xml", "../../examples/data/sp-public-key.pem", "../../examples/data/sp-private-key.pem", "../../examples/data/sp-crt.pem", lasso.signatureMethodRsaSha1) server.add_provider( "../../examples/data/idp-metadata.xml", "../../examples/data/idp-public-key.pem", "../../examples/data/ca-crt.pem") site.serverDump = server.dump() self.failUnless(site.serverDump) server.destroy() site.addWebUser('Nicolas') site.addWebUser('Romain') site.addWebUser('Valery') return site def setUp(self): pass def tearDown(self): pass class LoginTestCase(TestCase): def test01_generateServers(self): """Service provider initiated login using HTTP redirect""" internet = Internet() idpSite = self.generateIdpSite(internet) spSite = self.generateSpSite(internet) spSite.idpSite = idpSite principal = Principal(internet, "Romain Chantereau") principal.keyring[idpSite.url] = "Chantereau" principal.keyring[spSite.url] = "Romain" httpResponse = spSite.doHttpRequest(HttpRequest(principal, "GET", "/loginUsingRedirect")) self.failUnlessEqual(httpResponse.statusCode, 200) httpResponse = spSite.doHttpRequest(HttpRequest(principal, "GET", "/logoutUsingSoap")) self.failUnlessEqual(httpResponse.statusCode, 200) ## def test02_spLogin(self): ## """Service provider initiated login using HTTP redirect""" ## spLogin = self.spLoginForRedirect() ## # A real service provider would issue a HTTPS redirect to spLogin.msg_url. ## # Identity provider single sign-on, for a user having no federation. ## authnRequestQuery = spLogin.msg_url.split("?", 1)[1] ## idpLogin = self.idpSingleSignOnForRedirect(authnRequestQuery, None, None) ## self.failUnless(idpLogin.must_authenticate()) ## idpLoginDump = idpLogin.dump() ## # A real identity provider using a HTML form to ask user's login & password would store ## # idpLoginDump in a session variable and display the HTML login form. ## userAuthenticated = True ## authenticationMethod = lasso.samlAuthenticationMethodPassword ## idpServer = self.generateIdpServer() ## idpLogin = lasso.Login.new_from_dump(idpServer, idpLoginDump) ## #FIXME: set user and session from dump, because the logindump doesn't contain them. ## self.failUnlessEqual(idpLogin.protocolProfile, lasso.loginProtocolProfileBrwsArt) ## idpLogin = self.idpSingleSignOn_part2ForArtifactRedirect( ## idpLogin, userAuthenticated, authenticationMethod) ## # The user had no Liberty federation before, so identity must be dirty. ## self.failUnless(idpLogin.is_identity_dirty()) ## idpIdentityDump = idpLogin.get_identity().dump() ## idpSessionDump = idpLogin.get_session().dump() ## nameIdentifier = idpLogin.nameIdentifier ## artifact = idpLogin.assertionArtifact ## soapResponseMsg = idpLogin.response_dump ## # A real identity provider would store idpIdentityDump in user record and store ## # idpSessionDump in session variables or user record. ## # It would then index its user record and its session using nameIdentifier. ## # It would also store soapResponseMsg and index it using artifact. ## # It would optionally create a web session (using cookie, ...). ## # And finally, it would issue a HTTPS redirect to idpLogin.msg_url. ## # Service provider assertion consumer. ## responseQuery = idpLogin.msg_url.split("?", 1)[1] ## spLogin = self.spAssertionConsumerForRedirect(responseQuery) ## # A real service provider would issue a SOAP HTTPS request containing spLogin.msg_body to ## # spLogin.msg_url. ## # Identity provider SOAP endpoint. ## idpLogin = self.idpSoapEndpointForLogin(spLogin.msg_body) ## # A real identity provider would retrieve soapResponseMsg using spLogin.assertionArtifact ## # and return it as SOAP response. ## self.failUnlessEqual(idpLogin.assertionArtifact, artifact) ## # Service provider assertion consumer (part 2: process SOAP response). ## spLogin = self.spAssertionConsumer_part2(spLogin, soapResponseMsg) ## # A real service provider would search for a user record and a session indexed by ## # spLogin.nameIdentifier. ## # In this case, we assume that the user has no Liberty federation yet => no identity dump ## # and no session dump. ## self.failUnlessEqual(spLogin.nameIdentifier, nameIdentifier) ## spLogin = self.spAssertionConsumer_part3(spLogin, None, None) ## self.failUnless(spLogin.is_identity_dirty()) ## spIdentityDump = spLogin.get_identity().dump() ## spSession = spLogin.get_session() ## spSessionDump = spSession.dump() ## authenticationMethod = spSession.get_authentication_method() ## self.failUnlessEqual(authenticationMethod, lasso.samlAuthenticationMethodPassword) ## # A real service provider would store spIdentityDump in user record and spSessionDump ## # in session variables or user record. ## # It would then index its user record and its session using nameIdentifier. ## # It would create a web session (using cookie, ...). ## # And finally, it would display a page saying that Liberty authentication has succeeded. ## # Service provider logout using SOAP. ## spLogout = self.spLogoutForSoap(spIdentityDump, spSessionDump) ## # A real service provider would issue a SOAP HTTPS request containing spLogout.msg_body to ## # spLogout.msg_url. ## # Identity provider SOAP endpoint. ## idpLogout = self.idpSoapEndpointForLogout(spLogout.msg_body) ## self.failUnlessEqual(idpLogout.nameIdentifier, nameIdentifier) ## # A real identity provider would retrieve the user record and the session indexed by ## # idpLogout.nameIdentifier. ## idpLogout = self.idpSoapEndpointForLogout_part2(idpLogout, idpIdentityDump, idpSessionDump) ## # A real identity provider would store idpIdentityDump in user record and store or delete ## # idpSessionDump in session variables or user record. ## # It would then remove the nameIdentifier index to the user record and the session. ## # And finally, it would return idpLogout.msg_body as SOAP response. ## # Service provider logout (part 2: process SOAP response). ## spLogout = self.spLogoutForSoap_part2(spLogout, idpLogout.msg_body) ## self.failIf(spLogout.is_identity_dirty()) ## spIdentityDump = spLogout.get_identity().dump() ## spSession = spLogout.get_session() ## # In this case, spSession should be None, but Lasso doesn't implement it yet. ## # self.failIf(spSession) ## # ## # A real service provider would store spIdentityDump in user record and store or delete ## # spSessionDump in session variables or user record. ## # It would then remove the idpLogout.nameIdentifier index to the user record and the ## # session. ## # And finally, it would display a page saying that Liberty logout has succeeded. ## def test03(self): ## """Identity provider single sign-on when identity and session already exist.""" ## idpServer = self.generateIdpServer() ## idpLogin = lasso.Login.new(idpServer) ## idpIdentityDump = """\ ## NjMxMEMzRTlEMDA4NTNEMEZGNDI1MEM0QzY4NUNBNzY= ## """.strip() ## idpLogin.set_identity_from_dump(idpIdentityDump) ## idpSessionDump = """ ## NjMxMEMzRTlEMDA4NTNEMEZGNDI1MEM0QzY4NUNBNzY=NjMxMEMzRTlEMDA4NTNEMEZGNDI1MEM0QzY4NUNBNzY=urn:oasis:names:tc:SAML:1.0:cm:bearer ## ## ## ## ## ## ## ## ## ZRe7eb5JuhgL6W/Le1oMezbEHnA= ## ## ## CYOtlOvHtpkQsLA87GrtHs1WuoPVXHiPkVsmce2X1+PUslYpKLKp3cuNTVo1Z7+k ## Iku+DThYC9EvR7gprVQW2Y3CpCPanWs2A6j21SrlfqGFffpUtOFuiv3L1rfGKjPJ ## eMWehfc/SEi3+/JT22RejeYrSA61YLwsfItB7Ie4L0TRuZuxxu++CsidIEu2iv7l ## fI79SMn5hF7j/oFU9IODFhCArNLgBiOxA9rnRNvXwRFFmRN3qvdEuXuAZBthRhoa ## BRcL2T7tLxIVV+8y1fUjkliV1QgvOeus9g1bib1FLHdzHZ6KNGLPkZiXuM7ZPT1B ## G8WStJalTeH81AE7Ol4pcg== ## ## ## MIIDKTCCAhECAQEwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCSVQxDzANBgNV ## BAcTBlBvbXBlaTEQMA4GA1UEChMHVmVzdXZpbzEpMCcGA1UEAxMgVmVzdXZpbyBM ## aWJlcnR5IEFsbGlhbmNlIFJvb3QgQ0EwHhcNMDQwNDIwMTQwMzQ1WhcNMDUwNDIw ## MTQwMzQ1WjBaMQswCQYDVQQGEwJJVDEPMA0GA1UEBxMGUG9tcGVpMR4wHAYDVQQK ## ExVJZGVudGl0eSBQcm92aWRlciBJbmMxGjAYBgNVBAMTEWlkZW50aXR5LXByb3Zp ## ZGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4SGH3FPnhpQ8rCED ## RmC+NEkJQ6ZrG1jRL1kNx3wNu1xRZgFPiEDFnu9p/muVQkRAzK4txgC5i0ymwgRZ ## uan2yFrdq7Kpc9r0cM1S/q63aQeOMXQszz6G0NIY9DOzdrdlTc2uToBpIPA4a/Tf ## NWpMFZ7zGB9ThJ4+S5MAIA6y3SRWYHOqdlwjo/R0P4C3y8wIClgI0ZTdS6/Rkr59 ## XC4WRocMzGCSsk+1F1tAZoR77ummLcY4nFkbtawyeRXEUpSpDaxgVEEmvH+/Kqx5 ## NhVzeCZkm8szOzMea+QT4Uh3F7GVwY/7+JV23eCGyr2n3EhXgCqw0nnGSGR7vrNl ## Ue1oswIDAQABMA0GCSqGSIb3DQEBBAUAA4IBAQAFyYC/V49X7ZNLpYI8jx1TE9X3 ## J4c47cCLaxslrhi0/X6nCOEcBckXtbL+ZhIiHfI6PWizHMjTCEkJOYMVOsXyWN73 ## XdzfIZVrThQRsYvQZqUH8cZZH3fFg/RyEM3fzlFDsuIxfg7+NIDNmSFbt/YdFL0T ## 3sB7jYSkKr4buX9ZewdOfRxwN4MZIE32SoBo+UOgNrMM2hcQTStBK09vzJiWQE/4 ## aWbZJT9jtBPGWTsMS8g1x9WAmJHV2BpUiSfY39895a5T7kbbqZ3rp7DM9dgLjdXC ## jFL7NhzvY02aBTLhm22YOLYnlycKm64NGne+siooDCi5tel2/vcx+e+btX9x ## ## ## ## """.strip() ## # " <-- Trick for Emacs Python mode. ## idpLogin.set_session_from_dump(idpSessionDump) ## authnRequestQuery = """NameIDPolicy=federated&IsPassive=false&ProviderID=https%3A%2F%2Fservice-provider%3A2003%2Fliberty-alliance%2Fmetadata&consent=urn%3Aliberty%3Aconsent%3Aobtained&IssueInstance=2004-08-02T20%3A33%3A58Z&MinorVersion=2&MajorVersion=1&RequestID=ODVGNkUyMzY5N0MzOTY4QzZGOUYyNzEwRTJGMUNCQTI%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=fnSL5Mgp%2BV%2FtdUuYQJmFKvFY8eEco6sypmejvP4sD0v5ApywV94mUo6BxE29o1KW%0AGFXiMG7puhTwRSlKDo1vlh5iHNqVfjKcbx2XhfoDfplqLir102dyHxB5GedEQvqw%0AbTFtFrB6SnHi5facrYHCn7b58CxAWv9XW4DIfcVCOSma2OOBCm%2FzzCSiZpOtbRk9%0AveQzace41tDW0XLlbRdWpvwsma0yaYSkqYvTV3hmvgkWS5x9lzcm97oME4ywzwbU%0AJAyG8BkqMFoG7FPjwzR8qh7%2FWi%2BCzxxqfczxSGkUZUmsQdxyxazjhDpt1X8i5fan%0AnaF1vWF3GmS6G4t7mrkItA%3D%3D""" ## method = lasso.httpMethodRedirect ## idpLogin.init_from_authn_request_msg(authnRequestQuery, method) ## self.failIf(idpLogin.must_authenticate()) ## userAuthenticated = True ## authenticationMethod = lasso.samlAuthenticationMethodPassword ## self.failUnlessEqual(idpLogin.protocolProfile, lasso.loginProtocolProfileBrwsArt) ## idpLogin.build_artifact_msg( ## userAuthenticated, authenticationMethod, "FIXME: reauthenticateOnOrAfter", ## lasso.httpMethodRedirect) ## self.failUnless(idpLogin.msg_url) ## self.failUnless(idpLogin.assertionArtifact) ## self.failUnless(idpLogin.response_dump) ## self.failUnless(idpLogin.nameIdentifier) ## def test04(self): ## """Identity provider logout.""" ## idpServer = self.generateIdpServer() ## soapRequestMessage = """\ ## https://service-provider:2003/liberty-alliance/metadataQkM3M0M4MTYxREQzNEYwNEI4M0I4MUVERDUyQUUyMjA= ## ## ## ## ## ## ## ## ## NlVszQnxIyPU7zbJYadQmTnFAsI= ## ## ## h0lB2hBstgxlNYnVQ4xzmXIi2APqNxKEEfUqYm3NeGmddbazg0/Y/SdcqLlto9fy ## ML34w/TJG7DnCdeUQVxdxhzmJlv3X2U5qDAYh6gX4g36wJCntderC5LtNkZhhTWt ## m9NWGszFhCm9nSaGATdj4JGqJNc+LUIt3EvXHDIqQ/LU2g3hxZQ4Hs5Fg9yqRS98 ## 5CWPtckYcGPcG8kFuTKNos2F4KQPyXJRX0KF+9FbkBX0RsblstzL0CiFUlor4m+R ## ejvMcEt/nGCGj7F5mRPYcW3ZxTw4J2wAqS52Tu41fyeKw5SHIJQNmwV25P/hINim ## hd2ybn/G3vK2If0+rUjA8Q== ## ## ## MIIDJzCCAg8CAQIwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCSVQxDzANBgNV ## BAcTBlBvbXBlaTEQMA4GA1UEChMHVmVzdXZpbzEpMCcGA1UEAxMgVmVzdXZpbyBM ## aWJlcnR5IEFsbGlhbmNlIFJvb3QgQ0EwHhcNMDQwNDIwMTQyMDMxWhcNMDUwNDIw ## MTQyMDMxWjBYMQswCQYDVQQGEwJJVDEPMA0GA1UEBxMGUG9tcGVpMR0wGwYDVQQK ## ExRTZXJ2aWNlIFByb3ZpZGVyIEluYzEZMBcGA1UEAxMQc2VydmljZS1wcm92aWRl ## cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALIjOIroSVwUaMOyFlGL ## p6oCDkI14ssZRec/l2Z+p89kwVF+vkyhE7LHkaIgE1RnmPhcudzMCNFc6okpHdtV ## yU+GTSXhRN7/BGYBoDpfNpTMP0aUpw/BQOhL+zeb0nSsSf7ejNeKyvR+q5ia+3N4 ## dm9vgUPWZk0iN0URMSRxzIA3nEsR+B9JV7BFFyfbBxwLR4Aht667cuSeFnAUnynp ## JiHiKF/r5yXk+EKK++8NpjflpJnFVT1mSfj+6iYutiOrgUKgCANsaXr0WomR4oKg ## kqzP2DLDwnwi73vUAW4y9CBNk7nDtZJFhUxKa63i1HgHCKNvHfVjvKPz844PnLw/ ## CWMCAwEAATANBgkqhkiG9w0BAQQFAAOCAQEAOfAVexQY2ImgBWjcAkGAYfLwMZ2k ## 8jtQGRgbPuD1DBQ+oZm+Ykuw30orVAo8/S5PcSNdRawOVoTY60oRupGBctoqSzmp ## SiBkWOwb4wBZOHfSNRFDS83N0ewHk4FFY6t5NPlhUORC07xl4GaVUb5LjyDKMh2j ## RtLaR85lCV8xVvM+jdBzBM2FxOQ0WdhphMjO4gj5ene791iT4PpA69o7wuZ9g728 ## CGb/HRUx5EPgbIy52G224ITlQWadD1Z6y4PFTowDjkaRVerjUVRJZ/a5QVNsI4Du ## /z71zAbdg4NfTfXjAXHRhEGappHVBROAQFchQ0oKhCTkICN4TUSuodgy/A== ## ## ## ## """.strip() ## # " <-- Trick for Emacs Python mode. ## requestType = lasso.get_request_type_from_soap_msg(soapRequestMessage) ## self.failUnlessEqual(requestType, lasso.requestTypeLogout) ## idpLogout = lasso.Logout.new(idpServer, lasso.providerTypeIdp) ## idpLogout.process_request_msg(soapRequestMessage, lasso.httpMethodSoap) ## self.failUnless(idpLogout.nameIdentifier) ## idpIdentityDump = """\ ## QkM3M0M4MTYxREQzNEYwNEI4M0I4MUVERDUyQUUyMjA= ## """.strip() ## idpLogout.set_identity_from_dump(idpIdentityDump) ## self.failUnlessEqual(idpLogout.get_identity().dump(), idpIdentityDump) ## idpSessionDump = """ ## QkM3M0M4MTYxREQzNEYwNEI4M0I4MUVERDUyQUUyMjA=QkM3M0M4MTYxREQzNEYwNEI4M0I4MUVERDUyQUUyMjA=urn:oasis:names:tc:SAML:1.0:cm:bearer ## ## ## ## ## ## ## ## ## TqCKQTLsexix/tIqEabjBPcYby8= ## ## ## l96xDhc0/nevhvx79eyYvGknXDJMcykiomKOLMiL0FcxOglaKi/aNOGNA5VdT0mh ## EdlAynOOVy9xXphy9kLyXXSMcYV5UMeqCIi0ro5cvMP1xBfEqBHAHaYQR+TXbGdn ## bPCkIvGwzLDVr8bvwWnPjHqaXffswlfzjrDYq726Sx37s3UBgcViEVG0HTGe2X+f ## Kx2iahOjVLvR9bBWOdsiKNisK3GtZPGFmxIXALg8oZnwJA4JKodzh+o1synKoLn3 ## 2WigVh7r43LISSkCHx1C7qIK2zFz8YtPtaHa4xfMWT6QwZRngsXRcUcUibWZyoYt ## 950ly3lp1XkexL0uRXPvKw== ## ## ## MIIDKTCCAhECAQEwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCSVQxDzANBgNV ## BAcTBlBvbXBlaTEQMA4GA1UEChMHVmVzdXZpbzEpMCcGA1UEAxMgVmVzdXZpbyBM ## aWJlcnR5IEFsbGlhbmNlIFJvb3QgQ0EwHhcNMDQwNDIwMTQwMzQ1WhcNMDUwNDIw ## MTQwMzQ1WjBaMQswCQYDVQQGEwJJVDEPMA0GA1UEBxMGUG9tcGVpMR4wHAYDVQQK ## ExVJZGVudGl0eSBQcm92aWRlciBJbmMxGjAYBgNVBAMTEWlkZW50aXR5LXByb3Zp ## ZGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4SGH3FPnhpQ8rCED ## RmC+NEkJQ6ZrG1jRL1kNx3wNu1xRZgFPiEDFnu9p/muVQkRAzK4txgC5i0ymwgRZ ## uan2yFrdq7Kpc9r0cM1S/q63aQeOMXQszz6G0NIY9DOzdrdlTc2uToBpIPA4a/Tf ## NWpMFZ7zGB9ThJ4+S5MAIA6y3SRWYHOqdlwjo/R0P4C3y8wIClgI0ZTdS6/Rkr59 ## XC4WRocMzGCSsk+1F1tAZoR77ummLcY4nFkbtawyeRXEUpSpDaxgVEEmvH+/Kqx5 ## NhVzeCZkm8szOzMea+QT4Uh3F7GVwY/7+JV23eCGyr2n3EhXgCqw0nnGSGR7vrNl ## Ue1oswIDAQABMA0GCSqGSIb3DQEBBAUAA4IBAQAFyYC/V49X7ZNLpYI8jx1TE9X3 ## J4c47cCLaxslrhi0/X6nCOEcBckXtbL+ZhIiHfI6PWizHMjTCEkJOYMVOsXyWN73 ## XdzfIZVrThQRsYvQZqUH8cZZH3fFg/RyEM3fzlFDsuIxfg7+NIDNmSFbt/YdFL0T ## 3sB7jYSkKr4buX9ZewdOfRxwN4MZIE32SoBo+UOgNrMM2hcQTStBK09vzJiWQE/4 ## aWbZJT9jtBPGWTsMS8g1x9WAmJHV2BpUiSfY39895a5T7kbbqZ3rp7DM9dgLjdXC ## jFL7NhzvY02aBTLhm22YOLYnlycKm64NGne+siooDCi5tel2/vcx+e+btX9x ## ## ## ## """.strip() ## # " <-- Trick for Emacs Python mode. ## idpLogout.set_session_from_dump(idpSessionDump) ## self.failUnlessEqual(idpLogout.get_session().dump(), idpSessionDump) ## idpLogout.validate_request() ## self.failIf(idpLogout.is_identity_dirty()) ## self.failUnless(idpLogout.is_session_dirty()) ## idpSessionDump = idpLogout.get_session().dump() ## self.failUnless(idpSessionDump) ## self.failIf(idpLogout.get_next_providerID()) ## idpLogout.build_response_msg() ## soapResponseMsg = idpLogout.msg_body ## self.failUnless(soapResponseMsg) ## def test05(self): ## """Service provider logout.""" ## spServer = self.getServer() ## spLogout = lasso.Logout.new(spServer, lasso.providerTypeSp) ## spIdentityDump = """\ ## RTE5REZDN0UyMEJEQzA0MDQxRjM3NThCQkFCNERCODQ=RTE5REZDN0UyMEJEQzA0MDQxRjM3NThCQkFCNERCODQ= ## """.strip() ## spLogout.set_identity_from_dump(spIdentityDump) ## spSessionDump = """\ ## RTE5REZDN0UyMEJEQzA0MDQxRjM3NThCQkFCNERCODQ=RTE5REZDN0UyMEJEQzA0MDQxRjM3NThCQkFCNERCODQ=urn:oasis:names:tc:SAML:1.0:cm:bearer ## ## ## ## ## ## ## ## ## 8BSywvR2YB/euz8CCEhElQRSiZA= ## ## ## Vg0BM0Z15mFsRxEOhy9oCfXuK/NgQPrgJc2Kf3tE9g/uTnNFGq0YNB5KSlonJLUr ## 0cZ8D18XlTJrZp22vPCUO44hvL5DDWGTctqJbl+TV3D8qzFlfe8XOPBy3cUSXcYo ## E4qR44SnA9iZeRH0t4c3+8lY+BeXoqcglBrpE86B5Ftfb7wvLY0m8fdzPSJneSqq ## Z41uh4Wtegq4bqIkUev0nrY1wKHJjkfpKNmcirGTNm0gm8c/Ki9UCgI9g4cknj+F ## /UR8LQH/H8u2YSp3w5wiWfcmEfjfoVqa8YoiwWAoRgkKRVwER6iXYdqJ9vF0GFN/ ## Bm7OmEnDwF3bc/fruca4Pg== ## ## ## MIIDKTCCAhECAQEwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCSVQxDzANBgNV ## BAcTBlBvbXBlaTEQMA4GA1UEChMHVmVzdXZpbzEpMCcGA1UEAxMgVmVzdXZpbyBM ## aWJlcnR5IEFsbGlhbmNlIFJvb3QgQ0EwHhcNMDQwNDIwMTQwMzQ1WhcNMDUwNDIw ## MTQwMzQ1WjBaMQswCQYDVQQGEwJJVDEPMA0GA1UEBxMGUG9tcGVpMR4wHAYDVQQK ## ExVJZGVudGl0eSBQcm92aWRlciBJbmMxGjAYBgNVBAMTEWlkZW50aXR5LXByb3Zp ## ZGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4SGH3FPnhpQ8rCED ## RmC+NEkJQ6ZrG1jRL1kNx3wNu1xRZgFPiEDFnu9p/muVQkRAzK4txgC5i0ymwgRZ ## uan2yFrdq7Kpc9r0cM1S/q63aQeOMXQszz6G0NIY9DOzdrdlTc2uToBpIPA4a/Tf ## NWpMFZ7zGB9ThJ4+S5MAIA6y3SRWYHOqdlwjo/R0P4C3y8wIClgI0ZTdS6/Rkr59 ## XC4WRocMzGCSsk+1F1tAZoR77ummLcY4nFkbtawyeRXEUpSpDaxgVEEmvH+/Kqx5 ## NhVzeCZkm8szOzMea+QT4Uh3F7GVwY/7+JV23eCGyr2n3EhXgCqw0nnGSGR7vrNl ## Ue1oswIDAQABMA0GCSqGSIb3DQEBBAUAA4IBAQAFyYC/V49X7ZNLpYI8jx1TE9X3 ## J4c47cCLaxslrhi0/X6nCOEcBckXtbL+ZhIiHfI6PWizHMjTCEkJOYMVOsXyWN73 ## XdzfIZVrThQRsYvQZqUH8cZZH3fFg/RyEM3fzlFDsuIxfg7+NIDNmSFbt/YdFL0T ## 3sB7jYSkKr4buX9ZewdOfRxwN4MZIE32SoBo+UOgNrMM2hcQTStBK09vzJiWQE/4 ## aWbZJT9jtBPGWTsMS8g1x9WAmJHV2BpUiSfY39895a5T7kbbqZ3rp7DM9dgLjdXC ## jFL7NhzvY02aBTLhm22YOLYnlycKm64NGne+siooDCi5tel2/vcx+e+btX9x ## ## ## ## """.strip() ## # " <-- Trick for Emacs Python mode. ## spLogout.set_session_from_dump(spSessionDump) ## spLogout.init_request() ## spLogout.build_request_msg() ## self.failUnless(spLogout.msg_url) ## self.failUnless(spLogout.msg_body) ## self.failUnless(spLogout.nameIdentifier) ## soapResponseMessage = """\ ## https://identity-provider:1998/liberty-alliance/metadata ## """.strip() ## spLogout.process_response_msg(soapResponseMessage, lasso.httpMethodSoap) ## self.failIf(spLogout.is_identity_dirty()) ## self.failUnless(spLogout.is_session_dirty()) ## spSessionDump = spLogout.get_session().dump() ## # self.failIf(spSessionDump) ## def test06(self): ## """Service provider LECP login.""" ## # LECP has asked service provider for login. ## spServer = self.getServer() ## # FIXME: Why doesn't lasso.Lecp.new have spServer as argument? ## # spLecp = lasso.Lecp.new(spServer) ## spLecp = lasso.Lecp.new() ## spLecp.init_authn_request_envelope(sp, ) ## lasso_lecp_init_authn_request_envelope(sp_lecp, spserver, authnRequest); ## lasso_lecp_build_authn_request_envelope_msg(sp_lecp); ## msg = g_strdup(sp_lecp->msg_body); ## lasso_lecp_destroy(sp_lecp); suite1 = unittest.makeSuite(LoginTestCase, 'test') allTests = unittest.TestSuite((suite1,)) if __name__ == '__main__': sys.exit(not unittest.TextTestRunner(verbosity=2).run(allTests).wasSuccessful())