single logout and federation termination support (both initiated by idp, either
redirect or soap).
This commit is contained in:
parent
e37585e783
commit
60ebf982ba
|
@ -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:])
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -11,4 +11,5 @@ class User(storage.Storable):
|
|||
self.roles = []
|
||||
self.name_identifiers = []
|
||||
self.identification_token = None
|
||||
self.lasso_dump = None
|
||||
|
||||
|
|
Loading…
Reference in New Issue