Skip to main content

AuthSession

Struct AuthSession 

Source
pub struct AuthSession(/* private fields */);
Expand description

Axum request extractor providing typed, mutable session access.

Zero generic parameters: wraps the SessionHandle inserted by SessionLayer. Obtain one in a handler by listing it as a parameter:

async fn my_handler(session: AuthSession) -> impl IntoResponse { ... }

Changes are committed to the store automatically when the response is sent.

Implementations§

Source§

impl AuthSession

Source

pub async fn is_authenticated(&self) -> bool

Return true if the session is fully authenticated.

Source

pub async fn auth_state(&self) -> AuthState

Clone the current authentication state enum (cheap; fields are Arc<str>).

Source

pub async fn authenticating_state( &self, ) -> Option<(UserId, TenantId, Vec<FactorKind>)>

Destructure an AuthState::Authenticating session into its (user_id, tenant_id, remaining_factors) triple. Returns None for any other AuthState variant (Guest / Identifying / Authenticated / PendingWorkflow).

Service-side callers in the multi-factor pipeline (begin_login, prepare_factor, verify_factor) all need this triple to make progress and treat any other state as the canonical AuthnError::NoFlow, typically session.authenticating_state().await.ok_or(AuthnError::NoFlow)?. This destructuring was lifted out of AuthnService because it has no service dependency; it belongs alongside the other session-state accessors here.

Single-acquisition: the read lock is taken once and the entire triple is built under it, matching snapshot’s shape rather than the older “auth_state().await then match” pattern that incurred two lock acquisitions and an extra AuthState::clone.

Source

pub async fn session_id(&self) -> SessionId

Return the session ID.

Source

pub async fn device_id(&self) -> Option<DeviceId>

Return the resolved crate::authn::ids::DeviceId for this session, if the device subsystem populated it. None when the device feature is disabled, when the resolver did not run for this request, or when the request did not match a known device.

Single-acquisition read; cheap when the device subsystem is in use because DeviceId is a 16-byte Copy UUID newtype.

Source

pub async fn data(&self) -> SessionData

Return a clone of the full session data.

Source

pub async fn with_auth_state<F, T>(&self, f: F) -> T
where F: FnOnce(&AuthState) -> T,

Invoke f against a borrow of the current AuthState without cloning. Use this when the caller only needs to read a few fields. Avoids the full AuthState::clone() that auth_state performs (which clones every Arc<str> plus the workflow state). For AuthState::Authenticated in particular this halves the per-request lock-held work in authenticated handlers that just need the user id.

The closure runs while the session read lock is held, so do not await inside it on something that needs the same lock.

Source

pub async fn with_data<F, T>(&self, f: F) -> T
where F: FnOnce(&SessionData) -> T,

Invoke f against a borrow of the full SessionData without cloning. Useful when reading several fields together, where data() would copy more than necessary. Same lock-held caveat as with_auth_state.

Source

pub async fn snapshot(&self) -> Option<AuthSnapshot>

Read all the common identity fields under a single read-lock acquisition. The previous pattern of calling is_authenticated() then user_id() then tenant_id() then session_id() from a typical authenticated handler took four RwLock reads per request: most contention-free, but each is a cross-await synchronization point. snapshot() collapses them into one acquisition.

Returns None when the session is not authenticated.

Source

pub async fn set_authenticated( &self, user_id: UserId, tenant_id: TenantId, authn_time: DateTime<Utc>, )

Mark the session as fully authenticated.

Cycles the session id eagerly so handler code that subsequently calls session.session_id().await (e.g. to register against a SessionRegistry) reads the post-rotation id, the same id the cookie will carry on the next request.

Source

pub async fn set_identifying(&self, user_id: UserId, tenant_id: TenantId)

Enter the identifying state (user has typed their username).

Binds the session fingerprint early so that even pre-MFA sessions are protected against cross-device replay.

Source

pub async fn set_pending_workflow( &self, user_id: UserId, tenant_id: TenantId, workflow: WorkflowState, )

Transition to a pending workflow state.

Source

pub async fn clear(&self)

Clear the session (logout). Resets state to Guest and marks as modified.

The caller should regenerate the session ID separately to prevent session fixation.

Source

pub async fn regenerate(&self)

Cycle the session ID immediately.

Mints a new id, swaps it in, and stashes the old id for the layer to store.cycle on the way out. Idempotent within a single request; calling twice still rotates only once.

Call at any privilege boundary; i.e. any change to the session’s authentication context, scope, or subject identity. Login is already auto-cycled; the rest is the app’s call. Canonical list (OWASP ASVS V3, OWASP Session Management Cheat Sheet, NIST SP 800-63B AAL transitions):

  • MFA factor added (TOTP, WebAuthn, recovery codes, …)
  • MFA factor removed or disabled (AAL drops)
  • Password / primary-credential change
  • Step-up to a higher assurance level
  • Account-recovery flow completion
  • Impersonation start / stop
  • Role grant / revoke or scope change
  • Tenant switch in a multi-tenant deployment

Do not call on routine writes (profile edit, factor config tuning, theme change); rotating churns the cookie and the store without any security benefit.

On credential changes (password change, recovery completion) consider also revoking sibling sessions via SessionRegistry::revoke_user_sessions; that is a strictly stronger statement than rotation and cuts off other devices still holding a stale credential-derived cookie.

See docs/sessions/lifecycle.md for the full rationale and the “library can’t hook this for you” discussion.

Source

pub async fn get_custom(&self, key: &str) -> Option<Value>

Read a value from the custom JSON bag.

Source

pub async fn clear_custom(&self)

Wipe the entire custom JSON bag in one shot. Used at privilege boundaries (e.g., admin impersonation) where the previous session’s app-controlled custom data must not leak into the assumed identity: pre-seeded OAuth ceremony state in custom could otherwise be used to hijack a subsequent OAuth flow under the new principal.

Source

pub async fn remove_custom(&self, key: &str) -> bool

Remove a key from the custom JSON bag. Returns true if a key was removed. Use this rather than set_custom(k, Value::Null) so the JSON object stays compact; repeated nulled-out keys would otherwise monotonically grow until the size cap clears the whole bag.

Source

pub async fn mutate_custom<F, T>(&self, f: F) -> T
where F: FnOnce(&mut Map<String, Value>) -> T,

Run f against a mutable borrow of the custom-bag JSON object under a single write-lock acquisition. Returns the value produced by f. Marks the session modified if f actually mutated the bag (judged by JSON-byte-length comparison).

Use this in place of a series of remove_custom/set_custom calls when several edits must appear atomic to a concurrent reader. The original sequence in clear_oauth_state issued six independent remove_custom calls; a parallel set_custom racing in between could re-introduce a key after it had already been removed.

f runs while the write lock is held; do not await inside it on something that needs the same lock.

Source

pub async fn take_custom(&self, key: &str) -> Option<Value>

Atomically read and remove a key from the custom JSON bag.

Returns the removed value, or None if the key was absent. The read and the remove run under a single write lock; use this in preference to get_custom(k).await followed by remove_custom(k) for any one-shot ceremony state (FIDO2 auth_state, OAuth PKCE verifier, password-reset token, etc.) where two parallel requests must not both observe the same value.

Source

pub async fn set_custom(&self, key: impl Into<String>, value: Value) -> bool

Store a value in the custom JSON bag.

Returns false if the write would exceed the configured max_custom_bytes limit; the value is not stored in that case.

Trait Implementations§

Source§

impl AuthSessionTestExt for AuthSession

Available on crate features testing only.
Source§

async fn set_authenticated( &self, user_id: UserId, tenant_id: TenantId, authn_time: DateTime<Utc>, )

Force the session into AuthState::Authenticated.
Source§

async fn begin_authenticating( &self, user_id: UserId, tenant_id: TenantId, method_name: Arc<str>, factors: Vec<FactorKind>, )

Force the session into AuthState::Authenticating with the given factor sequence.
Source§

async fn advance_factor(&self, kind: &FactorKind, authn_time: DateTime<Utc>)

Drive one factor-pipeline step from the test side, advancing the in-session remaining queue and transitioning to AuthState::Authenticated when empty.
Source§

async fn record_attempt_at(&self, now: DateTime<Utc>)

Stamp a failed-attempt timestamp on the session without touching the persistent lockout counter; mirrors what the factor pipeline does on credential mismatch, but addressable from a unit test.
Source§

impl Clone for AuthSession

Source§

fn clone(&self) -> AuthSession

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<S> FromRequestParts<S> for AuthSession
where S: Send + Sync,

Source§

type Rejection = SessionMissing

If the extractor fails it’ll use this “rejection” type. A rejection is a kind of error that can be converted into a response.
Source§

async fn from_request_parts( parts: &mut Parts, _state: &S, ) -> Result<Self, Self::Rejection>

Perform the extraction.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<S, T> FromRequest<S, ViaParts> for T
where S: Send + Sync, T: FromRequestParts<S>,

Source§

type Rejection = <T as FromRequestParts<S>>::Rejection

If the extractor fails it’ll use this “rejection” type. A rejection is a kind of error that can be converted into a response.
Source§

fn from_request( req: Request<Body>, state: &S, ) -> impl Future<Output = Result<T, <T as FromRequest<S, ViaParts>>::Rejection>>

Perform the extraction.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more