Docs menu: IndieAuth strategy
Provider strategy

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

  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

  • 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.