This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
expression/src/modules/libertyalliance.py

774 lines
35 KiB
Python

# -*- coding: UTF-8 -*-
# Expression
# By: Frederic Peters <fpeters@entrouvert.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
#
# Copyright (C) 2004 Entr'ouvert, Frederic Peters & 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.
"""Liberty Alliance Module"""
import httplib
import os
import urllib
import urlparse
import lasso
lasso.init()
import libxml2
import expression.core.directories as directories
import expression.core.documents as documents
import expression.core.elements as elements
import expression.core.environs as environs
import expression.core.faults as faults
import expression.core.filesystems as filesystems
import expression.core.html as html
import expression.core.http as http
import expression.core.locations as locations
import expression.core.logs as logs
import expression.core.modules as modules
import expression.core.namespaces as namespaces
import expression.core.sessions as sessions
import expression.core.stations as stations
import expression.core.strings as strings
import expression.core.things as things
import identities
import libertyallianceaccounts
import libertyallianceresponses
deleteSessionOnLogout = True
lassoServerContext = None
#symmetricKey = "Expression rules!" # FIXME
class EntityDescriptor(elements.Element):
def getAssertionConsumerServiceUrl(self, id):
if id:
nodes = self.evaluateXpath("md:SPDescriptor/md:AssertionConsumerServiceURL[@id = '%s']"
% id.replace("'", "&apos;"))
else:
nodes = None
if not nodes:
nodes = self.evaluateXpath(
"md:SPDescriptor/md:AssertionConsumerServiceURL[@isDefault = 'true']")
if not nodes:
return None
return nodes[0].content
def getProviderId(self):
nodes = self.evaluateXpath("@ProviderID")
if not nodes:
return None
return nodes[0].content
def getSingleSignOnProtocolProfiles(self):
nodes = self.evaluateXpath("md:IDPDescriptor/md:SingleSignOnProtocolProfile")
return [node.content for node in nodes]
def getSingleSignOnServiceUrl(self):
nodes = self.evaluateXpath("md:IDPDescriptor/md:SingleSignOnServiceURL")
if not nodes:
return None
return nodes[0].content
def getSoapEndpoint(self):
nodes = self.evaluateXpath("md:IDPDescriptor/md:SoapEndpoint")
if not nodes:
return None
return nodes[0].content
providerId = property(getProviderId)
singleSignOnProtocolProfiles = property(getSingleSignOnProtocolProfiles)
singleSignOnServiceUrl = property(getSingleSignOnServiceUrl)
soapEndpoint = property(getSoapEndpoint)
class LibertyAlliance(things.Thing):
_serverContextDump = None
def afterAuthentication(self, action = "afterAuthentication", authnResponse = None):
"""Liberty Alliance Identity Provider Method which is called once the user authentication
requested by singleSignOn has been attempted.
Handles HTTP GET.
"""
command = environs.getVar("httpCommand")
if command != "GET":
raise faults.PathNotFound("")
success = True
session = environs.getVar("session")
if session is None:
success = False
if success:
if authnResponse is None:
authnResponse = lasso.AuthnResponse.new_from_dump(
session.libertyAllianceAuthenticationResponse)
user = environs.getVar("user")
if user is None:
success = False
if success:
authenticationRequest = authnResponse.request
serviceProviderId = authenticationRequest.get_child(
"ProviderID").get_content()
serviceProviderMetadata = self.getServiceProviderMetadata(
serviceProviderId)
if serviceProviderMetadata is None:
success = False
authnResponse.process_authentication_result(success)
if success:
assertion = lasso.Assertion(
"issuer",
authnResponse.get_attr_value("InResponseTo"))
authenticationMethod = session.getAuthenticationMethod()
if authenticationMethod == "password":
lassoAuthenticationMethod = lasso.samlAuthenticationMethodPassword
else:
raise Exception("Unknown authentication method %s" % authenticationMethod)
identification = user.getIdentification(serviceProviderId)
# No service identification found, create it.
if identification is None:
if user.identifications is None:
user.node.newTextChild(None, "identifications", None)
identifications = user.identifications
identificationNode = identifications.node.newTextChild(
None, "identification", None)
identification = identifications.newElement(identificationNode)
identification.providerId = serviceProviderId
identification.localNameIdentifier \
= 'CDSICDSC7SD89CDSDCDCDCDISCDUIDSI344343'#lassoTools.generateNameIdentifier(serviceProviderId)
user.identifications.append(identificationNode)
user.getDocument().save()
# Process the NameIDPolicy.
# Remove the next lines.
nameIdentifierPolicy = "federated"
nameIdentifier = identification.peerNameIdentifier
if not nameIdentifier:
nameIdentifier = identification.localNameIdentifier
assert nameIdentifier
## nameIdentifierPolicy = authenticationRequest.getNameIDPolicy()
## nameIdentifier = None
## if nameIdentifierPolicy == "none":
## # No federation, just return the peer/local name identifier.
## nameIdentifier = identification.peerNameIdentifier
## if not nameIdentifier:
## nameIdentifier = identification.localNameIdentifier
## assert nameIdentifier
## elif nameIdentifierPolicy == "onetime":
## # One time federation.
## nameIdentifier = lassoTools.generateNameIdentifier(
## peerProviderId)
## raise "FIXME: Store new nameIdentifier in identification?"
## elif nameIdentifierPolicy == "federated":
## # Federation. Return peer/local/new name identifier
## nameIdentifier = identification.peerNameIdentifier
## if not nameIdentifier:
## nameIdentifier = identification.localNameIdentifier
## assert nameIdentifier
## elif nameIdentifierPolicy == "any":
## # Federated else none.
## consent = authenticationRequest.getConsent()
## if consent:
## nameIdentifier = identification.peerNameIdentifier
## if not nameIdentifier:
## nameIdentifier = identification.localNameIdentifier
## assert nameIdentifier
## else:
## raise "FIXME: No consent given by the principal"
# Get nameIdentifiers formats.
nameIdentifierFormat = "federated"
idpNameIdentifierFormat = "federated"
if nameIdentifierPolicy == "onetime":
nameIdentifierFormat = "onetime"
idpNameIdentifierFormat = "onetime"
authenticationStatement = lasso.AuthenticationStatement(
lassoAuthenticationMethod,
"2005-05-03T16:12:00Z", # reauthenticateOnOrAfter
nameIdentifier = nameIdentifier,
nameQualifier = serviceProviderId,
format = nameIdentifierFormat,
idp_nameIdentifier = identification.localNameIdentifier,
idp_nameQualifier = self.getMetadata().providerId,
idp_format = idpNameIdentifierFormat)
assertion.add_authenticationStatement(authenticationStatement)
assertion.set_signature(1, self.privateKeyFilePath, self.certificateFilePath)
authnResponse.add_assertion(assertion)
protocolProfileLassoNode = authenticationRequest.get_child(
"ProtocolProfile")
if protocolProfileLassoNode is None:
protocolProfile = "artifact"
else:
protocolProfile = protocolProfileLassoNode.get_content()
# FIXME: To remove.
if protocolProfile != lasso.libProtocolProfilePost:
logs.debug(
"Using POST protocol profile instead of %s." % protocolProfile)
protocolProfile = "post"
## if protocolProfile == lasso.libProtocolProfileArtifact:
## # Send an artifact, keep the assertion for later retrieval.
## raise "BOUM"
## assertionsProxy = getProxyForServerRole("assertions")
## artifact = assertionsProxy.addAssertion(assertion.exportToString())
## url = sso.getServiceProviderAssertionArtifactHandlerUrl(
## serviceProviderMetadata.assertionConsumerServiceUrl, # FIXME
## artifact,
## authenticationRequest.getRelayState())
## return redirect(url)
if protocolProfile == lasso.libProtocolProfilePost:
import base64
lares = authnResponse.export_to_base64()
# Remove this line and uncomment the next ones.
assertionConsumerServiceId = None
## assertionConsumerServiceIdLassoNode \
## = authenticationRequest.get_child("AssertionConsumerServiceID")
## if assertionConsumerServiceIdLassoNode is None:
## assertionConsumerServiceId = None
## else:
## assertionConsumerServiceId \
## = assertionConsumerServiceIdLassoNode.get_content()
actionUrl = serviceProviderMetadata.getAssertionConsumerServiceUrl(
assertionConsumerServiceId)
layout = html.html(
html.head(html.title(_("Authentication Succeeded"))),
html.body(
html.form(
html.input(
name = "LARES", type = "hidden", value = lares),
html.p(_("""\
You have been succesfully authenticated; click ok to go back to the service provider.\
""")),
html.div(
html.span(
html.input(
class_ = "button", name = "submit", type = "submit",
value = _("OK")),
class_ = "action-buttons-bar"),
class_ = "buttons-bar"),
action = actionUrl,
enctype = "multipart/form-data", method = "post")))
htmlDocument = documents.newTemporaryHtmlDocument()
htmlDocument.append(layout)
stylesheet = self.getDataHolder().getSiteXslt()
self.outputHttpHtmlDocument(htmlDocument, stylesheet)
else:
# Unknown protocol profile. We dont know what to do :
raise "FIXME: Unknow protocol profile"
def assertionConsumer(self):
"""Liberty Alliance service provider method which processes an authentication response
coming (indirectly) from identity provider.
Handles HTTP GET & POST.
"""
command = environs.getVar("httpCommand")
if command not in ("GET", "POST"):
raise faults.PathNotFound("")
serverContextDump = self.getServerContextDump()
serverContext = lasso.Server.new_from_dump(serverContextDump)
loginContext = lasso.Login.new(serverContext)
submission = environs.getVar("submission")
if command == "GET":
responseMsg = environs.getVar("httpQuery")
method = lasso.httpMethodRedirect
else: # command == "POST"
responseMsg = submission.getField("LAREQ")
method = lasso.httpMethodPost
relayState = submission.getField("RelayState", default = None)
errorCode = loginContext.init_request(responseMsg, method)
if errorCode:
raise Exception("Lasso login error %s" % errorCode)
errorCode = loginContext.build_request_msg()
if errorCode:
raise Exception("Lasso login error %s" % errorCode)
idpSoapEndpoint = loginContext.msg_url
soapRequestMsg = loginContext.msg_body
logs.debug("idpSoapEndpoint = %s; soapRequestMsg = %s" % (idpSoapEndpoint, soapRequestMsg))
idpParsedSoapEndpoint = urlparse.urlparse(idpSoapEndpoint)
idpAddressingScheme, idpHostName, idpPath = idpParsedSoapEndpoint[:3]
if idpAddressingScheme == "https":
privateKeyAbsolutePath = self.getConfigAbsolutePath("yep:sslCertificateKeyFile")
certificateAbsolutePath = self.getConfigAbsolutePath("yep:sslCertificateFile")
peerCaCertificateAbsolutePath = self.getConfigAbsolutePath(
"yep:sslCACertificateFile", None)
connection = http.HttpsConnection(
idpHostName, None, privateKeyAbsolutePath, certificateAbsolutePath,
peerCaCertificateAbsolutePath)
else:
connection = httplib.HTTPConnection(idpHostName)
connection.request("POST", idpPath, soapRequestMsg, {"Content-type": "text/xml"})
soapResponseFile = connection.getresponse()
soapResponseMsg = soapResponseFile.read()
logs.debug("soapResponseMsg = %s" % soapResponseMsg)
errorCode = loginContext.process_response_msg(soapResponseMsg)
if errorCode:
raise Exception("Lasso login error %s" % errorCode)
nameIdentifier = loginContext.nameIdentifier
# Retrieve account using name identifier.
accountsPath = self.getAccountsDirectoryAbsolutePath()
accountsHolder = directories.DirectoryHolder(
pathFragment = accountsPath, previous = environs.getVar("rootStation"),
isRootElder = True, containedFileSystem = filesystems.PartialFileSystem(accountsPath))
accountLocalId = accountsHolder.getItemLocalId(nameIdentifier)
if accountLocalId is None:
accountHolder = None
else:
accountHolder = accountsHolder.getItem(accountLocalId)
if accountHolder is None:
# There is no account indexed by this name identifier. Create it and its user.
# FIXME: Call account creation wizard and user creation or retrieval wizard.
# Create user.
usersPath = self.getConfigAbsolutePath("yep:usersPath")
usersHolder = directories.DirectoryHolder(
pathFragment = usersPath, previous = environs.getVar("rootStation"),
isRootElder = True,
containedFileSystem = filesystems.PartialFileSystem(usersPath))
userFeature = modules.getElementFeature(namespaces.yep.uri, "user")
userHolder = userFeature.newXmlHolder(usersHolder)
user = userHolder.getRootElement()
# FIXME: Initialize user attributes.
# userHolder.save() is done below.
# Create account.
accountFeature = modules.getElementFeature(
namespaces.yep.uri, "libertyAllianceAccount")
accountHolder = accountFeature.newXmlHolder(
accountsHolder, pathFragment = nameIdentifier + ".xml")
account = accountHolder.getRootElement()
account.setNameIdentifier(nameIdentifier)
account.setUserAbsolutePath(user.getAbsolutePath())
user.setLibertyAllianceAccountAbsolutePath(account.getAbsolutePath())
userContextDump = None
else:
account = accountHolder.getRootElement()
user = account.getUser()
userContextDump = account.getUserContextDump()
loginContext.create_user(userContextDump)
# Save the new or updated userContext into account.
account.setUserContextDump(loginContext.user.dump())
# Retrieve the authentication method and store it in account.
lassoAuthenticationMethod = loginContext.response.get_child(
"AuthenticationStatement").get_attr_value("AuthenticationMethod")
if lassoAuthenticationMethod == lasso.samlAuthenticationMethodPassword:
authenticationMethod = "password"
else:
logs.debug('Unknown authentication method = "%s"' % lassoAuthenticationMethod)
account.setAuthenticationMethod(authenticationMethod)
account.getDocument().save()
# User is now authenticated => create session, cookie...
session = sessions.getOrCreateSession()
session.publishToken = True
session.setAccountAbsolutePath(account.getAbsolutePath())
user.setSessionToken(session.getToken())
user.getDocument().save()
baseEnviron = environs.get(_level = "handleHttpCommand")
baseEnviron.setVar("user", user)
logs.debug('Setting session user = "%s" at "%s".' % (
user.getSimpleLabel(), session.getAbsolutePath()))
raise "On avance"
def getAccountsDirectoryAbsolutePath(self):
nodes = self.evaluateXpath("yep:accountsDirectory")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getCertificateFilePath(self):
nodes = self.evaluateXpath("yep:certificateFile")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getMetadata(self):
directoryHolder = self.getDataHolder().getUriPrevious()
try:
metadataHolder = directoryHolder.walkToLocation(
directoryHolder.getSubPathInternUri("metadata.xml"))
except faults.PathNotFound:
return None
return metadataHolder.getRootElement()
def getMetadataFilePath(self):
location = "metadata.xml"
return self.convertRelativeLocationToAbsolutePath(location)
def getPeerCertificationAuthorityCertificateFilePath(self):
nodes = self.evaluateXpath("yep:peerCACertificateFile")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getPeerMetadata(self):
# FIXME: Temporary element name: yep:peerMetadata
nodes = self.evaluateXpath("yep:peerMetadata/@src")
if not nodes:
return None
location = nodes[0].content.strip()
directoryHolder = self.getDataHolder().getUriPrevious()
try:
metadataHolder = directoryHolder.walkToLocation(
directoryHolder.getSubPathInternUri(location))
except faults.PathNotFound:
return None
return metadataHolder.getRootElement()
def getPeerMetadataFilePath(self):
nodes = self.evaluateXpath("yep:peerMetadata/@src")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getPeerPublicKeyFilePath(self):
nodes = self.evaluateXpath("yep:peerPublicKeyFile")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getPrivateKeyFilePath(self):
nodes = self.evaluateXpath("yep:privateKeyFile")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getPublicKeyFilePath(self):
nodes = self.evaluateXpath("yep:publicKeyFile")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getResponsesDirectoryAbsolutePath(self):
nodes = self.evaluateXpath("yep:responsesDirectory")
if nodes:
location = nodes[0].content.strip()
return self.convertRelativeLocationToAbsolutePath(location)
else:
return None
def getServerContextDump(self):
if self._serverContextDump is None:
serverContext = lasso.Server.new(
self.getMetadataFilePath(), self.getPublicKeyFilePath(),
self.getPrivateKeyFilePath(), self.getCertificateFilePath(),
lasso.signatureMethodRsaSha1)
serverContext.add_provider(
self.getPeerMetadataFilePath(), self.getPeerPublicKeyFilePath(),
self.getPeerCertificationAuthorityCertificateFilePath())
self._serverContextDump = serverContext.dump()
return self._serverContextDump
def getServiceProviderMetadata(self, providerId):
directoryHolder = self.getDataHolder().getUriPrevious()
try:
metadataHolder = directoryHolder.walkToLocation(directoryHolder.getSubPathInternUri(
"service-providers/%s" % strings.simplify(providerId)))
except faults.PathNotFound:
logs.debug("Service provider not found: %s" % providerId)
return None
return metadataHolder.getRootElement()
def login(self):
"""Liberty Alliance service provider method that builds an authentication requests and then
redirects to the identity provider login page.
Handles HTTP GET.
"""
command = environs.getVar("httpCommand")
if command != "GET":
raise faults.PathNotFound("")
serverContextDump = self.getServerContextDump()
serverContext = lasso.Server.new_from_dump(serverContextDump)
loginContext = lasso.Login.new(serverContext)
if loginContext.init_authn_request(self.getPeerMetadata().getProviderId()):
raise Exception('Login error')
# Identity provider will ask user to authenticate himself.
loginContext.request.set_isPassive(False)
# Identity provider will not ask user to authenticate himself if he has already done it
# recently.
# loginContext.request.set_forceAuthn(False)
loginContext.request.set_nameIDPolicy(lasso.libNameIDPolicyTypeFederated)
# loginContext.request.set_relayState("fake")
# loginContext.request.set_protocolProfile(lasso.libProtocolProfileBrwsArt)
if loginContext.build_authn_request_msg():
raise Exception('Login error')
return environs.getVar("httpRequestHandler").outputRedirect(loginContext.msg_url)
def soapEndpoint(self):
"""Liberty Alliance identity & service provider SOAP endpoint.
Handles HTTP POST.
"""
command = environs.getVar("httpCommand")
if command != "POST":
raise faults.PathNotFound("")
submission = environs.getVar("submission")
requestMsg = submission.readFile()
serverContextDump = self.getServerContextDump()
serverContext = lasso.Server.new_from_dump(serverContextDump)
loginContext = lasso.Login.new(serverContext)
errorCode = loginContext.process_request_msg(requestMsg)
if errorCode:
raise Exception("Lasso login error %s" % errorCode)
# Retrieve response with artifact. Reply to SOAP request using the response dump, then
# destroy response.
responsesPath = self.getResponsesDirectoryAbsolutePath()
responsesHolder = directories.DirectoryHolder(
pathFragment = responsesPath, previous = environs.getVar("rootStation"),
isRootElder = True, containedFileSystem = filesystems.PartialFileSystem(responsesPath))
responseLocalId = responsesHolder.getItemLocalId(loginContext.assertionArtifact)
if responseLocalId is None:
responseHolder = None
else:
responseHolder = responsesHolder.getItem(responseLocalId)
if responseHolder is None:
raise "FIXME: What should be done when artifact %s is unknown?" % loginContext.assertionArtifact
response = responseHolder.getRootElement()
responseDump = response.getResponseDump()
responseHolder.destroy()
# FIXME: I presume that responseDump should be encapsulated inside a SOAP enveloppe?
environs.getVar("httpRequestHandler").outputData(responseDump, mimeType = "text/xml")
def singleSignOn(self):
"""Liberty Alliance identity provider method that processes an authentication request
coming (indirectly) from a service provider.
Handles HTTP GET & POST.
"""
command = environs.getVar("httpCommand")
if command not in ("GET", "POST"):
raise faults.PathNotFound("")
serverContextDump = self.getServerContextDump()
serverContext = lasso.Server.new_from_dump(serverContextDump)
userContext = None
account = None
user = environs.getVar("user")
if user is not None:
account = user.getLibertyAllianceAccount()
if account is not None:
userContextDump = account.getUserContextDump()
if userContextDump is not None:
userContext = lasso.User.new_from_dump(userContextDump)
loginContext = lasso.Login.new(serverContext, userContext)
if command == "GET":
authnRequestMsg = environs.getVar("httpQuery")
method = lasso.httpMethodRedirect
else: # command == "POST"
submission = environs.getVar("submission")
authnRequestMsg = submission.getField("LAREQ")
method = lasso.httpMethodPost
if loginContext.init_from_authn_request_msg(authnRequestMsg, method):
raise Exception('Login error')
logs.debug("ProtocolProfile = %s" % loginContext.protocolProfile)
mustAuthenticate = loginContext.must_authenticate()
logs.debug("User must be authenticated = %s" % mustAuthenticate)
if mustAuthenticate:
if self.getConfigBoolean("yep:useHttpAuthentication", default = False):
# HTTP authentication.
if user is None:
return environs.getVar("httpRequestHandler").outputErrorUnauthorized(
self.getUriAbsolutePath())
else:
# The user is already authenticated using HTTP authentication.
userAuthenticated = True
authenticationMethod = "password"
else:
# FIXME: Authenticate the user and set the right authenticationMethod.
raise "TODO"
else:
userAuthenticated = True
authenticationMethod = "password" # FIXME
if authenticationMethod == "password":
lassoAuthenticationMethod = lasso.samlAuthenticationMethodPassword
else:
logs.debug('Unknown authentication method = "%s"' % authenticationMethod)
if loginContext.protocolProfile == lasso.loginProtocolProfileBrwsArt:
# We can send the artifact either using a redirect or a POST. It is an IDP choice,
# but redirect is better than POST (no need for a page with a form).
useRedirectForArtifact = True
if useRedirectForArtifact:
errorCode = loginContext.build_artifact_msg(
userAuthenticated, lassoAuthenticationMethod,
"FIXME: reauthenticateOnOrAfter", lasso.httpMethodRedirect)
if errorCode:
raise Exception("Lasso login error %s" % errorCode)
logs.debug("msg_url = %s; assertionArtifact = %s; response_dump = %s" % (
loginContext.msg_url, loginContext.assertionArtifact,
loginContext.response_dump))
nameIdentifier = loginContext.nameIdentifier
# Save user dump and name identifier.
if account is None:
accountsPath = self.getAccountsDirectoryAbsolutePath()
accountsHolder = directories.DirectoryHolder(
pathFragment = accountsPath, previous = environs.getVar("rootStation"),
isRootElder = True,
containedFileSystem = filesystems.PartialFileSystem(accountsPath))
accountLocalId = accountsHolder.getItemLocalId(nameIdentifier)
if accountLocalId is None:
accountHolder = None
else:
accountHolder = accountsHolder.getItem(accountLocalId)
if accountHolder is None:
# There is no account indexed by this name identifier. Create it and
# link it to the user.
accountFeature = modules.getElementFeature(
namespaces.yep.uri, "libertyAllianceAccount")
accountHolder = accountFeature.newXmlHolder(
accountsHolder, pathFragment = nameIdentifier + ".xml")
account = accountHolder.getRootElement()
account.setNameIdentifier(nameIdentifier)
else:
account = accountHolder.getRootElement()
logs.warning(
'Liberty Alliance account "%s" was not referenced by user %s'
% (account.getAbsolutePath(), user.getAbsolutePath()))
account.setUserAbsolutePath(user.getAbsolutePath())
user.setLibertyAllianceAccountAbsolutePath(account.getAbsolutePath())
user.getDocument().save()
# Save the new or updated userContext into account.
account.setUserContextDump(loginContext.user.dump())
account.setAuthenticationMethod(authenticationMethod)
account.getDocument().save()
# Save response dump, to retrieve it later, when receiving a request with the
# same artifact.
responsesPath = self.getResponsesDirectoryAbsolutePath()
responsesHolder = directories.DirectoryHolder(
pathFragment = responsesPath, previous = environs.getVar("rootStation"),
isRootElder = True,
containedFileSystem = filesystems.PartialFileSystem(responsesPath))
responseFeature = modules.getElementFeature(
namespaces.yep.uri, "libertyAllianceResponse")
responseHolder = responseFeature.newXmlHolder(
responsesHolder, pathFragment = loginContext.assertionArtifact + ".xml")
response = responseHolder.getRootElement()
response.setArtifact(loginContext.assertionArtifact)
response.setResponseDump(loginContext.response_dump)
response.getDocument().save()
return environs.getVar("httpRequestHandler").outputRedirect(
loginContext.msg_url)
else:
errorCode = loginContext.build_artifact_msg(
userAuthenticated, lassoAuthenticationMethod,
"FIXME: reauthenticateOnOrAfter", lasso.httpMethodPost)
if errorCode:
raise Exception("Lasso login error %s" % errorCode)
logs.debug("msg_url = %s; msg_body = %s; msg_relayState = %s; "
"assertionArtifact = %s; response_dump = %s" % (
loginContext.msg_url, loginContext.msg_body, loginContext.msg_relayState,
loginContext.assertionArtifact, loginContext.response_dump))
raise "FIXME"
else: # loginContext.protocolProfile == lasso.loginProtocolProfileBrwsPost:
errorCode = loginContext.build_authn_response_msg(
userAuthenticated, lassoAuthenticationMethod, "FIXME: reauthenticateOnOrAfter")
if errorCode:
raise Exception("Lasso login error %s" % errorCode)
logs.debug("msg_url = %s; msg_body = %s; msg_relayState = %s" % (
loginContext.msg_url, loginContext.msg_body, loginContext.msg_relayState))
raise "FIXME"
raise "TODO"
# FIXME: To remove.
if loginContext.protocolProfile == lasso.loginProtocolProfileBrwsArt:
if loginContext.build_artifact_msg(1, lasso.samlAuthenticationMethodPassword,
"",
lasso.httpMethodRedirect):
raise Exception('Login error')
logs.debug("msg_url = %s" % loginContext.msg_url)
protocolProfile = lasso.authn_request_get_protocolProfile(ssoQuery)
if protocolProfile == lasso.libProtocolProfilePost:
authnResponse = lasso.AuthnResponse.new_from_request_query(
ssoQuery, self.getMetadata().providerId)
if authnResponse is None:
raise faults.PathForbidden("")
if not authnResponse.verify_signature(
self.peerPublicKeyFilePath, # FIXME: Use a certificate instead & How to know which SP?
self.privateKeyFilePath # Should be removed. Used only to generate a fake signature.
): # Change this test to compare to 0.
# FIXME: Retourner le post d'erreur.
raise "BOUM"
user = environs.getVar("user")
if authnResponse.must_authenticate(
is_authenticated = user is not None):
# Save the authentication response. It will be used after
# authentication.
session = sessions.getOrCreateSession()
session.publishToken = True
session.libertyAllianceAuthenticationResponse \
= authnResponse.dump()
return self.walkToLocation(
"/accounts/passwords/login", "GET",
nextUrl = self.getActionUri("afterAuthentication"))
else:
return self.afterAuthentication("singleSignOn", authnResponse)
else:
# FIXME: Gérer l'artifact.
raise "BOUM"
elements.registerElement(
namespaces.md.uri, "EntityDescriptor", EntityDescriptor,
"http://www.entrouvert.org/expression/schemas/liberty-metadata-v1.0.xsd")
elements.registerElement(namespaces.yep.uri, "libertyAlliance", LibertyAlliance)