def active(self, request): """ we re-extract credentials from the SAML2 service, but with is_pasive=False to initiate a redirect to the login page if no SSI session exists. """ actual_url = request.get("ACTUAL_URL", '') sp_url = self.saml2_sp_url if not actual_url.startswith(sp_url): # the request was made to a URL we cannot handle return None session = request.SESSION session.set(self.session_auth_key, False) logger.info('REFERER: %s' % request.HTTP_REFERER) session.set(self.session_storedurl_key, request.HTTP_REFERER) config = self._saml2_config() entityid = config.metadata.keys()[0] # Initiate challenge scl = Saml2Client(config) # if we have an existing SSI session, continue in extractCredentials, otherwise redirect to SAML2 login (sid, result) = scl.authenticate( entityid, binding=BINDING_HTTP_REDIRECT, requested_authn_context=self._authn_context()) session.set(self.session_sessid, {sid: ''}) headers = dict(result['headers']) for k, v in headers.items(): request.response.setHeader(k, v) request.response.redirect(headers['Location'], lock=1) return True
def redirect_logout_request(self, request): session = request.SESSION session.set(self.session_auth_key, False) config = self._saml2_config() scl = Saml2Client(config) sessidx = session.get(self.session_samlsessionindex_key, '') msg = scl.http_redirect_logout_request_check_session_index( request, sessidx, logger) headers = dict(msg['headers']) return request.response.redirect(headers['Location'], lock=True)
def slo(self, request): """ generate a SAML2 logout request; reset session; return IDP URL """ session = request.SESSION session.set(self.session_auth_key, False) del session[self.session_user_properties] config = self._saml2_config() scl = Saml2Client(config) samluid = session.get(self.session_samluid_key, '') entityid = config.metadata.keys()[0] sp_url = self.saml2_sp_url actual_url = request.get("ACTUAL_URL", '') if not actual_url.startswith(sp_url): # the request was made from within a context we cannot handle return None session.set(self.session_storedurl_key, request.URL1) # we cannot simply call global_logout on the client since it doesn't know about our user... srvs = scl.metadata.single_logout_service(entityid, BINDING_HTTP_REDIRECT, "idpsso") destination = destinations(srvs)[0] samlrequest = scl.create_logout_request( destination, entityid, name_id=saml.NameID(text=samluid)) samlrequest.session_index = samlp.SessionIndex( session.get(self.session_samlsessionindex_key)) to_sign = [] samlrequest = signed_instance_factory(samlrequest, scl.sec, to_sign) logger.info('SSO logout request: %s' % samlrequest.to_string()) session_id = samlrequest.id rstate = scl._relay_state(session_id) msg = http_redirect_message(samlrequest, destination, rstate) headers = dict(msg['headers']) location = headers['Location'] logger.info( 'attempting to post: {loc}'.format(loc=headers['Location'])) return location
def passive(self, request): session = request.SESSION if session.get(self.session_auth_key, False): session.set(self.session_lock_key, False) return {'login': session[self.session_login_key], 'ssiauth': True} creds = {} config = self._saml2_config() scl = Saml2Client(config) entityid = config.metadata.keys()[0] sp_url = self.saml2_sp_url actual_url = request.get("ACTUAL_URL", '') if not actual_url.startswith(sp_url): # the request was made from within a context we cannot handle return None actual_url_with_query = '%s?%s' % (actual_url, make_query( request.form)) if request.get( 'REQUEST_METHOD') == 'GET' else actual_url # Initiate challenge if 'SAMLResponse' not in request.form and not session.get( self.session_lock_key, False): session.set(self.session_lock_key, True) logger.info('ACTUAL_URL: %s' % actual_url) (sid, result) = scl.authenticate( entityid, binding=BINDING_HTTP_REDIRECT, is_passive='true', requested_authn_context=self._authn_context(), service_url_binding=self.saml2_service_url_binding, ) #session.set(self.session_sessid, {sid:''}) session.set(self.session_storedurl_key, actual_url_with_query) headers = dict(result['headers']) for k, v in headers.items(): request.response.setHeader(k, v) request.response.redirect(headers['Location'], lock=1) # Idp response - protocol binding POST if 'SAMLResponse' in request.form and actual_url.strip( '/') == sp_url.strip('/'): post_env = request.environ.copy() post_env['QUERY_STRING'] = '' request.stdin.seek(0) post = cgi.FieldStorage( fp=StringIO(request.stdin.read()), environ=post_env, keep_blank_values=True, ) storedurl = session.get(self.session_storedurl_key, actual_url_with_query) if session.has_key(self.session_storedurl_key): session.delete(self.session_storedurl_key) request.response.redirect(storedurl) try: sessinfo = scl.parse_authn_request_response( post['SAMLResponse'].value, BINDING_HTTP_POST, session.get(self.session_sessid, {})) except: session.set(self.session_auth_key, False) # Saml2 auth failed. Do not ask again. return None creds = self._setup_local_session(session, scl, sessinfo) elif 'SAMLart' in request.form: storedurl = session.get(self.session_storedurl_key, actual_url_with_query) if session.has_key(self.session_storedurl_key): session.delete(self.session_storedurl_key) request.response.redirect(storedurl) r = scl.artifact2message(request.form.pop('SAMLart'), 'idpsso') logger.info(r.text) if r.status_code == 200: try: response = scl.parse_artifact_resolve_response(r.text) response.attribute_converters = scl.config.attribute_converters response.assertion = response.assertion[0] response.ava = get_identity(response) creds = self._setup_local_session(session, scl, response) except: session.set(self.session_auth_key, False) # Saml2 auth failed. Do not ask again. return None return creds