asap 0.14.0

An implementation of ASAP for rust.
Documentation
use std::result::Result as StdResult;

#[cfg(feature = "validator")]
use crate::jwt;

// A handy alias for `Result` that carries a generic error type.
pub type Result<T> = ::std::result::Result<T, anyhow::Error>;

// The `jsonwebtoken` lib uses the deprecated `error_chain` lib for its error
// handling. This is a small fix so that the `anyhow` lib plays nicely with
// the errors generated by `error_chain`.
//
// See: https://github.com/rust-lang-nursery/failure/issues/109
pub trait ResultExt<T, E> {
    fn sync(self) -> StdResult<T, anyhow::Error>
    where
        Self: Sized,
        E: ::std::error::Error + Send + 'static;
}

impl<T, E> ResultExt<T, E> for StdResult<T, E>
where
    E: Sync,
{
    fn sync(self) -> StdResult<T, anyhow::Error>
    where
        Self: Sized,
        E: ::std::error::Error + Send + 'static,
    {
        self.map_err(anyhow::Error::new)
    }
}

// The types of errors a Validator may encounter.
#[cfg(feature = "validator")]
#[derive(thiserror::Error, Debug)]
pub enum ValidatorError {
    #[error("JWT header did not contain a `kid` claim: {0:?}")]
    NoKIDFound(jwt::Header),

    #[error(
        "JWT header did not contain a valid `kid` claim. As per \
                   ASAP spec, the `kid` claim must start with \"$iss/\" where $iss is the \
                   issuer (kid: {0:?}, iss: {1:?})"
    )]
    InvalidKID(String, String),

    #[error("Received `None` when fetching from cache")]
    CacheError,

    #[error("Failed to retrieve public key from keyserver: {0:?}")]
    KeyserverError(String),

    #[error("Expired item: {0:?}")]
    ExpiredCache(String),

    #[error(
        "Token contained a lifespan greater than the `max_lifespan` \
                   (hard limit of 3600 seconds)"
    )]
    InvalidLifespan,

    #[error("Immature jwt signature, nbf: {0:?} exp: {1:?}")]
    ImmatureSignature(i64, i64),

    #[error("Expired jwt signature, nbf: {0:?} exp: {1:?}")]
    ExpiredSignature(i64, i64),

    #[error("Duplicate `jti` encountered: {0:?}")]
    DuplicateJTI(String),

    #[error("Required claim not found in token: {0:?}")]
    ClaimNotFound(String),

    #[error(
        "Resource server audience not found in `aud` claims of \
                   token {0:?}"
    )]
    UnrecognisedAudience(Vec<String>),

    #[error(
        "Unknown or unauthorized subject {0:?}. The `sub` claim \
                   (or `iss`) must exist in `whitelisted_issuers` {1:?}"
    )]
    UnauthorizedSubject(String, Vec<String>),
}