Skip to content

Commit

Permalink
Invalidate cached sessions on logout
Browse files Browse the repository at this point in the history
This is not strictly necessary and it won't do the right thing when
running in Azure Functions (because we don't know how many frontends
the runtime will spawn and we cannot reliably do cache invalidation
across them all), but it's still the right thing to do.  After all,
consumers of this code could run in a single server, and in that
case we would want this to happen.
  • Loading branch information
jmmv committed Sep 3, 2023
1 parent 05f3db4 commit d4dbd1b
Showing 1 changed file with 39 additions and 0 deletions.
39 changes: 39 additions & 0 deletions authn/src/driver/logout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ impl AuthnDriver {
db::delete_session(tx.ex(), session, now).await?;

tx.commit().await?;

// Removing the session from the cache is only a best-effort operation. If we end up with
// multiple instances of a frontend running at once, there is no easy way to perform cache
// invalidation across all of them. But we don't know how this code is consumed (maybe it
// is part of a single-instance server instead of a lambda-style deployment), so let's try
// to do the right thing.
let mut cache = self.sessions_cache.lock().await;
let _previous = cache.remove(&token);

Ok(())
}
}
Expand All @@ -44,6 +53,7 @@ mod tests {
use crate::driver::testutils::*;
use crate::driver::AuthnOptions;
use iii_iv_core::db::DbError;
use std::time::Duration;

#[tokio::test]
async fn test_ok() {
Expand Down Expand Up @@ -88,4 +98,33 @@ mod tests {

assert_eq!(err1, err2);
}

#[tokio::test]
async fn test_remove_from_sessions_cache() {
// Configure a cache with just one entry and "infinite" duration so that we can precisely
// control when entries get evicted.
let opts = AuthnOptions {
sessions_cache_capacity: 1,
sessions_cache_ttl: Duration::from_secs(900),
..Default::default()
};
let context = TestContext::setup(opts).await;

let username = Username::from("test");

assert_eq!(0, context.driver().sessions_cache.lock().await.len());
let token = context.do_test_login(username.clone()).await;

let mut tx = context.db().begin().await.unwrap();
let _user = context
.driver()
.get_session(&mut tx, context.driver().now_utc(), token.clone())
.await
.unwrap();
tx.commit().await.unwrap();
assert_eq!(1, context.driver().sessions_cache.lock().await.len());

context.driver().logout(token.clone(), username).await.unwrap();
assert_eq!(0, context.driver().sessions_cache.lock().await.len());
}
}

0 comments on commit d4dbd1b

Please sign in to comment.