Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ set and is preferred in containers and hosted environments.

### WebAuthn

| Variable | Required | Default | Seeds `system_config` | Notes |
| --------- | -------- | ------- | --------------------- | ----------------------------------------------------------------------------- |
| `RPID` | Yes | - | `rpid` | Relying party ID (a domain, no scheme). |
| `ORIGINS` | Yes | - | `origins` | WebAuthn allowed origins (comma-separated URLs). Distinct from `APP_ORIGINS`. |
| Variable | Required | Default | Seeds `system_config` | Notes |
| --------- | -------- | ------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RPID` | Yes | - | `rpid` | Relying party ID (a domain, no scheme). |
| `ORIGINS` | Yes | - | `origins` | WebAuthn allowed origins (comma-separated URLs). Distinct from `APP_ORIGINS`. When you serve the admin console, the origin it loads from must also appear here, alongside the app origins. See [Admin dashboard](#admin-dashboard-optional). |

### OAuth

Expand Down Expand Up @@ -167,6 +167,29 @@ app.use('/console', createSeamlessConsoleProxy({ authServerUrl: opts.authServerU
The proxy forwards `/console` requests to this API's `/console` (so the dashboard version tracks
the auth image), while the adapter bridges the dashboard's cookie session to Bearer upstream.

**Prerequisites for browser flows started from the console.** Serving the console changes the
origin that passkey ceremonies carry, and for OAuth it changes the full redirect URI. Two separate
allowlists validate these, and both fail the same confusing way: the flow starts normally and only
fails partway through, so the configuration looks correct right up to the point it does not work.
Both apply to both deployment shapes above (served directly by this API at its own origin, or
reverse-proxied through `createSeamlessConsoleProxy` at the adopter's origin).

1. **The console's origin must be in `ORIGINS`.** Passkey and step-up ceremonies started in the
console carry the origin the console was loaded from, and WebAuthn verification checks it against
`origins` in `system_config` (seeded from `ORIGINS`). If it is missing, `start` returns 200 with
a challenge and the browser prompts normally, but `finish` fails, so step-up never completes.
Add the console's origin (for example `https://api.example.com`) to `ORIGINS` alongside the app
origins. `RPID` does not need to change, since the RP ID ignores the port.

2. **The console's callback must be in each provider's `redirectUris`.** The dashboard builds its
OAuth redirect with the router basename applied, so the `/console` build sends
`<origin>/console/oauth/callback`, a different path (and host) from a typical web app's
`/oauth/callback`. `redirectUris` is matched exactly, so this URL must be listed explicitly on
each provider, and it must also be registered as an authorized redirect URI with the identity
provider itself. If it is missing here, `POST /oauth/:providerId/start` returns 400 before any
redirect; if it is missing at the provider, the provider rejects with `redirect_uri_mismatch` at
the consent screen. See [docs/oauth.md](./oauth.md).

### Direct messaging (optional)

Needed only when this API sends OTP/magic-link messages itself. Not needed when a SeamlessAuth
Expand Down
4 changes: 4 additions & 0 deletions docs/oauth.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ For production providers, configure `redirectUris` as exact callback URLs. When

Providers without `redirectUris` fall back to configured trusted origins. Exact provider allowlists are preferred for production.

### Admin console callback

When the admin console runs OAuth, its callback is `<origin>/console/oauth/callback`, because the dashboard applies its router basename (`/console`) to the redirect. That is a different path from a typical web app's `/oauth/callback`, and a different host when the console is served or proxied from the API origin. Because `redirectUris` is matched exactly, this URL must be listed explicitly in each provider's `redirectUris`, and it must also be registered as an authorized redirect URI with the identity provider itself. If it is missing here, `POST /oauth/:providerId/start` returns 400 before any redirect; if it is missing at the provider, the consent screen rejects with `redirect_uri_mismatch`. See the admin dashboard prerequisites in [docs/configuration.md](./configuration.md#admin-dashboard-optional).

## Account Linking

`accountLinking` controls whether a provider identity can attach to an existing local user by email:
Expand Down
Loading