aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/login.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 15:29:06 +0000
committertv <tv@krebsco.de>2026-11-09 18:15:56 +0100
commit62b2f880a1a209e396d3adaef6a38395298011c6 (patch)
tree2b3bb738755168096561f6dbc6e90f30e2573451 /src/api/login.rs
parentd7eaef8b94c13fb2da4c87e98dd2464a31b5c128 (diff)
access: an ended session recorded until the login's end
Review 4, F7: `DELETE /auth/session` recorded the session as ended until the `session_exp` of the token it came with. A token handed to another member's dashboard has its `session_exp` cut to its own end (five minutes), and so has the session that dashboard keeps with it: logging out there recorded an end minutes away, the next remake's snapshot left it out, and the original browser's tokens of the same session, refreshable for days, were taken again. A token now keeps the login's end as it logged in (`Claims::login_exp`), which no refresh changes, and an ended session is recorded until then (or the token's `session_exp`, if later, as for a token from before the field).
Diffstat (limited to 'src/api/login.rs')
-rw-r--r--src/api/login.rs6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/api/login.rs b/src/api/login.rs
index 57c1859..dc9d895 100644
--- a/src/api/login.rs
+++ b/src/api/login.rs
@@ -272,6 +272,7 @@ fn new_login(
exp,
session: token::new_session(),
session_exp: ended_with(session_exp, exp, lifetime),
+ login_exp: session_exp,
limit,
}
}
@@ -532,7 +533,10 @@ pub(crate) async fn end_session(
/// registry, else on this node only.
async fn end(state: &AppState, claims: &Claims, by: &str) -> Result<(), ApiError> {
let path = registry::session_path(&claims.user, &claims.session);
- let until = claims.session_exp;
+ // The login's end, not this token's refresh deadline (a token handed to another
+ // member's dashboard ends its session in minutes): every token of the session is
+ // refused until it.
+ let until = claims.login_exp.max(claims.session_exp);
let recorded = if state.is_ready().await {
state
.mutate_doc_for(Some(by.to_owned()), Sign::Protocol, move |doc| {