vestibule/strategy
Provider-strategy interface. A `Strategy(e)` is an opaque record bundling the provider-specific functions an OAuth/OIDC provider implements: build authorize URL, exchange code, fetch user, and an optional refresh token.
vestibule/strategy
Provider-strategy interface. A Strategy(e) is an opaque record
bundling the provider-specific functions an OAuth/OIDC provider
implements: build authorize URL, exchange code, fetch user, and an
optional refresh token.
Provider packages (vestibule_google, vestibule_apple, …) build
these with strategy.new, which takes the three required capabilities
directly, plus the optional with_refresh and with_nonce builders;
the core library invokes them through the exposed accessors.
Types
ExchangeResult
The result of exchanging an authorization code.
credentials contains the standard OAuth credentials. artifacts contains
provider-specific token response data that may be needed while resolving the
user, such as an OpenID Connect id_token.
Opaque to keep provider-specific artifacts evolution-safe.
pub type ExchangeResultStrategy
A strategy is the bundle of provider-specific functions needed to authenticate with a single OAuth/OIDC provider.
The type parameter e corresponds to the custom error type in
AuthError(e). Built-in strategies are polymorphic in e.
Opaque so that vestibule can add optional capabilities without breaking
provider packages. Construct with new, which requires the three core
capabilities (authorize_url, exchange_code, fetch_user) so that a
strategy unable to complete an authentication flow cannot be built.
Attach optional capabilities with the with_refresh and with_nonce
builders. Invoke through the build_authorize_url, exchange_code,
refresh_token, and fetch_user helpers.
refresh_token is optional: a strategy built without with_refresh fails
refresh_token with an AuthError of kind RefreshUnsupportedKind.
pub type Strategy(a)UserResult
Normalized user details returned by a strategy.
Opaque so that new fields can be added without breaking strategy
implementations. Construct with user_result and read with the
user_result_uid, user_result_info, and user_result_extra accessors.
pub type UserResultFunctions
append_code_verifier
Append a PKCE code_verifier to a form-encoded request body when present.
Strategy implementations should call this after building the token exchange request to include the PKCE verifier parameter.
pub fn append_code_verifier( request.Request(String), option.Option(String)) -> request.Request(String)authorization_header
Build the Authorization header value from credentials.
Uses the token_type from the credentials (e.g., “Bearer”, “bearer”).
Strategy implementations should use this instead of hardcoding "Bearer ".
Returns Error if the token type is not “bearer” (case-insensitive),
as vestibule only supports Bearer token authentication.
pub fn authorization_header(credentials: credential.Credentials) -> Result(String, error.AuthError(a))build_authorize_url
Build the provider’s authorization URL.
pub fn build_authorize_url( Strategy(a), config: config.ClientConfig, options: config.AuthorizeOptions, scopes: List(String), state: String) -> Result(String, error.AuthError(a))default_scopes
Return the strategy’s default scopes, used when the caller’s
AuthorizeOptions does not specify any.
pub fn default_scopes(Strategy(a)) -> List(String)exchange_artifacts
Return provider-specific artifacts produced by the exchange
(e.g., an OpenID Connect id_token).
pub fn exchange_artifacts(ExchangeResult) -> dict.Dict(String, dynamic.Dynamic)exchange_code
Exchange an authorization code for credentials and any provider-specific
artifacts. Pass the PKCE code_verifier if one was generated for the
authorization request.
pub fn exchange_code( Strategy(a), config: config.ClientConfig, code: String, code_verifier: option.Option(String)) -> Result(ExchangeResult, error.AuthError(a))exchange_credentials
Return the OAuth credentials produced by the exchange.
pub fn exchange_credentials(ExchangeResult) -> credential.Credentialsexchange_result
Build an exchange result for providers with no provider-specific artifacts.
pub fn exchange_result(credential.Credentials) -> ExchangeResultexchange_result_with_artifacts
Build an exchange result with provider-specific artifacts.
pub fn exchange_result_with_artifacts( credential.Credentials, dict.Dict(String, dynamic.Dynamic)) -> ExchangeResultfetch_user
Fetch user info using the obtained exchange result.
pub fn fetch_user( Strategy(a), config: config.ClientConfig, exchange: ExchangeResult) -> Result(UserResult, error.AuthError(a))new
Build a Strategy for provider.
default_scopes is used when the caller’s AuthorizeOptions does not
specify any scopes. The three core capabilities are required:
authorize_urlbuilds the provider-specific authorization URL from the config, options, scopes, and state.exchange_codeexchanges an authorization code for credentials and optional provider-specific artifacts; the third parameter is the PKCEcode_verifierif one was generated.fetch_userresolves the authenticated user from the exchange result.
Attach optional capabilities with the with_* builders:
strategy.new( provider: "github", default_scopes: ["user:email"], authorize_url: do_authorize_url, exchange_code: do_exchange_code, fetch_user: do_fetch_user,)|> strategy.with_refresh(do_refresh_token)pub fn new( provider: String, default_scopes: List(String), authorize_url: fn(config.ClientConfig, config.AuthorizeOptions, List(String), String) -> Result(String, error.AuthError(a)), exchange_code: fn(config.ClientConfig, String, option.Option(String)) -> Result(ExchangeResult, error.AuthError(a)), fetch_user: fn(config.ClientConfig, ExchangeResult) -> Result(UserResult, error.AuthError(a))) -> Strategy(a)provider
Return the human-readable provider name (e.g., "github", "google").
pub fn provider(Strategy(a)) -> Stringrefresh_token
Refresh credentials using a refresh token.
Returns an AuthError of kind RefreshUnsupportedKind if the strategy was
built without with_refresh.
pub fn refresh_token( Strategy(a), config: config.ClientConfig, refresh_token: String) -> Result(credential.Credentials, error.AuthError(a))user_result
Build a UserResult.
pub fn user_result( uid: String, info: user_info.UserInfo, extra: dict.Dict(String, dynamic.Dynamic)) -> UserResultuser_result_extra
Return provider-specific extra fields associated with the user.
pub fn user_result_extra(UserResult) -> dict.Dict(String, dynamic.Dynamic)user_result_info
Return the normalized user info.
pub fn user_result_info(UserResult) -> user_info.UserInfouser_result_uid
Return the provider’s unique user id.
pub fn user_result_uid(UserResult) -> Stringuses_nonce
Whether this strategy uses the OIDC nonce (generate + validate).
pub fn uses_nonce(Strategy(a)) -> Boolwith_nonce
Mark this strategy as using the OIDC nonce. The core will then generate
an OIDC nonce, emit it on the authorize URL, and validate it against the
id_token on callback. Plain OAuth2 strategies should omit this.
pub fn with_nonce(Strategy(a)) -> Strategy(a)with_refresh
Attach an optional token-refresh capability. refresh_token swaps a
refresh token for fresh credentials. Strategies built without this fail
refresh_token with an AuthError of kind RefreshUnsupportedKind.
pub fn with_refresh( Strategy(a), fn(config.ClientConfig, String) -> Result(credential.Credentials, error.AuthError(a))) -> Strategy(a)