use std::env;
use std::fmt::Debug;
use reqwest_middleware::ClientWithMiddleware as Client;
use tracing::debug;
use url::Url;
use super::jwt_bearer;
use crate::{CredentialResult, Token, TokenSource};
#[derive(Debug)]
pub struct OidcAuthProvider {
client: Client,
token_endpoint: Url,
workload_id: String,
assertion_provider: Option<TokenSource>,
}
impl OidcAuthProvider {
pub fn new(client: impl Into<Client>, token_endpoint: Url, workload_id: String) -> Self {
OidcAuthProvider {
client: client.into(),
token_endpoint,
workload_id,
assertion_provider: None,
}
}
pub fn with_assertion_provider(mut self, source: TokenSource) -> Self {
self.assertion_provider = Some(source);
self
}
}
impl OidcAuthProvider {
pub async fn token(&self) -> CredentialResult<Option<Token>> {
let assertion = match &self.assertion_provider {
Some(provider) => provider
.token()
.await?
.map(|token| token.expose_secret().to_owned()),
None => env::var("SPIRAL_OIDC_PROVIDER_TOKEN").ok(),
};
let Some(oidc_token) = assertion else {
return Ok(None);
};
let token = jwt_bearer(
&self.client,
&self.token_endpoint,
self.workload_id.clone(),
oidc_token,
None,
)
.await?;
debug!("OidcAuthProvider obtained a workload token");
Ok(Some(token))
}
}
impl_token_source!(OidcAuthProvider);