misc: use session to track passive auth (#43196)

This commit is contained in:
Frédéric Péters 2023-10-05 20:31:19 +02:00
parent a3e596acb4
commit 212197150d
3 changed files with 23 additions and 30 deletions

View File

@ -701,11 +701,15 @@ def test_opened_session_cookie(pub, path):
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
pub.site_options.write(fd)
pub.session_class.wipe()
resp = app.get(f'{path}?parameter=value')
cookie_name = '%s-passive-auth-tried' % pub.config.session_cookie_name
assert pub.session_class.count() == 1
assert pub.session_class.select()[0].opened_session_value
cookie_name = pub.config.session_cookie_name
cookie_store = http.cookies.SimpleCookie()
cookie_store.load(resp.headers['Set-Cookie'])
assert list(cookie_store.keys()) == [cookie_name]
assert pub.session_class.select()[0].id == cookie_store[cookie_name].value
assert 'HttpOnly' in resp.headers['Set-Cookie']
assert 'SameSite=None' in resp.headers['Set-Cookie']
assert 'Path=/' in resp.headers['Set-Cookie']
@ -745,8 +749,6 @@ def test_opened_session_cookie(pub, path):
assert resp.status_int == 200
assert get_session(app).opened_session_value == '2'
assert get_session(app).user == user.id
# '*-passive-auth-tried' cookie was removed, since we logged in.
assert cookie_name not in app.cookies
# if the IDP_OPENED_SESSION cookie change then we are logged out
app.set_cookie('IDP_OPENED_SESSION', '3')
@ -787,12 +789,16 @@ def test_expired_opened_session_cookie_menu_json(pub):
session.id = 'abcd'
session.store()
app.set_cookie(pub.config.session_cookie_name, session.id)
app.set_cookie(pub.config.session_cookie_name + '-passive-auth-tried', '3')
# access to a restricted page with no session on the idp or passive sso already tried
# access to a restricted page with no session on the idp or passive sso not yet tried
app.set_cookie('IDP_OPENED_SESSION', '3')
app.get('/backoffice/menu.json', status=302)
# access to a restricted page with passive sso tried
session.opened_session_value = '3'
session.store()
app.get('/backoffice/menu.json', status=403)
def test_opened_session_backoffice_url(pub):
app = get_app(pub)

View File

@ -127,6 +127,7 @@ class Session(QommonSession, CaptchaSession, StorableObject):
or self.has_uploads
or self.jsonp_display_values
or self.extra_variables
or self.opened_session_value
or CaptchaSession.has_info(self)
or self.expire
or self.extra_user_variables

View File

@ -317,7 +317,6 @@ class RootDirectory(Directory):
def try_passive_sso(self, path):
publisher = get_publisher()
idp_session_cookie_name = publisher.get_site_option('idp_session_cookie_name')
passive_tried_cookie_name = '%s-passive-auth-tried' % publisher.config.session_cookie_name
if not idp_session_cookie_name:
return
@ -330,13 +329,6 @@ class RootDirectory(Directory):
request = get_request()
cookies = request.cookies
response = get_response()
# expire passive_tried_cookie_name if already logged or if not equal to passive_tried_cookie_name
if passive_tried_cookie_name in cookies and (
request.user or cookies.get(passive_tried_cookie_name) != cookies.get(idp_session_cookie_name)
):
response.expire_cookie(passive_tried_cookie_name)
if request.user:
if request.session.opened_session_value and request.session.opened_session_value != cookies.get(
@ -345,31 +337,25 @@ class RootDirectory(Directory):
# logout current user if saved value for idp_session_cookie_name differs from the current one
get_session_manager().expire_session()
get_request()._user = ()
get_publisher().session_manager.start_request()
get_publisher().session_manager.maintain_session(get_session())
else:
# already logged, stop here.
return
elif path and path[0] in ('api', 'backoffice', 'login'):
# do not start passive SSO for API or backoffice or login URLs
return
if idp_session_cookie_name not in cookies or cookies.get(idp_session_cookie_name) == cookies.get(
passive_tried_cookie_name
session = get_session()
if (
idp_session_cookie_name not in cookies
or cookies.get(idp_session_cookie_name) == session.opened_session_value
):
# no session on the idp or passive sso already tried, init a new session if necessary
# (because it was explicitly expired just above), then let the flow continue and the
# expected page be served.
if get_session() is None:
# init a new session
get_publisher().session_manager.start_request()
get_publisher().session_manager.maintain_session(get_session())
# let the flow continue and the expected page be served.
return
response.set_cookie(
passive_tried_cookie_name,
cookies.get(idp_session_cookie_name),
secure=request.scheme == 'https',
httponly=1,
path=publisher.config.session_cookie_path,
domain=publisher.config.session_cookie_domain,
)
session.opened_session_value = cookies.get(idp_session_cookie_name)
url = request.get_url()
query = request.get_query()
if query: