saml2: begin slo implementation

This commit is contained in:
Jérôme Schneider 2013-05-27 08:47:06 +02:00
parent 765b526c6e
commit bcb29a4cc2
1 changed files with 106 additions and 2 deletions

View File

@ -28,7 +28,10 @@ class SAML2Auth(AuthForm):
lasso.SAML2_METADATA_BINDING_POST ,
self.config.END_POINTS_PATH['single_sign_on_post']
),
)
('SingleLogoutService',
lasso.SAML2_METADATA_BINDING_REDIRECT,
'/singleLogout', '/singleLogoutReturn'),
)
self.metadata_options = { 'key': self.config.SAML_SIGNATURE_PUBLIC_KEY }
super(SAML2Auth, self).__init__(form_values, site_name)
@ -108,7 +111,7 @@ class SAML2Auth(AuthForm):
return str(metagen)
def sso(self, env, values, request, response):
target_idp = None
target_idp = self.config.IDP_METADATA
metadata_file_path = self._get_idp_metadata_file_path()
if not metadata_file_path:
return _500('sso', 'Unable to load provider.')
@ -145,6 +148,37 @@ class SAML2Auth(AuthForm):
return _500('sso', 'Enable to perform sso by redirection.')
return _302(login.msgUrl)
def slo(self, env, values, request, response):
logger.debug('saml2_slo: new slo request')
target_idp = self.config.IDP_METADATA
metadata_file_path = self._get_idp_metadata_file_path()
logger.debug('saml2_slo: target idp %s' % target_idp)
logger.debug('saml2_slo: metadata file path %s' % metadata_file_path)
server = create_server(self._get_metadata(env),
self.config.SAML_SIGNATURE_PRIVATE_KEY)
if not server:
return _500('saml2_slo', 'Error creating server object.')
logger.debug('saml2_slo: mandaye server object created')
server.addProvider(lasso.PROVIDER_ROLE_IDP, metadata_file_path)
logout = lasso.Logout(server)
if not logout:
return _500('saml2_slo', 'Error creating logout object.')
try:
logout.initRequest(target_idp, lasso.HTTP_METHOD_REDIRECT)
except:
logger.critical('sp_slo: init request error')
return _500('saml2_slo', 'init request error')
try:
logout.buildRequestMsg()
except:
logger.critical('sp_slo: build request error')
return _500('saml2_slo', 'build request error')
logger.info('sp_slo: sp_slo by redirect')
#save_key_values(logout.request.id,
# logout.dump(), provider_id, next)
return _302(logout.msgUrl)
def single_sign_on_post(self, env, values, request, response):
target_idp = None
metadata_file_path = self._get_idp_metadata_file_path()
@ -197,6 +231,76 @@ class SAML2Auth(AuthForm):
return _302(values['next_url'])
def singleLogout(self, env, values, request, response):
'''
Single Logout IdP initiated by Redirect
'''
query = get_saml2_query_request(request)
if not query:
return http_response_forbidden_request('singleLogout: \
Unable to handle Single Logout by Redirect without request')
server = build_service_provider(request)
if not server:
return http_response_forbidden_request('singleLogout: \
Service provider not configured')
logout = lasso.Logout(server)
provider_loaded = None
while True:
try:
logout.processRequestMsg(query)
break
except (lasso.ServerProviderNotFoundError,
lasso.ProfileUnknownProviderError):
provider_id = logout.remoteProviderId
provider_loaded = load_provider(request, provider_id,
server=server, sp_or_idp='idp')
if not provider_loaded:
message = _('singleLogout: provider %r unknown') % provider_id
return error_page(request, message, logger=logger)
else:
continue
except lasso.Error, error:
logger.error('singleLogout: %s' % lasso.strError(error[0]))
return slo_return_response(logout)
logger.info('singleLogout: from %s' % logout.remoteProviderId)
policy = get_idp_options_policy(provider_loaded)
if not policy:
logger.error('singleLogout: No policy found for %s'\
% logout.remoteProviderId)
return return_logout_error(request, logout,
AUTHENTIC_STATUS_CODE_UNAUTHORIZED)
if not policy.accept_slo:
logger.warn('singleLogout: received slo from %s not authorized'\
% logout.remoteProviderId)
return return_logout_error(request, logout,
AUTHENTIC_STATUS_CODE_UNAUTHORIZED)
load_session(request, logout, kind=LIBERTY_SESSION_DUMP_KIND_SP)
try:
logout.validateRequest()
except lasso.Error, error:
logger.error('singleLogout: %s' % lasso.strError(error[0]))
return slo_return_response(logout)
#Play the role of IdP sending a SLO to all SP
slo_soap_as_idp(request, logout)
#Break local session and respond to the IdP initiating the SLO
if logout.isSessionDirty:
if logout.session:
save_session(request, logout, kind=LIBERTY_SESSION_DUMP_KIND_SP)
else:
delete_session(request)
remove_liberty_session_sp(request)
signals.auth_logout.send(sender=None, user=request.user)
auth_logout(request)
return slo_return_response(logout)
def metadata(self, env, values, request, response):
title='metadata'