Stateless orchestrator for the full OAuth2 / credential lifecycle.
Mirrors Python ADK's CredentialManager but as pure functions.
The lifecycle is: load → exchange → refresh → save.
Usage
alias ADK.Auth.{Credential, CredentialManager, InMemoryStore}
# Create a store process
{:ok, store} = InMemoryStore.start_link()
# Initial credential (has auth_code, awaiting exchange)
cred = Credential.oauth2_with_code(
"client-id",
"client-secret",
"auth-code-from-callback",
token_endpoint: "https://oauth.example.com/token"
)
# The manager will exchange, save, and return the ready credential
{:ok, ready} = CredentialManager.get_credential("github", cred, server: store)
# => %Credential{type: :oauth2, access_token: "gho_...", refresh_token: "ghr_..."}
# On next call: loads from store, refreshes if near-expired
{:ok, ready} = CredentialManager.get_credential("github", cred, server: store)Options
:server— the credential store PID or name (passed toInMemoryStore):store_mod— module implementingADK.Auth.CredentialStore(default:ADK.Auth.InMemoryStore):redirect_uri— used during auth code exchange:refresh_buffer— seconds before expiry to proactively refresh (default: 300):http_opts— extra options forwarded toReq.post/2
Summary
Functions
Delete a credential from the store.
Get a ready credential by name, running exchange/refresh as needed.
Store a credential under a name. Convenience wrapper around the store module.
Functions
Delete a credential from the store.
@spec get_credential(String.t(), ADK.Auth.Credential.t(), keyword()) :: {:ok, ADK.Auth.Credential.t()} | :needs_auth | {:error, term()}
Get a ready credential by name, running exchange/refresh as needed.
Steps:
- If credential is a simple type (api_key, http_bearer) → return immediately
- Try loading from the credential store
- If loaded → check expiry → refresh if needed → save if refreshed → return
- If not loaded and credential needs exchange → exchange → save → return
- If not loaded and credential is client_credentials-capable → exchange → save → return
- Otherwise →
:needs_auth(user must re-authenticate)
Returns
{:ok, credential}— ready-to-use credential:needs_auth— no stored credential and no auth code; user must authenticate{:error, reason}— exchange/refresh/store failure
@spec save_credential(String.t(), ADK.Auth.Credential.t(), keyword()) :: :ok | {:error, term()}
Store a credential under a name. Convenience wrapper around the store module.