diff options
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/login.rs | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/api/login.rs b/src/api/login.rs index 3b4ee32..31a5d7f 100644 --- a/src/api/login.rs +++ b/src/api/login.rs @@ -248,6 +248,9 @@ fn new_login( lifetime: Option<u64>, ) -> Claims { let session_exp = now.saturating_add(state.session_lifetime.as_millis() as u64); + let exp = now + .saturating_add(lifetime_ms(state, lifetime)) + .min(session_exp); Claims { v: 1, swarm, @@ -255,15 +258,23 @@ fn new_login( user: user.to_owned(), login: login.to_owned(), iat: now, - exp: now - .saturating_add(lifetime_ms(state, lifetime)) - .min(session_exp), + exp, session: token::new_session(), - session_exp, + session_exp: ended_with(session_exp, exp, lifetime), limit, } } +/// When a session ends, `session_exp` at the latest, for a token ending at `exp`: with +/// it, where it was asked to live less (`lifetime`). A token to hand over is refreshed +/// past its end by nobody, its holder included. +fn ended_with(session_exp: u64, exp: u64, lifetime: Option<u64>) -> u64 { + match lifetime { + Some(_) => session_exp.min(exp), + None => session_exp, + } +} + /// `POST /auth/challenge`: one to sign for a login by key, valid for five minutes. pub(crate) async fn challenge(State(state): State<AppState>) -> Result<Response, ApiError> { let (_, now) = issuing(&state).await?; @@ -426,14 +437,16 @@ async fn refreshed( Some(limit) } }; + let exp = now + .saturating_add(lifetime_ms(state, lifetime)) + .min(earlier.session_exp); let claims = Claims { v: 1, swarm, issuer: state.local_id().to_owned(), iat: now, - exp: now - .saturating_add(lifetime_ms(state, lifetime)) - .min(earlier.session_exp), + exp, + session_exp: ended_with(earlier.session_exp, exp, lifetime), limit, ..(**earlier).clone() }; @@ -534,4 +547,12 @@ mod tests { assert!(!within(&[cap(&["logs"], &["read"])], &earlier)); assert!(!within(&[cap(&["notes"], &["read", "grant"])], &earlier)); } + + /// A token asked to live less ends its session with it; another, the session goes on. + #[test] + fn a_short_token_ends_its_session() { + assert_eq!(ended_with(7_000, 300, Some(300)), 300); + assert_eq!(ended_with(7_000, 300, None), 7_000); + assert_eq!(ended_with(200, 300, Some(300)), 200); + } } |
