Docs menu: Overview
Strategy-based OAuth2 authentication for Gleam
OAuth sign-in for Gleam apps, without the guesswork.
Vestibule gives Gleam applications a consistent request/callback flow, normalized auth results, PKCE, CSRF state, provider strategies, and Wisp or Mist middleware without hiding the security responsibilities your app still owns.
Search state, PKCE, provider packagesIdentity provider
- RequestURL, state, PKCE verifier
- StoreBind transient callback data
- CallbackValidate and normalize user info
Signed-in session in your app
Build the stack in two steps.
Start with the route layer: Wisp and Mist middleware own request and callback routes, or your own router calls the core API directly. Then add a provider strategy for profile and token behavior; it never replaces request and callback handling.
Route layer
Using Wisp or Mist?Start with middleware routesInstall core, one provider strategy, and the matching middleware package. Vestibule handles request and callback routing while your app stores callback data and creates the session.- Choose vestibule_wisp or vestibule_mist for your server.
- Store the returned state and PKCE verifier before redirecting.
- Handle the normalized auth result in your session code.
Provider strategy
Keep the callback boundary explicit.
Vestibule creates the authorization request and validates the callback. Your app still stores state and PKCE data before redirecting, then maps successful auth results to accounts.
State mismatchRestart sign-in and discard stored callback data.
Provider rejectionShow an auth error instead of asserting success.
Profile or token failureRetry the provider flow or route users to support.
import vestibule/authorization_request
import vestibule/error
// Request phase: failure here means
// misconfiguration, so assert is fine.
let options = config.authorize_options()
let assert Ok(auth_request) =
vestibule.create_authorization_request(
strategy,
config: client_config,
options: options,
)
// Store authorization_request.state(auth_request)
// and code_verifier(auth_request), then redirect
// to authorization_request.url(auth_request).
// Callback phase: state can mismatch and
// providers can reject the user, so handle
// both branches instead of asserting.
case
vestibule.handle_callback(
strategy,
client_config,
params,
expected_state,
code_verifier,
expected_nonce: option.None,
)
{
Ok(auth) -> sign_in(auth)
Error(err) ->
case error.kind(err) {
error.StateMismatchKind -> restart_sign_in()
_ -> show_auth_error(err)
}
}Secure defaults, explicit boundaries.
Vestibule creates strong state tokens, applies PKCE, validates callback state before surfacing provider details, and verifies the provider-specific data it owns. Your application still stores transient callback data, protects bearer credentials, and decides how users map to accounts.