Build a Vestibule OAuth2 provider strategy from scratch.
What the core handles
Vestibule generates and validates CSRF state. It manages PKCE and resolves
configured scopes. It also adds PKCE parameters and sends token-refresh
operations to the strategy.
Your strategy builds provider URLs.
Your strategy exchanges codes for credentials.
Your strategy fetches and normalizes user info.
The Strategy type
The provider name, default scopes, and builder functions define the
contract. Vestibule carries the custom error payload type through
AuthError(e).
Put a provider in a separate package. This example creates a Twitch
strategy package. It uses Vestibule and the OAuth helpers that the
built-in strategies use.
name ="vestibule_twitch"
version ="0.1.0"
description ="Twitch OAuth strategy for Vestibule"
Send the authorization code to the provider’s token endpoint. Parse the
response into ExchangeResult. Then use the credentials and
artifacts to get a stable provider UID and normalized
UserInfo.
Export a strategy() function. Return
strategy.Strategy(e) if the provider uses only built-in
error kinds. Return strategy.Strategy(YourError) if the
provider wraps a domain error payload with error.custom.
pubfnstrategy() ->Strategy(e) {
strategy.new(
provider: "twitch",
default_scopes: ["user:read:email"],
authorize_url: do_authorize_url,
exchange_code: do_exchange_code,
fetch_user: do_fetch_user,
)
|> strategy.with_refresh(do_refresh_token)
}
Authoring checklist
Use provider_support helpers. Do not copy built-in internals unless necessary.
Keep scopes minimal and provider-owned.
Keep optional provider fields optional when you normalize user info.
Document refresh-token behavior. Providers use different rotation rules and returned scopes.
Add tests for URL building, token parsing, profile normalization, and failure responses.