Login via custom url was removed from the desktop UI

(#267) Bug Won't fix desktop self-hosting

Thread

Comment by @mgabor3141
RexSystem 1 vote edited originally by @mgabor3141 on GitHub
I've been working on getting the desktop app functional with a self-hosted instance (including SSO login via an external OIDC provider). More context on self-hosting in general in my discussion post.

Connecting to a self-hosted instance

As @bmlzootown mentioned, the desktop app reads settings.json from the user data directory:
OSPath
Linux~/.config/fluxer/settings.json
macOS~/Library/Application Support/fluxer/settings.json
Windows%APPDATA%\fluxer\settings.json
{
  "app_url": "https://your-instance.example.com"
}
This works — the desktop app loads the web UI from your self-hosted instance. However, it currently requires creating this file manually. The InstanceSelector component exists in the codebase but isn't wired up to the login page, and even if it were, it wouldn't help: on first launch (without settings.json), the app loads the official web app from web.fluxer.app, which wouldn't have any self-hosted customizations. A proper solution would need a first-run instance picker built into the Electron shell itself (before any remote web app is loaded).

Building the desktop app

The fluxer_desktop package on the refactor branch needs a few fixes to build successfully:
  1. Preload ESM/CJS conflict: package.json has "type": "module", so .js files are treated as ESM, but the preload script is built as CJS. Fix: output preload as index.cjs in scripts/build.mjs and update the preload path in Window.tsx.
  1. ESM banner collision: The esbuild banner import { createRequire } from 'module' collides with esbuild's own bundled createRequire import. Fix: rename to _createRequire in the banner.
  1. electron-builder config: linux.desktop.Name/Comment/Categories/StartupWMClass need to be nested under linux.desktop.entry for electron-builder ≥26.
  1. Missing package.json metadata: electron-builder deb generation requires description, homepage, and author fields in fluxer_desktop/package.json.

SSO login from the desktop app

This was the bigger challenge. The normal SSO flow redirects the browser to the OIDC provider, which then redirects back to https://your-instance.example.com/auth/sso/callback. In the desktop app, the SSO page opens in the system browser (needed for passkey/WebAuthn support), but there's no way for the browser callback to get back to the Electron app. The solution uses the fluxer:// deep link protocol that the desktop app already registers: API changes (SsoService, AuthRequestService, AuthSchemas):
  • Added desktop boolean to SsoStartRequest
  • When desktop: true, the API uses fluxer://auth/sso/callback as the OIDC redirect_uri instead of the web callback URL
  • The desktop flag is stored in the SSO state payload so completeLogin uses the matching redirect_uri for the code exchange
Web app changes (AuthLoginLayout, AuthFlow, AuthenticationActionCreators):
  • When running in the desktop app, handleStartSso passes desktop: true and opens the authorization URL via electronApi.openExternal() (system browser) instead of window.location.assign()
Deep link handler (DeepLinkUtils):
  • Added handling for fluxer://auth/sso/callback?code=...&state=... deep links
  • Uses dynamic imports to avoid a circular dependency (DeepLinkUtils is loaded early from App.tsx)
OIDC provider config:
  • fluxer://auth/sso/callback must be added as an allowed redirect URI in your OIDC provider
The flow: click SSO → browser opens → authenticate (passkeys work!) → browser redirects to fluxer://auth/sso/callback?code=...&state=... → OS routes to desktop app → token exchange completes → logged in. Note: this also requires the SSO token exchange fixes from my discussion post #5 — without those, the OIDC code exchange fails regardless of desktop vs web.

Branch & builds

All changes are on mgabor3141/fluxer@feat/desktop-custom-instance-url-clean (based on refactor). There are CI-built artifacts (Linux x64, macOS arm64, Windows x64) from that branch here — though as always, the usual caveat applies: don't install binaries from random forks unless you've reviewed the source and trust the build pipeline.