Self-hosting Fluxer: findings, bugs, and patches from a real deployment

(#1037) Feature Shipped self-hosting

Thread

Comment by @mgabor3141
RexSystem 1 vote originally by @mgabor3141 on GitHub OP

5: SSO/OIDC token exchange broken (3 compounding bugs)

Setting up SSO with an OIDC provider (tested with Pocket ID) fails at the token exchange step. Three bugs compound: 1. URLSearchParams body serialized as '{}' packages/http_client/src/HttpClientRequestInternals.tsx — resolveRequestBody() JSON-stringifies non-string bodies. JSON.stringify(new URLSearchParams(...)) produces '{}', so the token exchange POST body is empty.
+ if (body instanceof URLSearchParams) {
+     return body.toString();
+ }
  if (typeof body === 'string') {
2. client_secret not included in token exchange packages/api/src/auth/services/SsoService.tsx calls getSsoConfig() without { includeSecret: true }, so clientSecret is always undefined.
- await this.instanceConfigRepository.getSsoConfig()
+ await this.instanceConfigRepository.getSsoConfig({ includeSecret: true })
3. Basic auth header ignored by some IdPs Upstream sends client_id in the POST body and client_secret via Authorization: Basic header. Some IdPs (e.g. Pocket ID) only parse Basic auth when client_id is absent from the body. Since it's present, the Basic auth is ignored entirely. Fix: send client_secret in the POST body instead:
- const encoded = Buffer.from(`${config.clientId}:${config.clientSecret}`, 'utf8').toString('base64');
- headers['Authorization'] = `Basic ${encoded}`;
+ body.set('client_secret', config.clientSecret);
Additional SSO fixes needed:
  • SSO users treated as "unclaimed" — User.tsx considers users with passwordHash === null && !isBot as unclaimed. SSO-provisioned users have no password but are legitimate. Fix: add && !this._traits.has('sso') to the condition.
  • SSO callback route blocked by auth guard — RootComponent.tsx redirects unauthenticated users to /login before the callback page at /auth/sso/callback can process the authorization code. Fix: add the path to the allowlist alongside the login route.