Skip to main content

AuthError

Enum AuthError 

Source
pub enum AuthError {
Show 16 variants NonceMissing, NonceMismatch, NonceConfigEmpty, AtHashMissing, AtHashMismatch, CHashMissing, CHashMismatch, AzpMissing, AzpMismatch, AuthTimeMissing, AuthTimeStale, AcrMissing, AcrNotAllowed, UnknownClaim(String), CatMismatch(String), Jose(SharedAuthError),
}
Expand description

Verification errors specific to the OIDC id_token profile.

Shared JOSE errors (M01-M16a algorithm/header, M17-M30 registered claims) reach this enum via the Jose carrier variant — the engine submodules emit access_token::AuthError, the id_token verify entry re-wraps. This is a deliberate seam: it lets the id_token surface stay narrow (only profile-specific variants enumerated here) while reusing the JOSE checks structurally.

Variants§

§

NonceMissing

M66: nonce claim is absent from the id_token payload. RFC says nonce is conditionally required (only when the RP sent one in the Auth Request) — but the engine’s VerifyConfig::id_token constructor requires expected_nonce, so reaching this error means the RP requested nonce binding and the IdP failed to honor it. Treat as suspect: either an issuer drift or a token forged against an older VerifyConfig.

§

NonceMismatch

M66: payload nonce is present but does not match the expected_nonce the RP stored at the auth request boundary. Canonical replay-attack signal — the attacker is presenting an id_token issued for a different session.

§

NonceConfigEmpty

Nonce::new("") was called. Construction-time invariant guard; reaching this at runtime means consumer code violated the non-empty contract. Surfaced as a verification error rather than a panic so the consumer gets a structured rejection it can audit.

§

AtHashMissing

M67: at_hash claim absent from payload while the verifier was configured with an expected access_token binding (i.e. VerifyConfig::with_access_token_binding was called). RFC says at_hash is conditionally required (only when the response_type includes token — hybrid + implicit flows); reaching this error means the RP told the engine to expect at_hash and the IdP failed to honor it. Either issuer drift or a substitution attempt.

§

AtHashMismatch

M67: payload at_hash is present but does not match the SHA-256 leftmost-128b base64url of the access_token the RP supplied via with_access_token_binding. Canonical access-token-substitution signal: an attacker is presenting an id_token issued for a different access_token than the one the RP just received.

§

CHashMissing

M68: c_hash claim absent from payload while the verifier was configured with an expected authorization-code binding. Mirror of M67 for the authorization-code flow (OIDC Core §3.3.2.11) — fires only when with_authorization_code_binding was called.

§

CHashMismatch

M68: payload c_hash is present but does not match the SHA-256 leftmost-128b base64url of the authorization code the RP received at the redirect_uri. Canonical code-substitution signal: an attacker is presenting an id_token issued for a different code than the one the RP is about to exchange at the token endpoint.

§

AzpMissing

M69: azp (authorized party) claim absent while the id_token has multiple audiences. OIDC Core §2 SHOULD requires azp on multi-aud tokens; Phase 7 elevates to MUST. Reaching this error means the IdP issued a multi-aud id_token without naming the authorized party — either an issuer drift or a substitution attempt.

§

AzpMismatch

M69: payload azp is present but does not equal the RP’s client_id (sourced from cfg.shared.audience). Fires regardless of aud cardinality — §2 mandates the equality unconditionally when azp is present. Canonical client-substitution signal: the id_token was authorized for a sibling client and is being replayed against this RP.

§

AuthTimeMissing

M70: auth_time claim absent from payload while the verifier was configured with a max_age window. OIDC Core §3.1.3.7 says auth_time is REQUIRED when max_age was requested; reaching this error means the RP told the engine to gate freshness and the IdP failed to honor it — IdP misconfiguration. Operator response: investigate the IdP, not the user session.

§

AuthTimeStale

M70: now - auth_time > max_age. The user authenticated too long ago for this RP’s freshness policy. Distinct from AuthTimeMissing because the operator response differs: Stale = re-authenticate the user (force OIDC prompt=login); Missing = IdP misconfig.

§

AcrMissing

M71: acr claim absent from payload while the verifier was configured with acr_values. OIDC Core §3.1.3.7 SHOULD elevated to MUST per Phase 7 strictness — RPs that requested a specific authentication context refuse tokens that don’t assert one.

§

AcrNotAllowed

M71: payload acr is present but not in the RP’s acr_values allowlist. Canonical step-up bypass signal: the IdP authenticated the user at a weaker level than this RP requires for the requested operation. Comparison is case-sensitive (URN values are case-sensitive by spec); case-folding would silently admit downgrades.

§

UnknownClaim(String)

M72: id_token payload contains a claim outside the per-scope allowlist (S::names()). Structurally mirrors M45’s access_token::AuthError::UnknownClaim but is profile-aware: the permitted set is derived from the type-level scope witness S, so the same wire payload is accepted at Claims<EmailProfile> and refused at Claims<Openid>.

Strict-refuse from day 1 (β1): no leniency flag, no silent stripping. The carried name is the first offending claim — audit logs distinguish a forgery (backdoor) from issuer drift (email at Openid scope) by reading the variant payload. Operator response depends on the name: investigate IdP scope emission policy or refuse the consumer’s scope drift.

§

CatMismatch(String)

M29-mirror (Phase 10.10): id_token payload carries a cat claim whose value is not "id". Structurally mirrors access-token’s M29 TokenTypeMismatch (engine::check_claims::run line 137-140 — refuses anything other than cat="access"); closes the asymmetry where id_token::verify previously had no profile- routing assertion and relied on M72 BASE_CLAIMS-omission to implicitly forbid cat. With cat now in BASE_CLAIMS (so self-issued tokens round-trip via M72), the value gate moves to this dedicated check.

Carries the offending value so audit logs distinguish:

  • CatMismatch("access") — an attacker presenting an id_token with a forged cat to make it look like an access token (the substitution attack M73 also defends against from the other side).
  • CatMismatch("") — payload missing cat entirely, either issuer drift (a non-PAS OIDC IdP that doesn’t emit ppoppo’s profile-routing claim) or a stripped-claims forgery attempt.
  • CatMismatch("<other>") — bespoke forgery; the variant payload is itself the audit signal.
§

Jose(SharedAuthError)

JOSE wire-format error from the shared engine pipeline. Algorithm whitelist, header attack surface, serialization shape, and structural rejections (oversize, JWE, JSON-form) all surface here. RFC 9068-specific errors (M17-M30 registered claims, M35-M45) stay on access_token::AuthError and never reach this enum.

Trait Implementations§

Source§

impl Clone for AuthError

Source§

fn clone(&self) -> AuthError

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 Debug for AuthError

Source§

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

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

impl Display for AuthError

Source§

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

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

impl Error for AuthError

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 From<SharedAuthError> for AuthError

Source§

fn from(source: SharedAuthError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for AuthError

Source§

fn eq(&self, other: &AuthError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for AuthError

Source§

impl StructuralPartialEq for AuthError

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> 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> 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> 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> 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, 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