Liberty Alliance login now works (but may be a raise is not a clean way to
show that it works).
This commit is contained in:
parent
7db3f1fa4a
commit
a24143c55e
|
@ -25,6 +25,8 @@
|
||||||
"""Inscriptions Module"""
|
"""Inscriptions Module"""
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import libxml2
|
import libxml2
|
||||||
|
|
||||||
import dataholders
|
import dataholders
|
||||||
|
@ -367,7 +369,10 @@ class InscriptionHolder(dataholders.XmlHolder):
|
||||||
return None
|
return None
|
||||||
# We replace " " by "-" instead of "_" because this is better for Google
|
# We replace " " by "-" instead of "_" because this is better for Google
|
||||||
# indexing.
|
# indexing.
|
||||||
return strings.simplify(email)
|
publicName = strings.simplify(email)
|
||||||
|
if self.isRootElder:
|
||||||
|
publicName = os.path.join(self.getDirectoryAbsolutePath(), publicName)
|
||||||
|
return publicName
|
||||||
|
|
||||||
def setPublicName(self, publicName):
|
def setPublicName(self, publicName):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -808,7 +808,10 @@ class XmlHolder(DataHolder, documents.AbstractDocument):
|
||||||
else:
|
else:
|
||||||
doc = self.parseDataFile()
|
doc = self.parseDataFile()
|
||||||
self._node = doc
|
self._node = doc
|
||||||
self.publicName = self.localId
|
if self.isRootElder:
|
||||||
|
self.publicName = self.getAbsolutePath()
|
||||||
|
else:
|
||||||
|
self.publicName = self.localId
|
||||||
doc.xincludeProcess()
|
doc.xincludeProcess()
|
||||||
|
|
||||||
# Now that we know what is the root node, we can change the class of the holder.
|
# Now that we know what is the root node, we can change the class of the holder.
|
||||||
|
@ -901,7 +904,12 @@ class XmlHolder(DataHolder, documents.AbstractDocument):
|
||||||
fileSystem = self.fileSystem
|
fileSystem = self.fileSystem
|
||||||
fileSystemPath = self.getFileSystemPath()
|
fileSystemPath = self.getFileSystemPath()
|
||||||
if isRenamed:
|
if isRenamed:
|
||||||
fileSystem.rename(oldFileSystemPath, fileSystemPath)
|
try:
|
||||||
|
fileSystem.rename(oldFileSystemPath, fileSystemPath)
|
||||||
|
except OSError:
|
||||||
|
logs.debug('oldFileSystemPath = "%s", fileSystemPath = "%s"' % (
|
||||||
|
oldFileSystemPath, fileSystemPath))
|
||||||
|
raise
|
||||||
dataFile = fileSystem.open(fileSystemPath, "wb")
|
dataFile = fileSystem.open(fileSystemPath, "wb")
|
||||||
dataFile.write(data)
|
dataFile.write(data)
|
||||||
dataFile.close()
|
dataFile.close()
|
||||||
|
|
|
@ -318,7 +318,6 @@ class HttpRequestHandlerMixin:
|
||||||
message = """Access to "%s" Forbidden.""" % filePath
|
message = """Access to "%s" Forbidden.""" % filePath
|
||||||
if station == "current":
|
if station == "current":
|
||||||
station = environs.getVar("currentStation", default = None)
|
station = environs.getVar("currentStation", default = None)
|
||||||
self.setCookie()
|
|
||||||
logs.info(message)
|
logs.info(message)
|
||||||
data = "<html><body>%s</body></html>" % message
|
data = "<html><body>%s</body></html>" % message
|
||||||
if station:
|
if station:
|
||||||
|
@ -331,7 +330,7 @@ class HttpRequestHandlerMixin:
|
||||||
mimeType, styledData = station.generateXmlDocumentStyledData(xmlDocument, xslt)
|
mimeType, styledData = station.generateXmlDocumentStyledData(xmlDocument, xslt)
|
||||||
if mimeType == "text/html":
|
if mimeType == "text/html":
|
||||||
data = styledData
|
data = styledData
|
||||||
return self.send_error(403, message, data)
|
return self.send_error(403, message, data, setCookie = True)
|
||||||
|
|
||||||
def outputErrorBadRequest(self, reason, station = "current"):
|
def outputErrorBadRequest(self, reason, station = "current"):
|
||||||
if reason:
|
if reason:
|
||||||
|
@ -393,7 +392,6 @@ class HttpRequestHandlerMixin:
|
||||||
message = """Path "%s" Not Found.""" % filePath
|
message = """Path "%s" Not Found.""" % filePath
|
||||||
if station == "current":
|
if station == "current":
|
||||||
station = environs.getVar("currentStation", default = None)
|
station = environs.getVar("currentStation", default = None)
|
||||||
self.setCookie()
|
|
||||||
logs.info(message)
|
logs.info(message)
|
||||||
data = "<html><body>%s</body></html>" % message
|
data = "<html><body>%s</body></html>" % message
|
||||||
if station:
|
if station:
|
||||||
|
@ -406,7 +404,7 @@ class HttpRequestHandlerMixin:
|
||||||
mimeType, styledData = station.generateXmlDocumentStyledData(xmlDocument, xslt)
|
mimeType, styledData = station.generateXmlDocumentStyledData(xmlDocument, xslt)
|
||||||
if mimeType == "text/html":
|
if mimeType == "text/html":
|
||||||
data = styledData
|
data = styledData
|
||||||
return self.send_error(404, message, data)
|
return self.send_error(404, message, data, setCookie = True)
|
||||||
|
|
||||||
def outputErrorUnauthorized(self, filePath, station = "current"):
|
def outputErrorUnauthorized(self, filePath, station = "current"):
|
||||||
if filePath is None:
|
if filePath is None:
|
||||||
|
@ -415,7 +413,6 @@ class HttpRequestHandlerMixin:
|
||||||
message = """Access to "%s" Unauthorized.""" % filePath
|
message = """Access to "%s" Unauthorized.""" % filePath
|
||||||
if station == "current":
|
if station == "current":
|
||||||
station = environs.getVar("currentStation", default = None)
|
station = environs.getVar("currentStation", default = None)
|
||||||
self.setCookie()
|
|
||||||
logs.info(message)
|
logs.info(message)
|
||||||
data = "<html><body>%s</body></html>" % message
|
data = "<html><body>%s</body></html>" % message
|
||||||
headers = {}
|
headers = {}
|
||||||
|
@ -432,7 +429,7 @@ class HttpRequestHandlerMixin:
|
||||||
if station.getConfigBoolean("yep:useHttpAuthentication", default = False):
|
if station.getConfigBoolean("yep:useHttpAuthentication", default = False):
|
||||||
headers["WWW-Authenticate"] = 'Basic realm="%s"' % station.getConfigString(
|
headers["WWW-Authenticate"] = 'Basic realm="%s"' % station.getConfigString(
|
||||||
"yep:title", default = "Expression")
|
"yep:title", default = "Expression")
|
||||||
return self.send_error(401, message, data, headers)
|
return self.send_error(401, message, data, headers, setCookie = True)
|
||||||
|
|
||||||
def outputInformationContinue(self):
|
def outputInformationContinue(self):
|
||||||
message = "Continue"
|
message = "Continue"
|
||||||
|
@ -584,7 +581,7 @@ Client: %(clientIp)s
|
||||||
|
|
||||||
return self.outputErrorInternalServer()
|
return self.outputErrorInternalServer()
|
||||||
|
|
||||||
def send_error(self, code, message = None, data = None, headers = None):
|
def send_error(self, code, message = None, data = None, headers = None, setCookie = False):
|
||||||
# We need to save the session before sending response, otherwise, the
|
# We need to save the session before sending response, otherwise, the
|
||||||
# server may receive a new HTTP request before the session is saved.
|
# server may receive a new HTTP request before the session is saved.
|
||||||
session = environs.getVar("session", default = None)
|
session = environs.getVar("session", default = None)
|
||||||
|
@ -605,6 +602,8 @@ Client: %(clientIp)s
|
||||||
if headers is not None:
|
if headers is not None:
|
||||||
for name, value in headers.items():
|
for name, value in headers.items():
|
||||||
self.send_header(name, value)
|
self.send_header(name, value)
|
||||||
|
if setCookie:
|
||||||
|
self.setCookie()
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
if self.command != "HEAD":
|
if self.command != "HEAD":
|
||||||
self.wfile.write(data)
|
self.wfile.write(data)
|
||||||
|
|
|
@ -251,6 +251,7 @@ class Application(object):
|
||||||
if submission.hasField("login") and not authorization \
|
if submission.hasField("login") and not authorization \
|
||||||
and rootDataHolder.getConfigBoolean("yep:useHttpAuthentication",
|
and rootDataHolder.getConfigBoolean("yep:useHttpAuthentication",
|
||||||
default = False):
|
default = False):
|
||||||
|
# Ask for HTTP authentication.
|
||||||
return httpRequestHandler.outputErrorUnauthorized(httpPath)
|
return httpRequestHandler.outputErrorUnauthorized(httpPath)
|
||||||
if submission.hasField("logout") and authorization:
|
if submission.hasField("logout") and authorization:
|
||||||
# Since HTTP authentication provides no way to logout, we send a status
|
# Since HTTP authentication provides no way to logout, we send a status
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"""Sessions Module"""
|
"""Sessions Module"""
|
||||||
|
|
||||||
|
|
||||||
|
import errno
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
|
|
@ -358,7 +358,9 @@ class DbXmlDocumentStation(stations.AbstractStation, documents.AbstractDocument)
|
||||||
def getPublicName(self):
|
def getPublicName(self):
|
||||||
publicName = self.node.prop("publicName")
|
publicName = self.node.prop("publicName")
|
||||||
if publicName is None:
|
if publicName is None:
|
||||||
return ""
|
return None
|
||||||
|
if self.isRootElder:
|
||||||
|
publicName = os.path.join(self.getDirectoryAbsolutePath(), publicName)
|
||||||
return publicName
|
return publicName
|
||||||
|
|
||||||
def outputHttpSource(self):
|
def outputHttpSource(self):
|
||||||
|
|
|
@ -25,12 +25,18 @@
|
||||||
"""Identities Module"""
|
"""Identities Module"""
|
||||||
|
|
||||||
|
|
||||||
|
import errno
|
||||||
|
|
||||||
import libxml2
|
import libxml2
|
||||||
|
|
||||||
|
import expression.core.dataholders as dataholders
|
||||||
import expression.core.directories as directories
|
import expression.core.directories as directories
|
||||||
import expression.core.elements as elements
|
import expression.core.elements as elements
|
||||||
import expression.core.faults as faults
|
import expression.core.faults as faults
|
||||||
|
import expression.core.filesystems as filesystems
|
||||||
|
import expression.core.logs as logs
|
||||||
import expression.core.namespaces as namespaces
|
import expression.core.namespaces as namespaces
|
||||||
|
import expression.core.sessions as sessions
|
||||||
import expression.core.stations as stations
|
import expression.core.stations as stations
|
||||||
import expression.core.things as things
|
import expression.core.things as things
|
||||||
|
|
||||||
|
@ -38,8 +44,17 @@ from persons import Person
|
||||||
|
|
||||||
|
|
||||||
class Identity(things.Thing):
|
class Identity(things.Thing):
|
||||||
|
_libertyAllianceAccount = None
|
||||||
_session = None
|
_session = None
|
||||||
|
|
||||||
|
def deleteLibertyAllianceAccountPath(self):
|
||||||
|
nodes = self.evaluateXpath("yep:libertyAllianceAccount")
|
||||||
|
if nodes:
|
||||||
|
node = nodes[0]
|
||||||
|
node.unlinkNode()
|
||||||
|
node.freeNode()
|
||||||
|
self.getDataHolder().isDirty = True
|
||||||
|
|
||||||
def deleteSessionToken(self):
|
def deleteSessionToken(self):
|
||||||
nodes = self.evaluateXpath("yep:sessionToken")
|
nodes = self.evaluateXpath("yep:sessionToken")
|
||||||
if nodes:
|
if nodes:
|
||||||
|
@ -64,6 +79,44 @@ class Identity(things.Thing):
|
||||||
person = personHolder.getRootElement()
|
person = personHolder.getRootElement()
|
||||||
return person.getLanguage()
|
return person.getLanguage()
|
||||||
|
|
||||||
|
def getLibertyAllianceAccount(self):
|
||||||
|
if self._libertyAllianceAccount is None:
|
||||||
|
libertyAllianceAccountAbsolutePath = self.getLibertyAllianceAccountAbsolutePath()
|
||||||
|
if libertyAllianceAccountAbsolutePath:
|
||||||
|
try:
|
||||||
|
libertyAllianceAccountHolder = dataholders.DataHolder(
|
||||||
|
pathFragment = libertyAllianceAccountAbsolutePath, mimeType = "text/xml",
|
||||||
|
isRootElder = True,
|
||||||
|
containedFileSystem = filesystems.PartialFileSystem(
|
||||||
|
libertyAllianceAccountAbsolutePath))
|
||||||
|
except IOError, error:
|
||||||
|
if error.errno == errno.ENOENT:
|
||||||
|
logs.debug("""LibertyAllianceAccount at path "%s" doesn't exist."""
|
||||||
|
% libertyAllianceAccountAbsolutePath)
|
||||||
|
self._libertyAllianceAccount = "none"
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._libertyAllianceAccount = libertyAllianceAccountHolder.getRootElement()
|
||||||
|
else:
|
||||||
|
libertyAllianceAccountNodes = self.evaluateXpath("yep:libertyAllianceAccount")
|
||||||
|
if libertyAllianceAccountNodes:
|
||||||
|
self._libertyAllianceAccount = elements.newElement(
|
||||||
|
libertyAllianceAccountNodes[0], previous = self, owner = self)
|
||||||
|
else:
|
||||||
|
self._libertyAllianceAccount = "none"
|
||||||
|
if self._libertyAllianceAccount == "none":
|
||||||
|
return None
|
||||||
|
return self._libertyAllianceAccount
|
||||||
|
|
||||||
|
def getLibertyAllianceAccountAbsolutePath(self):
|
||||||
|
nodes = self.evaluateXpath("yep:libertyAllianceAccount/@src")
|
||||||
|
if nodes:
|
||||||
|
libertyAllianceAccountPath = nodes[0].content
|
||||||
|
return self.convertPathToAbsolute(libertyAllianceAccountPath)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def getPerson(self):
|
def getPerson(self):
|
||||||
if self.getPersonLocation():
|
if self.getPersonLocation():
|
||||||
personHolder = self.walkToLocation(self.getPersonLocation())
|
personHolder = self.walkToLocation(self.getPersonLocation())
|
||||||
|
@ -88,7 +141,7 @@ class Identity(things.Thing):
|
||||||
if sessionToken is None:
|
if sessionToken is None:
|
||||||
self._session = "none"
|
self._session = "none"
|
||||||
else:
|
else:
|
||||||
self._session = sessions.retrieveSession(getSessionToken)
|
self._session = sessions.retrieveSession(sessionToken)
|
||||||
if self._session == "none":
|
if self._session == "none":
|
||||||
return None
|
return None
|
||||||
return self._session
|
return self._session
|
||||||
|
@ -106,6 +159,12 @@ class Identity(things.Thing):
|
||||||
else:
|
else:
|
||||||
return person.getSimpleLabel()
|
return person.getSimpleLabel()
|
||||||
|
|
||||||
|
def getUser(self):
|
||||||
|
# Some times, users are stored in independant files; some times they are embedded inside
|
||||||
|
# accounts.
|
||||||
|
# => This method is needed to ease user retrieval.
|
||||||
|
return self
|
||||||
|
|
||||||
def getVoteToken(self, ballotBoxLocalId):
|
def getVoteToken(self, ballotBoxLocalId):
|
||||||
votesNodes = self.evaluateXpath("yep:votes")
|
votesNodes = self.evaluateXpath("yep:votes")
|
||||||
if not votesNodes:
|
if not votesNodes:
|
||||||
|
@ -120,6 +179,12 @@ class Identity(things.Thing):
|
||||||
return None
|
return None
|
||||||
return tokenNodes[0].content
|
return tokenNodes[0].content
|
||||||
|
|
||||||
|
def setLibertyAllianceAccountAbsolutePath(self, libertyAllianceAccountAbsolutePath):
|
||||||
|
libertyAllianceAccountBaseRelativePath = self.convertAbsolutePathToBaseRelative(
|
||||||
|
libertyAllianceAccountAbsolutePath)
|
||||||
|
self.setElementAttribute(
|
||||||
|
"yep:libertyAllianceAccount", "src", libertyAllianceAccountBaseRelativePath)
|
||||||
|
|
||||||
def setPersonLocation(self, personLocation):
|
def setPersonLocation(self, personLocation):
|
||||||
self.setElementAttribute("yep:person", "src", personLocation)
|
self.setElementAttribute("yep:person", "src", personLocation)
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ class LibertyAlliance(things.Thing):
|
||||||
|
|
||||||
authenticationMethod = session.getAuthenticationMethod()
|
authenticationMethod = session.getAuthenticationMethod()
|
||||||
if authenticationMethod == "password":
|
if authenticationMethod == "password":
|
||||||
authenticationMethod = lasso.samlAuthenticationMethodPassword
|
lassoAuthenticationMethod = lasso.samlAuthenticationMethodPassword
|
||||||
else:
|
else:
|
||||||
raise Exception("Unknown authentication method %s" % authenticationMethod)
|
raise Exception("Unknown authentication method %s" % authenticationMethod)
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ class LibertyAlliance(things.Thing):
|
||||||
idpNameIdentifierFormat = "onetime"
|
idpNameIdentifierFormat = "onetime"
|
||||||
|
|
||||||
authenticationStatement = lasso.AuthenticationStatement(
|
authenticationStatement = lasso.AuthenticationStatement(
|
||||||
authenticationMethod,
|
lassoAuthenticationMethod,
|
||||||
"2005-05-03T16:12:00Z", # reauthenticateOnOrAfter
|
"2005-05-03T16:12:00Z", # reauthenticateOnOrAfter
|
||||||
nameIdentifier = nameIdentifier,
|
nameIdentifier = nameIdentifier,
|
||||||
nameQualifier = serviceProviderId,
|
nameQualifier = serviceProviderId,
|
||||||
|
@ -369,20 +369,22 @@ You have been succesfully authenticated; click ok to go back to the service prov
|
||||||
account = accountHolder.getRootElement()
|
account = accountHolder.getRootElement()
|
||||||
account.setNameIdentifier(nameIdentifier)
|
account.setNameIdentifier(nameIdentifier)
|
||||||
account.setUserAbsolutePath(user.getAbsolutePath())
|
account.setUserAbsolutePath(user.getAbsolutePath())
|
||||||
|
user.setLibertyAllianceAccountAbsolutePath(account.getAbsolutePath())
|
||||||
userContextDump = None
|
userContextDump = None
|
||||||
else:
|
else:
|
||||||
account = accountHolder.getRootElement()
|
account = accountHolder.getRootElement()
|
||||||
|
user = account.getUser()
|
||||||
userContextDump = account.getUserContextDump()
|
userContextDump = account.getUserContextDump()
|
||||||
loginContext.create_user(userContextDump)
|
loginContext.create_user(userContextDump)
|
||||||
# Save the new or updated userContext into account.
|
# Save the new or updated userContext into account.
|
||||||
account.setUserContextDump(loginContext.user.dump())
|
account.setUserContextDump(loginContext.user.dump())
|
||||||
# Retrieve the authentication method and store it in account.
|
# Retrieve the authentication method and store it in account.
|
||||||
authenticationMethod = loginContext.response.get_child(
|
lassoAuthenticationMethod = loginContext.response.get_child(
|
||||||
"AuthenticationStatement").get_attr_value("AuthenticationMethod")
|
"AuthenticationStatement").get_attr_value("AuthenticationMethod")
|
||||||
if authenticationMethod == lasso.samlAuthenticationMethodPassword:
|
if lassoAuthenticationMethod == lasso.samlAuthenticationMethodPassword:
|
||||||
authenticationMethod = "password"
|
authenticationMethod = "password"
|
||||||
else:
|
else:
|
||||||
logs.debug('Unknown authentication method = "%s"' % authenticationMethod)
|
logs.debug('Unknown authentication method = "%s"' % lassoAuthenticationMethod)
|
||||||
account.setAuthenticationMethod(authenticationMethod)
|
account.setAuthenticationMethod(authenticationMethod)
|
||||||
account.getDocument().save()
|
account.getDocument().save()
|
||||||
# User is now authenticated => create session, cookie...
|
# User is now authenticated => create session, cookie...
|
||||||
|
@ -595,9 +597,10 @@ You have been succesfully authenticated; click ok to go back to the service prov
|
||||||
serverContextDump = self.getServerContextDump()
|
serverContextDump = self.getServerContextDump()
|
||||||
serverContext = lasso.Server.new_from_dump(serverContextDump)
|
serverContext = lasso.Server.new_from_dump(serverContextDump)
|
||||||
userContext = None
|
userContext = None
|
||||||
|
account = None
|
||||||
user = environs.getVar("user")
|
user = environs.getVar("user")
|
||||||
if user is not None:
|
if user is not None:
|
||||||
account = user.getAccount()
|
account = user.getLibertyAllianceAccount()
|
||||||
if account is not None:
|
if account is not None:
|
||||||
userContextDump = account.getUserContextDump()
|
userContextDump = account.getUserContextDump()
|
||||||
if userContextDump is not None:
|
if userContextDump is not None:
|
||||||
|
@ -616,61 +619,110 @@ You have been succesfully authenticated; click ok to go back to the service prov
|
||||||
mustAuthenticate = loginContext.must_authenticate()
|
mustAuthenticate = loginContext.must_authenticate()
|
||||||
logs.debug("User must be authenticated = %s" % mustAuthenticate)
|
logs.debug("User must be authenticated = %s" % mustAuthenticate)
|
||||||
if mustAuthenticate:
|
if mustAuthenticate:
|
||||||
# FIXME: Authenticate the user and set the right authenticationMethod.
|
if self.getConfigBoolean("yep:useHttpAuthentication", default = False):
|
||||||
userAuthenticated = True
|
# HTTP authentication.
|
||||||
authenticationMethod = lasso.samlAuthenticationMethodPassword
|
if user is None:
|
||||||
if loginContext.protocolProfile == lasso.loginProtocolProfileBrwsArt:
|
return environs.getVar("httpRequestHandler").outputErrorUnauthorized(
|
||||||
# We can send the artifact either using a redirect or a POST. It is an IDP choice,
|
self.getUriAbsolutePath())
|
||||||
# but redirect is better than POST (no need for a page with a form).
|
|
||||||
useRedirectForArtifact = True
|
|
||||||
if useRedirectForArtifact:
|
|
||||||
errorCode = loginContext.build_artifact_msg(
|
|
||||||
userAuthenticated, authenticationMethod, "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))
|
|
||||||
|
|
||||||
# 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:
|
else:
|
||||||
errorCode = loginContext.build_artifact_msg(
|
# The user is already authenticated using HTTP authentication.
|
||||||
userAuthenticated, authenticationMethod, "FIXME: reauthenticateOnOrAfter",
|
userAuthenticated = True
|
||||||
lasso.httpMethodPost)
|
authenticationMethod = "password"
|
||||||
if errorCode:
|
else:
|
||||||
raise Exception("Lasso login error %s" % errorCode)
|
# FIXME: Authenticate the user and set the right authenticationMethod.
|
||||||
logs.debug("msg_url = %s; msg_body = %s; msg_relayState = %s; "
|
raise "TODO"
|
||||||
"assertionArtifact = %s; response_dump = %s" % (
|
else:
|
||||||
loginContext.msg_url, loginContext.msg_body, loginContext.msg_relayState,
|
userAuthenticated = True
|
||||||
loginContext.assertionArtifact, loginContext.response_dump))
|
authenticationMethod = "password" # FIXME
|
||||||
raise "FIXME"
|
if authenticationMethod == "password":
|
||||||
else: # loginContext.protocolProfile == lasso.loginProtocolProfileBrwsPost:
|
lassoAuthenticationMethod = lasso.samlAuthenticationMethodPassword
|
||||||
errorCode = loginContext.build_authn_response_msg(
|
else:
|
||||||
userAuthenticated, authenticationMethod, "FIXME: reauthenticateOnOrAfter")
|
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:
|
if errorCode:
|
||||||
raise Exception("Lasso login error %s" % errorCode)
|
raise Exception("Lasso login error %s" % errorCode)
|
||||||
logs.debug("msg_url = %s; msg_body = %s; msg_relayState = %s" % (
|
logs.debug("msg_url = %s; assertionArtifact = %s; response_dump = %s" % (
|
||||||
loginContext.msg_url, loginContext.msg_body, loginContext.msg_relayState))
|
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"
|
raise "FIXME"
|
||||||
else:
|
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 "FIXME"
|
||||||
raise "TODO"
|
raise "TODO"
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,11 @@
|
||||||
|
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
|
import os
|
||||||
|
|
||||||
import expression.core.dataholders as dataholders
|
import expression.core.dataholders as dataholders
|
||||||
import expression.core.elements as elements
|
import expression.core.elements as elements
|
||||||
|
import expression.core.filesystems as filesystems
|
||||||
import expression.core.namespaces as namespaces
|
import expression.core.namespaces as namespaces
|
||||||
import expression.core.things as things
|
import expression.core.things as things
|
||||||
|
|
||||||
|
@ -99,7 +101,10 @@ class LibertyAllianceAccount(things.Thing):
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
self._user = userHolder.getRootElement()
|
# Some times, users are stored in independant files; some times they are
|
||||||
|
# embedded inside accounts.
|
||||||
|
accountOrUser = userHolder.getRootElement()
|
||||||
|
self._user = accountOrUser.getUser()
|
||||||
else:
|
else:
|
||||||
userNodes = self.evaluateXpath("yep:user")
|
userNodes = self.evaluateXpath("yep:user")
|
||||||
if userNodes:
|
if userNodes:
|
||||||
|
@ -144,10 +149,12 @@ class LibertyAllianceAccountHolder(dataholders.XmlHolder):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getPublicName(self):
|
def getPublicName(self):
|
||||||
nameIdentifier = self.getRootElement().getNameIdentifier()
|
publicName = self.getRootElement().getNameIdentifier()
|
||||||
if nameIdentifier is None:
|
if publicName is None:
|
||||||
return None
|
return None
|
||||||
return nameIdentifier
|
if self.isRootElder:
|
||||||
|
publicName = os.path.join(self.getDirectoryAbsolutePath(), publicName)
|
||||||
|
return publicName
|
||||||
|
|
||||||
def setPublicName(self, publicName):
|
def setPublicName(self, publicName):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
"""Liberty Alliance Responses Module"""
|
"""Liberty Alliance Responses Module"""
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import expression.core.dataholders as dataholders
|
import expression.core.dataholders as dataholders
|
||||||
import expression.core.elements as elements
|
import expression.core.elements as elements
|
||||||
import expression.core.namespaces as namespaces
|
import expression.core.namespaces as namespaces
|
||||||
|
@ -72,10 +74,12 @@ class LibertyAllianceResponseHolder(dataholders.XmlHolder):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getPublicName(self):
|
def getPublicName(self):
|
||||||
artifact = self.getRootElement().getArtifact()
|
publicName = self.getRootElement().getArtifact()
|
||||||
if artifact is None:
|
if publicName is None:
|
||||||
return None
|
return None
|
||||||
return artifact
|
if self.isRootElder:
|
||||||
|
publicName = os.path.join(self.getDirectoryAbsolutePath(), publicName)
|
||||||
|
return publicName
|
||||||
|
|
||||||
def setPublicName(self, publicName):
|
def setPublicName(self, publicName):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
|
import os
|
||||||
|
|
||||||
import expression.core.dataholders as dataholders
|
import expression.core.dataholders as dataholders
|
||||||
import expression.core.directories as directories
|
import expression.core.directories as directories
|
||||||
|
@ -246,7 +247,10 @@ class PasswordAccount(things.Thing):
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
self._user = userHolder.getRootElement()
|
# Some times, users are stored in independant files; some times they are
|
||||||
|
# embedded inside accounts.
|
||||||
|
accountOrUser = userHolder.getRootElement()
|
||||||
|
self._user = accountOrUser.getUser()
|
||||||
else:
|
else:
|
||||||
userNodes = self.evaluateXpath("yep:user")
|
userNodes = self.evaluateXpath("yep:user")
|
||||||
if userNodes:
|
if userNodes:
|
||||||
|
@ -288,7 +292,10 @@ class PasswordAccountHolder(dataholders.XmlHolder):
|
||||||
email = self.getRootElement().email
|
email = self.getRootElement().email
|
||||||
if email is None:
|
if email is None:
|
||||||
return None
|
return None
|
||||||
return strings.simplify(email)
|
publicName = strings.simplify(email)
|
||||||
|
if self.isRootElder:
|
||||||
|
publicName = os.path.join(self.getDirectoryAbsolutePath(), publicName)
|
||||||
|
return publicName
|
||||||
|
|
||||||
def setPublicName(self, publicName):
|
def setPublicName(self, publicName):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
<configuration xmlns="http://www.entrouvert.org/namespaces/expression/0.0">
|
<configuration xmlns="http://www.entrouvert.org/namespaces/expression/0.0">
|
||||||
<defaultMode>list</defaultMode> <!-- for directories and Zips and... -->
|
<defaultMode>list</defaultMode> <!-- for directories and Zips and... -->
|
||||||
<sessionsPath>sessions</sessionsPath>
|
<sessionsPath>sessions</sessionsPath>
|
||||||
|
<useHttpAuthentication>true</useHttpAuthentication>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<peerPublicKeyFile>../security/public/service-provider-liberty-alliance.key</peerPublicKeyFile>
|
<peerPublicKeyFile>../security/public/service-provider-liberty-alliance.key</peerPublicKeyFile>
|
||||||
<peerCACertificateFile>../security/public/ca-liberty-alliance.crt</peerCACertificateFile>
|
<peerCACertificateFile>../security/public/ca-liberty-alliance.crt</peerCACertificateFile>
|
||||||
|
|
||||||
|
<accountsDirectory>accounts</accountsDirectory>
|
||||||
<responsesDirectory>responses</responsesDirectory>
|
<responsesDirectory>responses</responsesDirectory>
|
||||||
|
|
||||||
<mode name="afterAuthentication"><users commands="ACCESS GET"><everybody/></users></mode>
|
<mode name="afterAuthentication"><users commands="ACCESS GET"><everybody/></users></mode>
|
||||||
|
|
Reference in New Issue