Relationships
#1893 serve dashboard hardcodes swamp-club.com in OAuth login, ignoring --oauth-provider
Opened by sntxrr · 8/28/2026· Shipped 8/28/2026
Summary
The swamp serve web dashboard (--dashboard) hardcodes "swamp-club.com" in
every string of its OAuth login screen. When serve runs with --oauth-provider
pointed at a different authorization server, the dashboard still tells the user
to go to swamp-club.com. They go there, paste the user code, and it fails —
because that code was minted by a completely different IdP.
The backend is correct throughout. Only the client-side copy is wrong.
Environment
- swamp
20260828.013403.0-sha.4bde205b(also reproduced on20260827.012103.0) swamp serve --auth-mode oauth --oauth-provider https://<INTERNAL_HOST> --dashboard- Self-hosted authorization server (an OIDC shim in front of Authentik)
What happens
POST /auth/device returns the correct, provider-specific URIs:
{
"userCode": "<CODE>",
"verificationUri": "https://<INTERNAL_HOST>/device",
"verificationUriComplete": "https://<INTERNAL_HOST>/device?code=<CODE>"
}But packages/dashboard/src/views/Login.tsx renders:
| Line | Text |
|---|---|
| 177 | "You'll be redirected to swamp-club.com to authenticate with your account." |
| 196 | button label "Login with swamp-club" |
| 215 | "A new tab has opened at swamp-club.com. Enter the code below to confirm it's you." |
| 233 | link text "Open swamp-club.com manually" |
Line 233 is the most damaging. Its href is grant.verificationUriComplete,
which is correct — but the label names the wrong host. A user whose popup was
blocked reads the label, navigates to swamp-club.com by hand, and enters a code
that server never issued. That is exactly how this was hit.
The provider is already sent to the client, then discarded
src/cli/commands/serve.ts:3780—authInfo.verificationBaseUri = authConfig.oauthProviderpackages/dashboard/src/client/SwampProvider.tsx:32—AuthInfoalready declaresverificationBaseUri?: stringpackages/dashboard/src/client/SwampProvider.tsx:76—.then((info: AuthInfo) => setAuthMode(info.mode))keeps onlymodeand dropsverificationBaseUri
Confirmed live: GET /auth/info on a configured instance returns
{"mode":"oauth","verificationBaseUri":"https://<INTERNAL_HOST>"}. The value
reaches the browser and is thrown away one line later, so Login.tsx has no way
to name the real provider.
Suggested fix
Expose verificationBaseUri through the SwampProvider context and render its
host in the four strings above, falling back to "swamp-club.com" only when the
field is absent.
Even on its own, rewording line 233 to something provider-neutral — "Open the
approval page manually" — would remove the failure mode, since the href is
already right.
Impact
Any deployment using --oauth-provider against a non-swamp-club server.
--oauth-provider is honored everywhere in the backend; the dashboard login
screen appears to be the only component that still assumes swamp-club.
Shipped
Click a lifecycle step above to view its details.