| Crates.io | tower-sessions-cookie-store |
| lib.rs | tower-sessions-cookie-store |
| version | 0.5.2 |
| created_at | 2025-12-18 20:33:06.848368+00 |
| updated_at | 2025-12-18 20:44:13.188117+00 |
| description | Cookie-backed session store for tower-sessions (signed/private cookies via tower-cookies) |
| homepage | https://github.com/benwilber/tower-sessions-cookie-store |
| repository | https://github.com/benwilber/tower-sessions-cookie-store |
| max_upload_size | |
| id | 1993414 |
| size | 128,778 |
Cookie-backed session persistence for tower-sessions.
This crate provides CookieSessionManagerLayer, a Tower layer for cookie-backed sessions. It
integrates with tower-sessions and works with Axum extractors.
cargo add tower-sessions-cookie-store
signed (default): integrity-protected cookies (tamper-evident). Cookie contents are readable by
the client. Provided by cookie.private: encrypted + authenticated cookies (confidentiality + integrity). Provided by
cookie.key-expansion: enables Key::derive_from() for deriving a cookie Key from a 32-byte master
key. Requires signed and/or private. Provided by
cookie.dangerous-plaintext: plaintext cookies (no integrity, no confidentiality). Intended only for
testing/debugging.For more usage examples, see the examples/ directory.
use axum::{routing::get, Router};
use tower_sessions_cookie_store::{CookieSessionConfig, CookieSessionManagerLayer, Key, Session};
async fn handler(session: Session) -> String {
let n: usize = session.get("n").await.expect("session get succeeds").unwrap_or(0);
session.insert("n", n + 1).await.expect("session insert succeeds");
format!("n={n}")
}
let secret_key = Key::generate(); // store this someplace safe
let config = CookieSessionConfig::default()
.with_secure(false); // set true in production (HTTPS)
let router = Router::new()
.route("/", get(handler))
.layer(CookieSessionManagerLayer::signed(secret_key).with_config(config));
CookieSessionConfig controls cookie attributes and session persistence behavior:
name (default: "session")http_only (default: true)same_site (default: SameSite::Strict)secure (default: true)path (default: "/")domain (default: none)expiry (default: none)
Expiry::OnSessionEnd: no Max-Age is setExpiry::OnInactivity(d): expiration is computed from the last time the session was modified
(reads do not count). If you need sliding expiry on every request, set always_save = true.Expiry::AtDateTime(t): Max-Age is set from the record expiry (absolute unless changed)always_save (default: false): when true, refreshes cookie/expiry on every request even if
the session is not modifiedmax_cookie_bytes (default: 4096): maximum encoded cookie value sizeclear_on_decode_error (default: true): clears invalid/expired/undecodable cookiesmax_cookie_bytes), the layer responds with 500 and does not emit Set-Cookie.clear_on_decode_error is true, a bad/expired/undecodable incoming cookie is actively
cleared so the client stops sending it.The cookie value encodes the full session record using a versioned, base64url-encoded JSON envelope. The format is an implementation detail and may change between releases.
For testing/debugging, the crate exposes tower_sessions_cookie_store::{encode_record, decode_record}.
dangerous-plaintext feature offers no tamper resistance. A client can trivially edit
the cookie to escalate privileges and impersonate other users (including staff/admin). Do not
enable or use it in real applications.max_cookie_bytes (default 4096) or failed to
encode/verify; the layer returns 500 and does not set a cookie.SameSite::None and secure = true (required by browsers). It is very unlikely that you actually want to do this. Use caution.secure = true so browsers only send the cookie over HTTPS. Only disable it locally
for development.config.with_http_only(false)) lets any
injected script read and exfiltrate the bearer token, enabling replay. Only do this if you have
a very specific, XSS-hardened reason.MIT. See LICENSE.