ADK.Auth.CredentialManager (ADK v0.0.1-alpha.1)

Copy Markdown View Source

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 to InMemoryStore)
  • :store_mod — module implementing ADK.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 to Req.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_credential(credential_name, opts \\ [])

@spec delete_credential(
  String.t(),
  keyword()
) :: :ok | {:error, term()}

Delete a credential from the store.

get_credential(credential_name, raw_cred, opts \\ [])

@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:

  1. If credential is a simple type (api_key, http_bearer) → return immediately
  2. Try loading from the credential store
  3. If loaded → check expiry → refresh if needed → save if refreshed → return
  4. If not loaded and credential needs exchange → exchange → save → return
  5. If not loaded and credential is client_credentials-capable → exchange → save → return
  6. 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

save_credential(credential_name, cred, opts \\ [])

@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.