Skip to main content

tapis_core/
token.rs

1/// Contract for obtaining a fresh Tapis JWT.
2///
3/// Implement this trait on any type that knows how to produce or refresh a
4/// Tapis access token.  Pass an `Arc<dyn TokenProvider>` to a service-client
5/// constructor to enable automatic token refresh inside
6/// [`RefreshMiddleware`](../client/struct.RefreshMiddleware.html).
7///
8/// # No-circular-dependency guarantee
9///
10/// `tapis-core` has **zero** HTTP or service-client dependencies.
11/// `tapis-authenticator` implements `TokenProvider`; all other service crates
12/// depend on `tapis-core` only. This breaks the would-be cycle:
13///
14/// ```text
15/// tapis-jobs ──dep──> tapis-core <──impl── tapis-authenticator
16///                          ▲
17///                    (no dep on tapis-authenticator)
18/// ```
19///
20/// # Infinite-loop protection
21///
22/// `RefreshMiddleware` checks the outgoing URL before calling `get_token()`.
23/// If the URL contains `/oauth2/tokens` or `/v3/tokens` it skips refresh,
24/// mirroring the tapipy guard on `create_token` / `refresh_token` operations.
25///
26/// # Example
27///
28/// ```rust,no_run
29/// use std::sync::Arc;
30/// use tapis_core::TokenProvider;
31///
32/// struct StaticToken(String);
33///
34/// #[async_trait::async_trait]
35/// impl TokenProvider for StaticToken {
36///     async fn get_token(&self) -> Option<String> {
37///         Some(self.0.clone())
38///     }
39/// }
40///
41/// // Pass to any service client that accepts a TokenProvider.
42/// let provider: Arc<dyn TokenProvider> = Arc::new(StaticToken("my-jwt".into()));
43/// ```
44#[async_trait::async_trait]
45pub trait TokenProvider: Send + Sync {
46    /// Return a fresh JWT string, or `None` to leave the current token
47    /// on the request unchanged.
48    ///
49    /// Implementations should **not** panic. If the token cannot be obtained
50    /// (e.g., network error), return `None` so the request proceeds with the
51    /// stale token rather than crashing.
52    async fn get_token(&self) -> Option<String>;
53}