Docs menu: IndieAuth strategy
Provider strategy

vestibule_indieauth

Decentralized IndieAuth strategy for sign-in with a user-controlled URL and endpoints discovered at run time.

When to use it

Use IndieAuth if users sign in with their own domains instead of a centralized provider. The strategy discovers endpoints for each user and does not require an app client secret.

Default scopes: profile

Install

Vestibule packages are not available on Hex. Add them from GitHub with the moving v0 tag. Use Gleam 1.18 or later because companion packages use Git path dependencies.

[dependencies]
vestibule_indieauth = { git = "https://github.com/tylerbutler/vestibule.git", ref = "v0", path = "packages/vestibule_indieauth" }

Setup

  1. Host your application at a stable HTTPS URL. This URL is your client_id.
  2. Use `auth: config.PublicClient`. IndieAuth clients are public and do not send a client secret.
  3. Register the redirect URI your app uses for the callback.
  4. 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

  • The 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).
  • The strategy uses a public client. It does not send a client_secret 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 can use different authorization and token endpoints. Run discovery for each login.
  • The strategy requests profile data from a discovered userinfo endpoint. If no endpoint is available, it uses the me URL as the identity.