spiral_auth/providers/
oidc.rs1use std::env;
2use std::fmt::Debug;
3
4use reqwest_middleware::ClientWithMiddleware as Client;
5use tracing::debug;
6use url::Url;
7
8use super::jwt_bearer;
9use crate::{CredentialResult, Token, TokenSource};
10
11#[derive(Debug)]
15pub struct OidcAuthProvider {
16 client: Client,
17 token_endpoint: Url,
18 workload_id: String,
19 assertion_provider: Option<TokenSource>,
20}
21
22impl OidcAuthProvider {
23 pub fn new(client: impl Into<Client>, token_endpoint: Url, workload_id: String) -> Self {
25 OidcAuthProvider {
26 client: client.into(),
27 token_endpoint,
28 workload_id,
29 assertion_provider: None,
30 }
31 }
32 pub fn with_assertion_provider(mut self, source: TokenSource) -> Self {
35 self.assertion_provider = Some(source);
36 self
37 }
38}
39
40impl OidcAuthProvider {
41 pub async fn token(&self) -> CredentialResult<Option<Token>> {
43 let assertion = match &self.assertion_provider {
44 Some(provider) => provider
45 .token()
46 .await?
47 .map(|token| token.expose_secret().to_owned()),
48 None => env::var("SPIRAL_OIDC_PROVIDER_TOKEN").ok(),
49 };
50 let Some(oidc_token) = assertion else {
51 return Ok(None);
52 };
53
54 let token = jwt_bearer(
55 &self.client,
56 &self.token_endpoint,
57 self.workload_id.clone(),
58 oidc_token,
59 None,
60 )
61 .await?;
62
63 debug!("OidcAuthProvider obtained a workload token");
64 Ok(Some(token))
65 }
66}
67
68impl_token_source!(OidcAuthProvider);