o-nikolas commented on code in PR #72825:
URL: https://github.com/apache/airflow/pull/72825#discussion_r3974256911
##########
providers/fab/src/airflow/providers/fab/www/extensions/init_session.py:
##########
@@ -62,3 +70,32 @@ def make_session_permanent():
f"[fab] session_backend: '{selected_backend}'. Please set "
"this to either 'database' or 'securecookie'."
)
+
+
+def init_session_max_lifetime(app):
+ """Expire sessions ``[fab] session_max_lifetime_minutes`` after login,
regardless of activity."""
+ max_lifetime_minutes = conf.getint("fab", "session_max_lifetime_minutes",
fallback=0)
+ if max_lifetime_minutes <= 0:
+ return
+
+ max_lifetime_seconds = max_lifetime_minutes * 60
+
+ # ``weak=False``: the receiver is a local function, so a weak subscription
could be collected.
+ @user_logged_in.connect_via(app, weak=False)
+ def stamp_login_time(sender, user, **kwargs):
+ # Wall clock rather than ``time.monotonic()``: the stamp is persisted
in the session and
+ # read back by other API server processes, which share no monotonic
clock origin.
+ builtin_flask_session[SESSION_LOGIN_TIME_KEY] = time.time()
+
+ @app.before_request
+ def expire_session_past_max_lifetime():
+ login_time = builtin_flask_session.get(SESSION_LOGIN_TIME_KEY)
+ if login_time is None:
+ # Sessions that predate this setting have no stamp; cap them from
now on rather than
+ # leaving them exempt forever.
+ if current_user.is_authenticated:
+ builtin_flask_session[SESSION_LOGIN_TIME_KEY] = time.time()
+ return
+ if time.time() - login_time > max_lifetime_seconds:
+ log.debug("Session reached [fab] session_max_lifetime_minutes,
expiring it.")
+ builtin_flask_session.clear()
Review Comment:
My agent seems to think calling `logout_user()` is more effective than
`builtin_flask_session.clear()` (or both if really needed). Worth circling back
with yours about.
##########
providers/fab/provider.yaml:
##########
@@ -208,11 +208,34 @@ config:
session_lifetime_minutes:
description: |
The UI cookie lifetime in minutes. User will be logged out from UI
after
- ``[fab] session_lifetime_minutes`` of non-activity
+ ``[fab] session_lifetime_minutes`` of inactivity: the deadline
slides forward on every
+ request, so it is only reached once the session has been idle for
the whole period.
+
+ Note that leaving an Airflow UI tab open counts as activity even
when nobody is at the
+ keyboard. The UI polls the API in the background and silently
re-authenticates whenever
+ its API token expires, which keeps sliding the deadline, so a
session with an open tab is
+ never idle and never expires. Use ``[fab]
session_max_lifetime_minutes`` to log users out
+ after a fixed period regardless of activity.
version_added: 2.0.0
type: integer
example: ~
default: "43200"
+ session_max_lifetime_minutes:
+ description: |
+ Maximum lifetime of a UI session in minutes, counted from the login
time and never
+ extended by activity. Unlike ``[fab] session_lifetime_minutes``,
this deadline is
+ reached even when the user keeps working in the UI, so it forces
periodic
+ re-authentication. Set to ``0`` (the default) to disable it.
+
+ The session is only checked when the UI talks to the auth manager,
which it does when
+ its API token expires, so ``[api_auth] jwt_expiration_time`` bounds
how precisely the
+ deadline is enforced: with the default 24 hour token, a shorter
maximum lifetime still
+ takes up to 24 hours to log the user out. Set ``[api_auth]
jwt_expiration_time`` no
Review Comment:
My agent seems to think this gap is worse, if I understand correctly:
> The config text is honest that [api_auth] jwt_expiration_time bounds the
precision. But the effective worst case is
session_max_lifetime_minutes + jwt_expiration_time, and with the shipped
defaults that's the config's own example (480 minutes) plus 86400
seconds — up to roughly 32 hours after login for someone who thinks they
configured 8. Even after the session is cleared, an already-issued
JWT stays valid until it expires; the session isn't the boundary for API
calls.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]