pub struct SessionLayer<S> { /* private fields */ }Expand description
Tower layer that provides signed session cookies and typed crate::session::SessionData.
Add this layer to your Axum router. Handlers receive an super::extractor::AuthSession extractor
which wraps the SessionHandle stored in request extensions.
let app = Router::new()
.route("/login", post(login_handler))
.layer(SessionLayer::new(store, signing_key));§Configuration
Cookie attributes and TTL are set via the with_* builder methods:
let layer = SessionLayer::new(store, key)
.with_ttl(Duration::from_secs(7200))
.with_secure(false)
.with_same_site(SameSite::Strict);Implementations§
Source§impl<S: SessionStore> SessionLayer<S>
impl<S: SessionStore> SessionLayer<S>
Sourcepub fn new(store: S, signing_key: [u8; 32]) -> Self
pub fn new(store: S, signing_key: [u8; 32]) -> Self
Create a session layer with the given store and 32-byte HMAC signing key.
Uses SessionConfig::default(): production-safe defaults (24-hour TTL,
Secure, HttpOnly, SameSite=Lax).
The signing key derives sub-keys via HKDF for cookie HMAC, fingerprint HMAC, and CSRF; keep it in a secret store and rotate per your key-management policy (a fresh layer is required on rotation since the derived keys are cached).
§Example
use axess_core::{MemorySessionStore, session::SessionLayer};
use std::time::Duration;
// Production: load the master key from a secret store (KMS, Vault, …).
// Below uses a fixed value purely for the construction example.
let signing_key: [u8; 32] = [0u8; 32];
let store = MemorySessionStore::default();
let layer = SessionLayer::new(store, signing_key)
.with_ttl(Duration::from_secs(3600))
.with_cookie_name("myapp.sid");
// Attach to your router:
// let app = axum::Router::new().layer(layer);Sourcepub fn derive_subkey(&self, info: &'static [u8]) -> Zeroizing<[u8; 32]>
pub fn derive_subkey(&self, info: &'static [u8]) -> Zeroizing<[u8; 32]>
Derive a 32-byte sub-key from this layer’s master signing
key using a caller-supplied info label. Use this to feed
CSRF token signing, push-notification HMAC, or any other HMAC
site that would otherwise be tempted to reuse the raw master
key. Pick a stable byte-string label per use site (e.g.
b"my-app.v1.csrf"); changing the label invalidates every
value previously derived under it.
The returned bytes are wrapped in zeroize::Zeroizing so they
are wiped on drop: a compromise of any derived sub-key with a
known label lets an attacker forge against that path, so the
material is held under the same drop discipline as the master
key. Deref through * or as_ref() to access the raw [u8; 32].
Override the cookie name (default: "axess.sid").
Sourcepub fn with_secure(self, secure: bool) -> Self
pub fn with_secure(self, secure: bool) -> Self
Set the Secure flag on the session cookie (default: true).
Set to false only for local HTTP development. In production,
cookies without the Secure flag can be intercepted on the network.
Sourcepub fn with_same_site(self, same_site: SameSite) -> Self
pub fn with_same_site(self, same_site: SameSite) -> Self
Set the SameSite policy (default: Lax).
Sourcepub fn with_http_only(self, http_only: bool) -> Self
pub fn with_http_only(self, http_only: bool) -> Self
Set the HttpOnly flag on the session cookie (default: true).
Sourcepub fn with_max_custom_bytes(self, max: usize) -> Self
pub fn with_max_custom_bytes(self, max: usize) -> Self
Override the maximum size (in bytes) of the JSON-encoded
custom-data payload. Default: 64 KiB. Set to 0 to disable
the clamp entirely (do this only if you have your own size
guarding upstream of the session layer).
When the clamp fires, the offending custom payload is
dropped to Value::Null and a tracing::warn! is emitted;
the session itself is preserved.
Sourcepub fn with_path(self, path: impl Into<Arc<str>>) -> Self
pub fn with_path(self, path: impl Into<Arc<str>>) -> Self
Set the cookie Path attribute (default: "/").
Sourcepub fn with_binding(self, binding: impl SessionBinding) -> Self
pub fn with_binding(self, binding: impl SessionBinding) -> Self
Enable session-to-client binding for hijacking detection.
When enabled, the library hashes client-specific request properties
(determined by the SessionBinding implementation) and stores the
hash in the session upon authentication. On every subsequent request
the hash is recomputed and compared; a mismatch resets the session
to Guest (the cookie may have been stolen by a different client).
use axess::session::UserAgentBinding;
let layer = SessionLayer::new(store, key)
.with_binding(UserAgentBinding);Sourcepub fn with_metrics(self, metrics: impl AuthnMetrics) -> Self
pub fn with_metrics(self, metrics: impl AuthnMetrics) -> Self
Attach a metrics hook for session-level observability.
Sourcepub fn with_device_resolver<R>(self, resolver: R) -> Selfwhere
R: DeviceResolver,
Available on crate feature device only.
pub fn with_device_resolver<R>(self, resolver: R) -> Selfwhere
R: DeviceResolver,
device only.Configure a DeviceResolver to stamp
SessionData::device_id
on every request before the inner handler runs.
Errors returned by the resolver are logged via tracing::warn!
and treated as None; device resolution never fails the request.
When unset (the default), device_id stays at whatever the loaded
session carried, which for new sessions is None.
See docs/identity/device.md
for the full design.
Trait Implementations§
Source§impl<S: Clone> Clone for SessionLayer<S>
impl<S: Clone> Clone for SessionLayer<S>
Source§fn clone(&self) -> SessionLayer<S>
fn clone(&self) -> SessionLayer<S>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<S, Inner> Layer<Inner> for SessionLayer<S>where
S: SessionStore + Clone,
impl<S, Inner> Layer<Inner> for SessionLayer<S>where
S: SessionStore + Clone,
Auto Trait Implementations§
impl<S> Freeze for SessionLayer<S>where
S: Freeze,
impl<S> !RefUnwindSafe for SessionLayer<S>
impl<S> Send for SessionLayer<S>where
S: Send,
impl<S> Sync for SessionLayer<S>where
S: Sync,
impl<S> Unpin for SessionLayer<S>where
S: Unpin,
impl<S> UnsafeUnpin for SessionLayer<S>where
S: UnsafeUnpin,
impl<S> !UnwindSafe for SessionLayer<S>
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.