Skip to main content

faucet_stream/auth/
mod.rs

1//! Authentication strategies for REST APIs.
2
3pub mod api_key;
4pub mod basic;
5pub mod bearer;
6pub mod custom;
7pub mod oauth2;
8
9use crate::error::FaucetError;
10use reqwest::header::HeaderMap;
11
12/// Supported authentication methods.
13#[derive(Debug, Clone)]
14pub enum Auth {
15    None,
16    Bearer(String),
17    Basic {
18        username: String,
19        password: String,
20    },
21    /// API key sent in a request header.
22    ApiKey {
23        header: String,
24        value: String,
25    },
26    /// API key sent as a query parameter (e.g. `?api_key=secret`).
27    ///
28    /// Some APIs require the key in the URL rather than a header. The `param`
29    /// field is the query parameter name, and `value` is the key itself.
30    ApiKeyQuery {
31        param: String,
32        value: String,
33    },
34    OAuth2 {
35        token_url: String,
36        client_id: String,
37        client_secret: String,
38        scopes: Vec<String>,
39        /// Fraction of `expires_in` after which the cached token is considered
40        /// expired and a new one is fetched. Must be in `(0.0, 1.0]`.
41        /// Defaults to `0.9` (refresh after 90 % of the token lifetime).
42        expiry_ratio: f64,
43    },
44    Custom(HeaderMap),
45}
46
47impl Auth {
48    /// Apply header-based auth to the request headers.
49    ///
50    /// `ApiKeyQuery` is a no-op here — it is applied as a query parameter by
51    /// `RestStream::execute_request` instead.
52    pub fn apply(&self, headers: &mut HeaderMap) -> Result<(), FaucetError> {
53        match self {
54            Auth::None | Auth::ApiKeyQuery { .. } => Ok(()),
55            Auth::Bearer(token) => bearer::apply(headers, token),
56            Auth::Basic { username, password } => basic::apply(headers, username, password),
57            Auth::ApiKey { header, value } => api_key::apply(headers, header, value),
58            // OAuth2 is resolved to Auth::Bearer by RestStream before apply() is called.
59            // If apply() is reached with an OAuth2 variant, it means the caller bypassed
60            // RestStream — return a clear error rather than silently sending no auth.
61            Auth::OAuth2 { .. } => Err(FaucetError::Auth(
62                "OAuth2 auth must be resolved to a bearer token before applying; \
63                 use RestStream (which resolves it automatically) or call \
64                 fetch_oauth2_token() and use Auth::Bearer"
65                    .into(),
66            )),
67            Auth::Custom(h) => {
68                custom::apply(headers, h);
69                Ok(())
70            }
71        }
72    }
73}
74
75pub use oauth2::fetch_oauth2_token;