vestibule_indieauth
Decentralized IndieAuth strategy where users sign in with a URL they control and endpoints are discovered dynamically.
When to use it
Use IndieAuth when you want users to authenticate with their own domain instead of a centralized provider, with no per-app client secret and per-user endpoints discovered at runtime.
Default scopes: profile
Install
Until 1.0, install Vestibule packages from GitHub using the movingvestibule-v0.0 tag. This requires Gleam 1.18 or later because companion packages use git path dependencies.
[dependencies]
vestibule_indieauth = { git = "https://github.com/tylerbutler/vestibule.git", ref = "vestibule-v0.0", path = "packages/vestibule_indieauth" }Setup
- Host your application at a stable HTTPS URL — this URL is your client_id.
- Use `auth: config.PublicClient`; IndieAuth clients are public and do not send a client secret.
- Register the redirect URI your app uses for the callback.
- Call discover with the user-supplied profile URL before starting the flow.
Usage
import vestibule
import vestibule/config
import vestibule_indieauth
// Discover the user's IndieAuth endpoints from their URL.
let assert Ok(strategy) =
vestibule_indieauth.discover("https://user.example.com")
// client_id is your app's URL; no client_secret is required.
let client_config =
config.new(
client_id: "https://myapp.example.com/",
redirect_uri: "https://myapp.example.com/auth/indieauth/callback",
auth: config.PublicClient,
)
let options = config.authorize_options()
let assert Ok(auth_request) =
vestibule.create_authorization_request(
strategy,
config: client_config,
options: options,
)What Vestibule handles
- Identity is a URL — auth.uid(auth) returns the user's canonical me URL.
- Endpoints are discovered per user from their homepage (metadata, Link headers, then HTML link tags).
- Public-client semantics — no client_secret is sent during token exchange.
- PKCE is used for the authorization code flow.
- Profile name, email, and photo are populated from the token or userinfo response when available.
What you handle
- Discovery performs HTTP requests, so the strategy targets the Erlang (BEAM) runtime only.
- Each user may resolve to different authorization and token endpoints; always discover per login.
- When a userinfo endpoint is discovered it is queried for profile data; otherwise the me URL is used as the identity.