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
- 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 vestibuleimport vestibule/configimport 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.