single logout and federation termination support (both initiated by idp, either

redirect or soap).
This commit is contained in:
Frédéric Péters 2005-05-21 06:21:12 +00:00
parent e37585e783
commit 60ebf982ba
3 changed files with 137 additions and 2 deletions

View File

@ -18,7 +18,8 @@ import wcs.misc
from wcs import storage
class RootDirectory(Directory):
_q_exports = ["", "login", "assertionConsumer"]
_q_exports = ["", "login", "assertionConsumer", "singleLogout", "soapEndpoint",
"federationTermination", "federationTerminationReturn"]
def login(self):
server = wcs.misc.get_lasso_server()
@ -52,6 +53,7 @@ class RootDirectory(Directory):
login.processAuthnResponseMsg(get_field('LARES'))
login.acceptSso()
session = get_session()
session.lasso_session_dump = login.session.dump()
ni = login.nameIdentifier.content
for user in storage.get_storage().values('users'):
if ni in user.name_identifiers:
@ -59,8 +61,12 @@ class RootDirectory(Directory):
session.set_user(user.id)
break
else:
user = None
session.name_identifier = ni
session.set_user('anonymous-%s' % ni)
if user: # XXX doesn't store identity dump if anonymous; is this ok with liberty?
user.lasso_dump = login.identity.dump()
storage.get_storage().store(user)
response = get_response()
if session.after_url:
after_url = session.after_url
@ -71,6 +77,133 @@ class RootDirectory(Directory):
response.content_type = 'text/plain'
return "Your browser should redirect you"
def singleLogout(self):
request = get_request()
if lasso.isLibertyQuery(request.get_query()):
request = get_request()
logout = lasso.Logout(wcs.misc.get_lasso_server())
logout.processRequestMsg(request.get_query())
return self.slo_idp(logout, get_session())
else:
return self.slo_sp()
def slo_idp(self, logout, session):
# Single Logout initiated by IdP
if session.lasso_session_dump:
logout.setSessionFromDump(session.lasso_session_dump)
if session.user and not session.user.startswith('anonymous-'):
user = storage.get_storage().retrieve('users', session.user)
if user.lasso_dump:
logout.setIdentityFromDump(user.lasso_dump)
if logout.nameIdentifier.content != session.name_identifier:
raise "no appropriate name identifier in session"
try:
logout.validateRequest()
except lasso.Error, error:
if error[0] != lasso.PROFILE_ERROR_SESSION_NOT_FOUND:
raise
else:
get_session_manager().expire_session()
logout.buildResponseMsg()
if logout.msgBody: # soap answer
return logout.msgBody
else:
return redirect(logout.msgUrl)
def soapEndpoint(self):
request = get_request()
ctype = request.environ.get("CONTENT_TYPE")
if not ctype:
return
ctype, ctype_params = parse_header(ctype)
if ctype != 'text/xml':
return
response = get_response()
response.set_content_type('text/xml')
length = int(request.environ.get('CONTENT_LENGTH'))
soap_message = request.stdin.read(length)
request_type = lasso.getRequestTypeFromSoapMsg(soap_message)
if request_type == lasso.REQUEST_TYPE_LOGOUT:
logout = lasso.Logout(wcs.misc.get_lasso_server())
logout.processRequestMsg(soap_message)
for session in get_session_manager().values():
if name_identifier == session.name_identifier:
break
else:
raise "session not found"
return self.slo_idp(logout, session)
if request_type == lasso.REQUEST_TYPE_DEFEDERATION:
defederation = lasso.Defederation(get_lasso_server())
defederation.processNotificationMsg(soap_message)
name_identifier = defederation.nameIdentifier.content
for session in get_session_manager().values():
if name_identifier == session.name_identifier:
break
else:
raise "session not found"
return self.fedterm(defederation, session)
def federationTermination(self):
request = get_request()
if not lasso.isLibertyQuery(request.get_query()):
return redirect('.')
defederation = lasso.Defederation(wcs.misc.get_lasso_server())
defederation.processNotificationMsg(request.get_query())
session = get_session()
return self.fedterm(defederation, session)
def fedterm(self, defederation, session):
defederation.setSessionFromDump(session.lasso_session_dump)
try:
user = storage.get_storage().retrieve('users', session.user)
except KeyError:
pass
else:
if user.lasso_dump:
defederation.setIdentityFromDump(user.lasso_dump)
try:
defederation.validateNotification()
except lasso.Error, error:
pass # ignore failure (?)
else:
if not defederation.identity:
# if it was the last federation the whole identity dump collapsed
user.lasso_dump = None
else:
user.lasso_dump = defederation.identity.dump()
storage.get_storage().store(user)
if defederation.isSessionDirty:
if defederation.session:
session.lasso_session_dump = defederation.session.dump()
else:
session.lasso_session_dump = None
if defederation.msgUrl:
return redirect(defederation.msgUrl)
else:
get_session_manager().commit_changes(session)
response = get_response()
response.set_status(204)
return ''
def federationTerminationReturn(self):
return redirect('/')
def soap_call(url, msg):
if url.startswith('http://'):
host, query = urllib.splithost(url[5:])

View File

@ -11,9 +11,10 @@ class BasicSession(Session, storage.Storable):
Session.__init__(self, id)
self.name_identifier = None
self.after_url = None
self.lasso_session_dump = None
def has_info(self):
return self.name_identifier or self.after_url or Session.has_info(self)
return self.name_identifier or self.after_url or self.lasso_session_dump or Session.has_info(self)
is_dirty = has_info

View File

@ -11,4 +11,5 @@ class User(storage.Storable):
self.roles = []
self.name_identifiers = []
self.identification_token = None
self.lasso_dump = None