spiral-auth 0.1.12

Spiral credentials: bearer tokens and the providers that obtain them
Documentation
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};

/// Authenticates a workload with its Modal identity token, as a JWT-bearer grant at the
/// authorization server.
///
/// Modal puts one token in the environment rather than issuing tokens for a requested
/// audience, so its audience is always Modal's own. The workload's trust policy for Modal
/// accepts that audience explicitly.
#[derive(Debug)]
pub struct ModalAuthProvider {
    client: Client,
    token_endpoint: Url,
    workload_id: String,
}

impl ModalAuthProvider {
    /// Obtain the workload's tokens at `token_endpoint`, the authorization server's.
    pub fn new(client: impl Into<Client>, token_endpoint: Url, workload_id: String) -> Self {
        ModalAuthProvider {
            client: client.into(),
            token_endpoint,
            workload_id,
        }
    }
}

impl ModalAuthProvider {
    /// A usable token, or `None` when this provider has no credentials to offer.
    pub async fn token(&self) -> CredentialResult<Option<Token>> {
        let Some(modal_token) = env::var("MODAL_IDENTITY_TOKEN").ok() else {
            return Ok(None);
        };

        let token = jwt_bearer(
            &self.client,
            &self.token_endpoint,
            self.workload_id.clone(),
            modal_token,
            None,
        )
        .await?;

        debug!("ModalAuthProvider obtained a workload token");
        Ok(Some(token))
    }
}

impl_token_source!(ModalAuthProvider);