#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]
mod extractor;
mod jwks;
mod port;
mod verify;
pub use extractor::{AuthState, Authenticated, UNAUTHENTICATED};
pub use jwks::{AuthClient, JwksCache};
pub use verify::{Claims, VerifyError, token_fingerprint};
pub const ALGORITHM: &str = "ES256";
pub const JWKS_TTL_SECS: i64 = 3600;
pub const JWKS_MIN_REFETCH_SECS: i64 = 60;
pub const LEEWAY_SECS: i64 = 60;
#[must_use]
pub fn from_config(
config: &dyn cratefield_core::Config,
http: std::sync::Arc<dyn cratefield_core::HttpClient>,
clock: std::sync::Arc<dyn cratefield_core::Clock>,
) -> std::sync::Arc<dyn cratefield_core::Auth> {
let issuer = config.get("AUTH_ISSUER").filter(|v| !v.is_empty());
let client_id = config.get("AUTH_CLIENT_ID").filter(|v| !v.is_empty());
match (issuer, client_id) {
(Some(issuer), Some(client_id)) => {
std::sync::Arc::new(jwks::AuthClient::new(http, clock, issuer, client_id))
}
(issuer, client_id) => {
let mut missing = Vec::new();
if issuer.is_none() {
missing.push("AUTH_ISSUER");
}
if client_id.is_none() {
missing.push("AUTH_CLIENT_ID");
}
let why = format!(
"this deployment cannot identify a caller: {} is not set",
missing.join(" and ")
);
tracing::warn!(missing = %missing.join(","), "{why}");
std::sync::Arc::new(cratefield_core::Unconfigured::new(why))
}
}
}