Core OAuth2 HTTP operations: authorization URL generation, auth code exchange, and token refresh.
Uses Req for HTTP. All functions are stateless — they operate on credential
structs and return updated structs. The CredentialManager orchestrates
when to call these.
Token Exchange Flow
# 1. Build authorization URL (redirect user here)
url = ADK.Auth.OAuth2.authorization_url(%{
auth_endpoint: "https://accounts.google.com/o/oauth2/v2/auth",
client_id: "my-client-id",
redirect_uri: "https://myapp.com/auth/callback",
scopes: ["openid", "profile"],
state: "random-state-string"
})
# 2. After redirect, exchange code → tokens
{:ok, updated_cred} = ADK.Auth.OAuth2.exchange_code(credential, opts)
# 3. Later, refresh expired token
{:ok, refreshed_cred} = ADK.Auth.OAuth2.refresh_token(credential, opts)Token Expiry
Tokens include expires_at (Unix timestamp). Use expired?/1 or
expires_soon?/1 to check before use. The CredentialManager handles
this automatically.
Summary
Functions
Build an OAuth2 authorization URL to redirect the user to.
Perform a client credentials grant (server-to-server, no user).
Exchange an authorization code for access + refresh tokens.
Returns true if the credential's access token has expired.
Returns true if the credential will expire within the buffer window (default: 5 minutes). Proactive refresh to avoid races.
Returns true if the credential needs exchange (has auth_code but no access_token).
Refresh an expired access token using the refresh token.
Returns true if refresh is possible (credential has refresh_token + endpoint).
Types
Functions
Build an OAuth2 authorization URL to redirect the user to.
Required options:
:auth_endpoint— the authorization endpoint URL:client_id— OAuth2 client ID:redirect_uri— callback URL
Optional options:
:scopes— list of requested scopes (default:[]):state— CSRF state string (default: generated):access_type—"offline"to request refresh token (Google-specific):extra_params— map of additional query parameters
@spec client_credentials( ADK.Auth.Credential.t(), keyword() ) :: {:ok, ADK.Auth.Credential.t()} | {:error, term()}
Perform a client credentials grant (server-to-server, no user).
The credential must have client_id, client_secret, and token_endpoint.
Scopes from the credential are used if present.
Options:
:scopes— override credential scopes:http_opts— extra options passed toReq.post/2
@spec exchange_code( ADK.Auth.Credential.t(), keyword() ) :: {:ok, ADK.Auth.Credential.t()} | {:error, term()}
Exchange an authorization code for access + refresh tokens.
The credential must have:
auth_code— the code received from the OAuth callbackclient_id,client_secret— your OAuth app credentialstoken_endpoint— the token URL
Returns {:ok, updated_credential} with access_token, refresh_token,
and expires_at populated, and auth_code cleared.
Options:
:redirect_uri— must match the one used in the authorization URL:http_opts— extra options passed toReq.post/2
@spec expired?(ADK.Auth.Credential.t()) :: boolean()
Returns true if the credential's access token has expired.
Returns false if no expires_at is set (assumes still valid).
@spec expires_soon?(ADK.Auth.Credential.t(), non_neg_integer()) :: boolean()
Returns true if the credential will expire within the buffer window (default: 5 minutes). Proactive refresh to avoid races.
@spec needs_exchange?(ADK.Auth.Credential.t()) :: boolean()
Returns true if the credential needs exchange (has auth_code but no access_token).
@spec refresh_token( ADK.Auth.Credential.t(), keyword() ) :: {:ok, ADK.Auth.Credential.t()} | {:error, term()}
Refresh an expired access token using the refresh token.
The credential must have refresh_token, client_id, client_secret,
and token_endpoint.
Options:
:scopes— request specific scopes (optional):http_opts— extra options passed toReq.post/2
@spec refreshable?(ADK.Auth.Credential.t()) :: boolean()
Returns true if refresh is possible (credential has refresh_token + endpoint).