use std::fmt;
#[derive(Debug)]
#[non_exhaustive]
pub enum VerifyError {
MalformedToken,
AlgorithmNotAllowed,
UnknownKey,
InvalidKey,
SignatureInvalid,
IssuerMismatch,
AudienceMismatch,
AuthorizedPartyMismatch,
AuthorizedPartyMissing,
Expired,
ImmatureToken,
NonceMismatch,
JwksUnavailable,
InvalidToken,
}
impl fmt::Display for VerifyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
VerifyError::MalformedToken => f.write_str("malformed ID token"),
VerifyError::AlgorithmNotAllowed => {
f.write_str("ID token signing algorithm is not allowed")
}
VerifyError::UnknownKey => f.write_str("no JWKS key matches the ID token"),
VerifyError::InvalidKey => f.write_str("JWKS key could not be used for verification"),
VerifyError::SignatureInvalid => f.write_str("ID token signature is invalid"),
VerifyError::IssuerMismatch => f.write_str("ID token issuer does not match"),
VerifyError::AudienceMismatch => f.write_str("ID token audience does not match"),
VerifyError::AuthorizedPartyMismatch => {
f.write_str("ID token authorized party (azp) does not match")
}
VerifyError::AuthorizedPartyMissing => {
f.write_str("ID token has multiple audiences but no authorized party (azp)")
}
VerifyError::Expired => f.write_str("ID token has expired"),
VerifyError::ImmatureToken => f.write_str("ID token is not yet valid"),
VerifyError::NonceMismatch => f.write_str("ID token nonce does not match"),
VerifyError::JwksUnavailable => f.write_str("could not fetch the provider's JWKS"),
VerifyError::InvalidToken => f.write_str("ID token failed verification"),
}
}
}
impl std::error::Error for VerifyError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum DiscoveryError {
InvalidIssuerUrl(url::ParseError),
Http(axum_security_oauth2::HttpError),
Status(u16),
Parse(serde_json::Error),
IssuerMismatch,
}
impl std::fmt::Display for DiscoveryError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DiscoveryError::InvalidIssuerUrl(e) => write!(f, "invalid issuer URL: {e}"),
DiscoveryError::Http(e) => write!(f, "discovery request failed: {e}"),
DiscoveryError::Status(status) => {
write!(f, "discovery endpoint returned status {status}")
}
DiscoveryError::Parse(e) => write!(f, "could not parse provider metadata: {e}"),
DiscoveryError::IssuerMismatch => {
f.write_str("provider metadata issuer does not match the requested issuer")
}
}
}
}
impl std::error::Error for DiscoveryError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
DiscoveryError::InvalidIssuerUrl(e) => Some(e),
DiscoveryError::Http(e) => Some(e),
DiscoveryError::Parse(e) => Some(e),
DiscoveryError::Status(_) | DiscoveryError::IssuerMismatch => None,
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum OidcError {
Exchange(axum_security_oauth2::Error),
NoIdToken,
Verify(VerifyError),
}
impl fmt::Display for OidcError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
OidcError::Exchange(e) => write!(f, "authorization code exchange failed: {e}"),
OidcError::NoIdToken => f.write_str("token response contained no id_token"),
OidcError::Verify(e) => write!(f, "ID token verification failed: {e}"),
}
}
}
impl std::error::Error for OidcError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
OidcError::Exchange(e) => Some(e),
OidcError::Verify(e) => Some(e),
OidcError::NoIdToken => None,
}
}
}
#[derive(Debug)]
pub enum ClaimsError {
Deserialize(serde_json::Error),
}
impl fmt::Display for ClaimsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ClaimsError::Deserialize(e) => write!(f, "could not deserialize ID token claims: {e}"),
}
}
}
impl std::error::Error for ClaimsError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ClaimsError::Deserialize(e) => Some(e),
}
}
}