Skip to main content

AuthStrategy

Trait AuthStrategy 

Source
pub trait AuthStrategy: Send {
    // Required method
    fn get_token(
        self,
    ) -> impl Future<Output = Result<ServiceToken, AuthError>> + Send;
}
Expand description

A strategy for obtaining access tokens.

Implementations handle all details of authentication, token caching, and refresh. Callers just call get_token whenever they need a valid token.

The trait is designed to be implemented for &T, so that callers can use shared references (e.g. &OAuthStrategy) without consuming the strategy.

§Token refresh

All strategies that cache tokens (AccessKeyStrategy, OAuthStrategy, AutoStrategy) share the same internal refresh engine. Understanding the refresh model helps predict how get_token behaves under concurrent access.

§Expiry vs usability

A token has two time thresholds:

  • Expired — the token is within 90 seconds of its expires_at timestamp. This triggers a preemptive refresh attempt.
  • Usable — the token has not yet reached its expires_at timestamp. A token can be “expired” (in the preemptive sense) but still “usable” (the server will still accept it).

§Concurrent refresh strategies

The gap between “expired” and “unusable” enables two refresh modes:

  1. Expiring but still usable — The first caller triggers a background refresh. Concurrent callers receive the current (still-valid) token immediately without blocking.
  2. Fully expired — The first caller blocks while refreshing. Concurrent callers wait until the refresh completes, then all receive the new token.

Only one refresh runs at a time, regardless of how many callers request a token concurrently.

§Flow diagram

flowchart TD Start["get_token()"] --> Lock["Acquire lock"] Lock --> Cached{Token cached?} Cached -- No --> InitAuth["Authenticate (lock held)"] InitAuth -- OK --> ReturnNew["Return new token"] InitAuth -- NotFound --> ErrNotFound["NotAuthenticated"] InitAuth -- Err --> ErrAuth["Return error"] Cached -- Yes --> CheckRefresh{Expired?} CheckRefresh -- "No (fresh)" --> ReturnOk["Return cached token"] CheckRefresh -- "Yes (needs refresh)" --> InProgress{Refresh in progress?} InProgress -- Yes --> WaitOrReturn["Return token if usable, else wait for refresh"] WaitOrReturn -- OK --> ReturnOk WaitOrReturn -- "refresh failed" --> ErrExpired["TokenExpired"] InProgress -- No --> HasCred{Refresh credential?} HasCred -- None --> CheckUsable["Return token if usable, else TokenExpired"] HasCred -- Yes --> Usable{Still usable?} Usable -- "Yes (preemptive)" --> NonBlocking["Refresh in background (lock released)"] NonBlocking --> ReturnOld["Return current token"] Usable -- "No (fully expired)" --> Blocking["Refresh (lock held)"] Blocking -- OK --> ReturnNew2["Return new token"] Blocking -- Err --> ErrExpired["TokenExpired"]

Required Methods§

Source

fn get_token( self, ) -> impl Future<Output = Result<ServiceToken, AuthError>> + Send

Retrieve a valid access token, refreshing or re-authenticating as needed.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§