Skip to main content

AuthnError

Enum AuthnError 

Source
pub enum AuthnError<E: Error + Send + Sync + 'static> {
    Store(E),
    NoFlow,
    NotActive(EntityState),
    Locked {
        until: Option<DateTime<Utc>>,
    },
    InvalidAssertion,
    ExternalService(String),
    CrossTenant,
}
Expand description

Errors that can occur during authentication flows.

Parameterised over the backend error type E so that storage errors are propagated with their original type rather than being erased.

§Suggested HTTP status code mapping

VariantHTTP StatusRationale
Store500 Internal Server ErrorBackend / database failure; not the client’s fault.
NoFlow409 ConflictNo active authentication flow in the session; client must start one first.
NotActive403 ForbiddenAccount exists but is disabled, suspended, or otherwise ineligible.
Locked423 LockedAccount locked due to too many failed attempts; retry after cooldown.
InvalidAssertion401 UnauthorizedFIDO2 cryptographic validation failed; credential rejected.
ExternalService502 Bad GatewayUpstream provider (LDAP, OAuth IdP) returned an error or timed out.

These are suggestions for handler authors. The library does not convert errors to HTTP responses automatically; that mapping belongs in your application’s error-handling layer.

Variants§

§

Store(E)

An error from the underlying identity or factor store.

§

NoFlow

No active authentication flow found in the session.

Returned by verify_factor when the session is not in Authenticating state.

§

NotActive(EntityState)

The account exists but is not in a state that permits login.

§

Locked

The account is locked (suspension or accumulated failed attempts).

Returned by:

  • prepare_factor when account_status reports Suspended.
  • FIDO2 finish_discoverable_login when the lockout threshold is reached during a discoverable assertion’s failure path.

until is the suspension expiry when known (for Suspended accounts whose StatusDetail.until is set), None for indefinite locks or for the failed-attempt lockout (which has no inherent expiry: an admin must reset). Use lockout_expiry for one-call access that also handles the legacy NotActive(EntityState::Suspended(_)) case.

Callers should display a generic “account locked” message (rendering until if present and non-trivial) rather than distinguishing failed-attempt vs admin-suspension reasons; that distinction is operator-visible via the audit log, never a property of the error response.

Fields

§until: Option<DateTime<Utc>>

Wall-clock expiry of the lock, when known.

§

InvalidAssertion

A FIDO2/WebAuthn assertion or registration failed validation.

Distinct from NoFlow (no ceremony in progress): this means a ceremony was in progress but the cryptographic validation failed.

§

ExternalService(String)

An external service (LDAP, OAuth IdP, etc.) failed with a non-credential error (connection timeout, network issue, etc.).

Callers should treat this as a transient failure and may retry or show a “service unavailable” message, not “invalid credentials”.

§

CrossTenant

A tenant-scoped operation was invoked against a target whose tenant_id does not match the caller-supplied expected tenant.

Returned by the _in_tenant family of methods on AuthnService (e.g. suspend_user_in_tenant, activate_user_in_tenant, begin_impersonation_in_tenant) when the structural rail fires. Suggested HTTP status: 403 Forbidden (the caller is authenticated but operating outside their authorised scope).

Treat audit logging of this variant as security-relevant; it almost always indicates either a buggy admin UI or an attempted cross-tenant pivot.

Implementations§

Source§

impl<E: Error + Send + Sync + 'static> AuthnError<E>

Source

pub fn lockout_expiry(&self) -> Option<DateTime<Utc>>

Return the lockout expiry timestamp when this error represents a locked account, regardless of whether the lock surfaces as AuthnError::Locked or as AuthnError::NotActive(EntityState::Suspended(_)).

Returns None for indefinite locks, for failed-attempt lockouts (which have no inherent expiry), and for any non-lock error variant. Use this from UI code that wants to render “try again at X” without distinguishing the two error shapes: both a prepare_factor Suspended-account rejection and a FIDO2 discoverable-login lockout collapse to a single Option<DateTime<Utc>> lookup.

Saves callers from deep-pattern-matching EntityState::Suspended(StatusDetail { until, .. }) and handling the AuthnError::Locked { until } shape separately; both legs collapse to one call.

Source§

impl<E: Error + Send + Sync + 'static> AuthnError<E>

Default IntoResponse mapping for AuthnError.

Gated behind the default-error-response feature because mapping a library error to an HTTP response is policy that belongs to the application: status code, body shape, locale, correlation IDs, and problem+json formatting are all things callers may want to override. The doc table on AuthnError documents the recommended mapping for applications that ship their own impl.

Enable with axess-core = { features = ["default-error-response"] } to get the conservative default below.

Source

pub fn into_response_at(self, now: DateTime<Utc>) -> Response

Available on crate feature default-error-response only.

IntoResponse-shaped conversion taking the reference time explicitly. Test code with MockClock uses this to pin the Retry-After header against a controllable clock; the trait impl below delegates here with Utc::now() for production callers, which produces wall-clock behaviour that’s correct but non-deterministic across runs.

Adopters who don’t enable the default-error-response feature can still construct their own IntoResponse impl on top of this helper without forking the body/status logic.

Trait Implementations§

Source§

impl<E: Debug + Error + Send + Sync + 'static> Debug for AuthnError<E>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<E> Display for AuthnError<E>
where E: Display + Error + Send + Sync + 'static,

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<E> Error for AuthnError<E>
where E: Error + 'static + Error + Send + Sync, Self: Debug + Display,

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl<E: Error + Send + Sync + 'static> IntoResponse for AuthnError<E>

Available on crate feature default-error-response only.
Source§

fn into_response(self) -> Response

Delegates to AuthnError::into_response_at with chrono::Utc::now() as the reference time. Production-correct but non-deterministic; tests asserting on Retry-After should call into_response_at directly with a MockClock-derived timestamp.

Auto Trait Implementations§

§

impl<E> Freeze for AuthnError<E>
where E: Freeze,

§

impl<E> RefUnwindSafe for AuthnError<E>
where E: RefUnwindSafe,

§

impl<E> Send for AuthnError<E>

§

impl<E> Sync for AuthnError<E>

§

impl<E> Unpin for AuthnError<E>
where E: Unpin,

§

impl<E> UnsafeUnpin for AuthnError<E>
where E: UnsafeUnpin,

§

impl<E> UnwindSafe for AuthnError<E>
where E: UnwindSafe,

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> ToSmolStr for T
where T: Display + ?Sized,

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> ToStringFallible for T
where T: Display,

Source§

fn try_to_string(&self) -> Result<String, TryReserveError>

ToString::to_string, but without panic on OOM.

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