def get_authn_request(request, came_from, selected_idp, required_loa=None, force_authn=False): # Request the right AuthnContext for workmode # (AL1 for 'personal', AL2 for 'helpdesk' and AL3 for 'admin' by default) if required_loa is None: required_loa = request.registry.settings.get('required_loa', {}) workmode = request.registry.settings.get('workmode') required_loa = required_loa.get(workmode, '') log.debug('Requesting AuthnContext {!r}'.format(required_loa)) kwargs = { "requested_authn_context": RequestedAuthnContext( authn_context_class_ref=AuthnContextClassRef( text=required_loa ) ), "force_authn": str(force_authn).lower(), } client = Saml2Client(request.saml2_config) try: (session_id, info) = client.prepare_for_authenticate( entityid=selected_idp, relay_state=came_from, binding=BINDING_HTTP_REDIRECT, **kwargs ) except TypeError: log.error('Unable to know which IdP to use') raise oq_cache = OutstandingQueriesCache(request.session) oq_cache.set(session_id, came_from) return info
def test_outstanding_queries(self): oqc = OutstandingQueriesCache({}) oqc._db['user'] = '******' oqc._db.sync() self.assertEqual(oqc.outstanding_queries(), {'user': '******'})
def login_view(request): login_redirect_url = request.registry.settings.get( 'saml2.login_redirect_url', '/') came_from = request.GET.get('next', login_redirect_url) if authenticated_userid(request): return HTTPFound(location=came_from) selected_idp = request.GET.get('idp', None) idps = request.saml2_config.getattr('idp') if selected_idp is None and len(idps) > 1: log.debug('A discovery process is needed') return render_to_response('templates/wayf.jinja2', { 'available_idps': idps.items(), 'came_from': came_from, 'login_url': request.route_url('saml2-login'), }) # Request the right AuthnContext for workmode # (AL1 for 'personal', AL2 for 'helpdesk' and AL3 for 'admin' by default) required_loa = request.registry.settings.get('required_loa', {}) workmode = request.registry.settings.get('workmode') required_loa = required_loa.get(workmode, '') log.debug('Requesting AuthnContext {!r} for workmode {!r}'.format(required_loa, workmode)) kwargs = { "requested_authn_context": RequestedAuthnContext( authn_context_class_ref=AuthnContextClassRef( text=required_loa ) ) } client = Saml2Client(request.saml2_config) try: (session_id, result) = client.prepare_for_authenticate( entityid=selected_idp, relay_state=came_from, binding=BINDING_HTTP_REDIRECT, **kwargs ) except TypeError: log.error('Unable to know which IdP to use') raise oq_cache = OutstandingQueriesCache(request.session) oq_cache.set(session_id, came_from) log.debug('Redirecting the user to the IdP') if not request.is_xhr: return HTTPFound(location=get_location(result)) else: loginurl = request.route_url('saml2-login', _query=(('next', request.path),)) return HTTPXRelocate(loginurl)
def assertion_consumer_service(request): if 'SAMLResponse' not in request.POST: return HTTPBadRequest("Couldn't find 'SAMLResponse' in POST data.") xmlstr = request.POST['SAMLResponse'] client = Saml2Client(request.saml2_config, identity_cache=IdentityCache(request.session)) oq_cache = OutstandingQueriesCache(request.session) outstanding_queries = oq_cache.outstanding_queries() try: # process the authentication response response = client.parse_authn_request_response(xmlstr, BINDING_HTTP_POST, outstanding_queries) except AssertionError: log.error('SAML response is not verified') return HTTPBadRequest( """SAML response is not verified. May be caused by the response was not issued at a reasonable time or the SAML status is not ok. Check the IDP datetime setup""") if response is None: log.error('SAML response is None') return HTTPBadRequest( "SAML response has errors. Please check the logs") session_id = response.session_id() oq_cache.delete(session_id) # authenticate the remote user session_info = response.session_info() log.debug('Trying to locate the user authenticated by the IdP') log.debug('Session info:\n{!s}\n\n'.format(pprint.pformat(session_info))) user = authenticate(request, session_info) if user is None: log.error('Could not find the user identified by the IdP') return HTTPUnauthorized("Access not authorized") headers = login(request, session_info, user) _set_name_id(request.session, session_info['name_id']) # redirect the user to the view where he came from relay_state = request.POST.get('RelayState', '/') log.debug('Redirecting to the RelayState: ' + relay_state) return HTTPFound(location=relay_state, headers=headers)
def add_outstanding_query(self, came_from): queryUtility = self.testapp.app.registry.queryUtility session_factory = queryUtility(ISessionFactory) request = DummyRequest() session = session_factory(request) session.persist() # ensure that session id is a NCName valid session._sess.id = "a" + session._sess.id oq_cache = OutstandingQueriesCache(session) oq_cache.set(session._sess.id, came_from) session.persist() self.testapp.cookies['beaker.session.id'] = session._sess.id return session._sess.id
def test_delete(self): oqc = OutstandingQueriesCache({}) oqc.set('session_id', '/next') self.assertEqual(oqc.outstanding_queries(), {'session_id': '/next'}) oqc.delete('session_id') self.assertEqual(oqc.outstanding_queries(), {})