Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hard expiration to Flask session #5907

Merged
merged 12 commits into from Oct 27, 2023

Conversation

cbartz
Copy link
Contributor

@cbartz cbartz commented Aug 25, 2023

This PR adds the ability to set a hard expiration for the Flask session. This can be used in conjunction with a Flask Multipass identity provider that specifies the session expiration. See this post for more details on use cases and implementation considerations.

indico/web/flask/session.py Outdated Show resolved Hide resolved
indico/web/flask/session.py Outdated Show resolved Hide resolved
indico/web/flask/session_test.py Outdated Show resolved Hide resolved
indico/web/flask/session_test.py Outdated Show resolved Hide resolved
CHANGES.rst Outdated Show resolved Hide resolved
@cbartz cbartz marked this pull request as ready for review August 28, 2023 07:57
indico/modules/auth/auth_test.py Outdated Show resolved Hide resolved
indico/modules/auth/auth_test.py Outdated Show resolved Hide resolved
indico/web/flask/session.py Outdated Show resolved Hide resolved
@ThiefMaster
Copy link
Member

Just wondering... should there some kind of indicator that the session will expire soon when someone uses this feature? It'd be a bit disruptive if someone is e.g. writing an abstract or minutes for an event and does not realize that the session will expire in a few minutes!

@cbartz
Copy link
Contributor Author

cbartz commented Aug 30, 2023

Just wondering... should there some kind of indicator that the session will expire soon when someone uses this feature? It'd be a bit disruptive if someone is e.g. writing an abstract or minutes for an event and does not realize that the session will expire in a few minutes!

This may make sense. Would a flash inside session.py be the right approach or is there a better way?

@ThiefMaster
Copy link
Member

We do use flash messages in a few places, but IMHO it would be nicer to actually expose the session expiry to the client, and show a warning dialog client-side that the session will soon expire (with the option to refresh it (by going through the login again)) when getting close to the expiry.

@SegiNyn
Copy link
Contributor

SegiNyn commented Oct 2, 2023

but IMHO it would be nicer to actually expose the session expiry to the client, and show a warning dialog client-side that the session will soon expire (with the option to refresh it (by going through the login again)) when getting close to the expiry.

Hi @ThiefMaster, we were also proposing an expiration dialog of this nature to warn users when the session is about to expire and give them the opportunity to refresh:
Screenshot 2023-10-02 at 17 10 40
Screenshot 2023-10-02 at 17 10 54

is this something we can coordinate with this pr?

cc @OmeGak

@ThiefMaster
Copy link
Member

Maybe it's best for @SegiNyn to send a PR to @cbartz's branch used for this PR? Alterantively, @cbartz could give her access to his fork of Indico in order to push directly on top of his changes.

At least i'd prefer those options over first merging it and then having a separate PR to improve it...

@SegiNyn
Copy link
Contributor

SegiNyn commented Oct 10, 2023

Sending a pr to @cbartz's branch sounds good to me.

@@ -30,6 +32,12 @@
@multipass.identity_handler
def process_identity(identity_info):
logger.info('Received identity info: %s', identity_info)

if session_expiry := identity_info.multipass_data.get('session_expiry'):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @cbartz, please does this work when logging in with a local account? I'm getting a AttributeError: 'NoneType' object has no attribute 'get' when logging in with a local account.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the multipass_data is None for local accounts. so this is currently a bug in the PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thanks

@SegiNyn
Copy link
Contributor

SegiNyn commented Oct 20, 2023

Hi @ThiefMaster, I have sent a PR to @cbartz's branch here: cbartz#1 There are still some problems with it like some resources being fetched when opening the dialog which refreshes the session. You won't see this if you run indico with the -q flag because those requests will be silenced in the logs but they still reach the app and refresh the session.

@ThiefMaster
Copy link
Member

ThiefMaster commented Oct 20, 2023

Try this to prevent those requests from refreshing the session:

diff --git a/indico/web/flask/session.py b/indico/web/flask/session.py
index 8637f295c4..1d7fc785dd 100644
--- a/indico/web/flask/session.py
+++ b/indico/web/flask/session.py
@@ -162,6 +162,9 @@ class IndicoSessionInterface(SessionInterface):
             return self.temporary_session_lifetime

     def should_refresh_session(self, app, session):
+        if (request.blueprint == 'assets' or
+                (request.blueprint.startswith('plugin_') and request.endpoint.endswith('.static'))):
+            return False
         if session.new or '_expires' not in session:
             return False
         threshold = self.get_storage_lifetime(app, session) / 2

Or replace that whole if condition with re.match(r'assets\.|plugin_.*\.static$', request.endpoint) (you may want to re.compile() that regex since it's used on every single request)

@@ -25,4 +26,7 @@
{{ render_announcements() }}
{% endblock %}
{% block body %}{% endblock %}
{% block session_expiration %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SegiNyn do you override that block on your side? or is it a leftover that's no longer needed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry this is a leftover that's not being used

@ThiefMaster
Copy link
Member

I forcepushed some cleanups and also getting rid of those merge commits while rebasing

@ThiefMaster
Copy link
Member

@SegiNyn some feedback after testing this:

  • I think the RequestConfirm component is not a good choice here. It's meant for confirmation of possibly destructive actions. For example, it has no option to only show one button (OK and Cancel doing the same is bad UX) nor to not close when clicking outside the dialog.
  • Sending the user back to the login page only makes sense if there's a hard expiry date set for the session (and thus no possibility of refreshing it). Otherwise a request to an endpoint that simply refreshes its lifetime (as is the case during regular Indico usage) should be made which is much less intrusive (imagine you're writing minutes or an abstract and get this message - you do not expect a redirect, and in most cases it would not be necessary).

@ThiefMaster
Copy link
Member

Also, considering that the dialog still needs a bit of work and is not as straightforward as I originally thought, I'm thinking about merging this PR without the dialog stuff tomorrow (3.3 is under development so having no indicator of a soon-expiring session for the time being is fine). That way we avoid the indirection of PRs to a fork, and reviewing the dialog stuff properly will be easier...

@SegiNyn
Copy link
Contributor

SegiNyn commented Oct 26, 2023

hi @ThiefMaster, Yes I did notice the issue with the buttons which basically do the same thing but I had not thought of how disruptive it would be to refresh the page while the user is filling in an abstract. So I can add a custom dialog for this part. It's ok for me if you merge this pr with the hard expiry and then I create a different one for the dialog. I'm not going to be in tomorrow so I cannot work on it until Monday anyway.

@ThiefMaster ThiefMaster merged commit 3689c09 into indico:master Oct 27, 2023
12 checks passed
@ThiefMaster
Copy link
Member

@SegiNyn I pushed a branch containing your changes, rebased on top of the latest master, to session-expiry-with-dialog in my indico fork. It contains some fixes I did on top of your code so it might be good for you to reset your local branch to that one.

@cbartz
Copy link
Contributor Author

cbartz commented Oct 27, 2023

Thanks for merging the PR @ThiefMaster

@cbartz cbartz deleted the multipass-session-expiry branch October 27, 2023 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants