Enforce 30-day session expiry with lazy cleanup
Sessions never expired server-side despite the 30-day cookie Max-Age; repeat sign-ins orphaned rows. user_id now rejects tokens older than 30 days and deletes them on sight. Verified live: fresh 200, backdated 302 with row removed.
This commit is contained in:
parent
0f2a9743f2
commit
39332670be
1 changed files with 25 additions and 10 deletions
35
src/auth.rs
35
src/auth.rs
|
|
@ -100,17 +100,32 @@ pub async fn user_id(pool: &SqlitePool, h: &HeaderMap) -> Option<String> {
|
|||
}
|
||||
let token = token?;
|
||||
tracing::debug!("session token={token}");
|
||||
match sqlx::query_scalar::<_, String>("SELECT user_id FROM sessions WHERE token=?")
|
||||
.bind(token)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
{
|
||||
Ok(found) => {
|
||||
tracing::debug!("session lookup -> {:?}", found);
|
||||
found
|
||||
// Sessions live 30 days (matching the cookie Max-Age). Stale rows are
|
||||
// deleted on sight so repeat sign-ins don't orphan tokens forever.
|
||||
let row: Option<(String, String)> =
|
||||
sqlx::query_as("SELECT user_id, created_at FROM sessions WHERE token=?")
|
||||
.bind(token)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
.unwrap_or(None);
|
||||
match row {
|
||||
Some((uid, created)) => {
|
||||
let fresh = chrono::DateTime::parse_from_rfc3339(&created)
|
||||
.map(|t| (chrono::Utc::now() - t.with_timezone(&chrono::Utc)).num_days() < 30)
|
||||
.unwrap_or(false);
|
||||
if !fresh {
|
||||
sqlx::query("DELETE FROM sessions WHERE token=?")
|
||||
.bind(token)
|
||||
.execute(pool)
|
||||
.await
|
||||
.ok();
|
||||
return None;
|
||||
}
|
||||
tracing::debug!("session lookup -> {:?}", uid);
|
||||
Some(uid)
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("session lookup failed: {e}");
|
||||
None => {
|
||||
tracing::debug!("session lookup -> None");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue