1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use chrono::DateTime;
use chrono::Utc;
use url::Url;

use std::borrow::Cow;

type Time = DateTime<Utc>;

pub struct NegotiationParameter<'a> {
    pub client_id: Cow<'a, str>,
    pub redirect_url: Cow<'a, Url>,
    pub scope: Option<Cow<'a, Scope>>,
}

pub struct Negotiated<'a> {
    pub client_id: Cow<'a, str>,
    pub scope: Cow<'a, Scope>,
    pub redirect_url: Url,
}

pub struct Request<'a> {
    pub owner_id: &'a str,
    pub client_id: &'a str,
    pub redirect_url: &'a Url,
    pub scope: &'a Scope,
}

pub struct Grant<'a> {
    pub owner_id: Cow<'a, str>,
    pub client_id: Cow<'a, str>,
    pub redirect_url: Cow<'a, Url>,
    pub scope: Cow<'a, Scope>,
    pub until: Cow<'a, Time>,
}

#[derive(Clone, Debug)]
pub struct IssuedToken {
    pub token: String,
    pub refresh: String,
    pub until: Time,
}

pub enum RegistrarError {
    Unregistered,
    MismatchedRedirect,
    Error(error::AuthorizationError),
}

/// Registrars provie a way to interact with clients.
///
/// Most importantly, they determine defaulted parameters for a request as well as the validity
/// of provided parameters. In general, implementations of this trait will probably offer an
/// interface for registering new clients. This interface is not covered by this library.
pub trait Registrar {
    /// Determine the allowed scope and redirection url for the client. The registrar may override
    /// the scope entirely or simply substitute a default scope in case none is given. Redirection
    /// urls should be matched verbatim, not partially.
    fn negotiate<'a>(&self, NegotiationParameter<'a>) -> Result<Cow<'a, Scope>, RegistrarError>;
}

/// Authorizers create and manage authorization codes.
///
/// The authorization code can be traded for a bearer token at the token endpoint.
pub trait Authorizer {
    /// Create a code which allows retrieval of a bearer token at a later time.
    fn authorize(&mut self, Request) -> String;
    /// Retrieve the parameters associated with a token, invalidating the code in the process. In
    /// particular, a code should not be usable twice (there is no stateless implementation of an
    /// authorizer for this reason).
    fn extract<'a>(&mut self, &'a str) -> Option<Grant<'a>>;
}

/// Issuers create bearer tokens.
///
/// It's the issuers decision whether a refresh token is offered or not. In any case, it is also
/// responsible for determining the validity and parameters of any possible token string. Some
/// backends or frontends may decide not to propagate the refresh token (for example because
/// they do not intend to offer a statefull refresh api).
pub trait Issuer {
    /// Create a token authorizing the request parameters
    fn issue(&mut self, Request) -> IssuedToken;
    /// Get the values corresponding to a bearer token
    fn recover_token<'a>(&'a self, &'a str) -> Option<Grant<'a>>;
    /// Get the values corresponding to a refresh token
    fn recover_refresh<'a>(&'a self, &'a str) -> Option<Grant<'a>>;
}

/// Generic token for a specific grant.
///
/// The interface may be reused for authentication codes, bearer tokens and refresh tokens.
pub trait TokenGenerator {
    /// For example sign a grant or generate a random token. The exact guarantees and uses depend
    /// on the specific implementation.
    fn generate(&self, &Grant) -> String;
}

pub mod authorizer;
pub mod backend;
pub mod error;
pub mod frontend;
pub mod generator;
pub mod issuer;
pub mod registrar;
mod scope;

#[cfg(test)]
mod tests;

pub use self::scope::Scope;

pub mod prelude {
    pub use super::authorizer::Storage;
    pub use super::backend::{CodeRef, IssuerRef, GuardRef};
    pub use super::issuer::{TokenMap, TokenSigner};
    pub use super::generator::RandomGenerator;
    pub use super::registrar::ClientMap;
    pub use super::scope::Scope;
}