Files
stack/docs/SSO-PROVIDERS.md
Jarvis 774b76447d
Some checks failed
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
fix: rename all packages from @mosaic/* to @mosaicstack/*
- Updated all package.json name fields and dependency references
- Updated all TypeScript/JavaScript imports
- Updated .woodpecker/publish.yml filters and registry paths
- Updated tools/install.sh scope default
- Updated .npmrc registry paths (worktree + host)
- Enhanced update-checker.ts with checkForAllUpdates() multi-package support
- Updated CLI update command to show table of all packages
- Added KNOWN_PACKAGES, formatAllPackagesTable, getInstallAllCommand
- Marked checkForUpdate() with @deprecated JSDoc

Closes #391
2026-04-04 21:43:23 -05:00

3.4 KiB

SSO Providers

Mosaic Stack supports optional enterprise single sign-on through Better Auth's generic OAuth flow. The gateway mounts Better Auth under /api/auth, so every provider callback terminates at:

{BETTER_AUTH_URL}/api/auth/oauth2/callback/{providerId}

For the providers in this document:

  • Authentik: {BETTER_AUTH_URL}/api/auth/oauth2/callback/authentik
  • WorkOS: {BETTER_AUTH_URL}/api/auth/oauth2/callback/workos
  • Keycloak: {BETTER_AUTH_URL}/api/auth/oauth2/callback/keycloak

Required environment variables

Authentik

AUTHENTIK_ISSUER=https://auth.example.com/application/o/mosaic
AUTHENTIK_CLIENT_ID=...
AUTHENTIK_CLIENT_SECRET=...

WorkOS

WORKOS_ISSUER=https://your-company.authkit.app
WORKOS_CLIENT_ID=client_...
WORKOS_CLIENT_SECRET=...
NEXT_PUBLIC_WORKOS_ENABLED=true

WORKOS_ISSUER should be the WorkOS AuthKit issuer or custom auth domain, not the raw REST API hostname. Mosaic derives the OIDC discovery URL from that issuer.

Keycloak

KEYCLOAK_ISSUER=https://auth.example.com/realms/master
KEYCLOAK_CLIENT_ID=mosaic
KEYCLOAK_CLIENT_SECRET=...
NEXT_PUBLIC_KEYCLOAK_ENABLED=true

If you prefer, you can keep the issuer split as:

KEYCLOAK_URL=https://auth.example.com
KEYCLOAK_REALM=master

The auth package will derive KEYCLOAK_ISSUER from those two values.

WorkOS setup

  1. In WorkOS, create or select the application that will back Mosaic login.
  2. Configure an AuthKit domain or custom authentication domain for the application.
  3. Add the redirect URI:
{BETTER_AUTH_URL}/api/auth/oauth2/callback/workos
  1. Copy the application's client_id and client_secret into WORKOS_CLIENT_ID and WORKOS_CLIENT_SECRET.
  2. Set WORKOS_ISSUER to the AuthKit domain from step 2.
  3. Create the WorkOS organization and attach the enterprise SSO connection you want Mosaic to use.
  4. Set NEXT_PUBLIC_WORKOS_ENABLED=true in the web deployment so the login button is rendered.

Keycloak setup

  1. Start from an existing Keycloak realm or create a dedicated realm for Mosaic.
  2. Create a confidential OIDC client named mosaic or your preferred client ID.
  3. Set the valid redirect URI to:
{BETTER_AUTH_URL}/api/auth/oauth2/callback/keycloak
  1. Set the web origin to the public Mosaic web URL.
  2. Copy the client secret into KEYCLOAK_CLIENT_SECRET.
  3. Set either KEYCLOAK_ISSUER directly or KEYCLOAK_URL + KEYCLOAK_REALM.
  4. Set NEXT_PUBLIC_KEYCLOAK_ENABLED=true in the web deployment so the login button is rendered.

Local Keycloak smoke test

If you want to test locally with Docker:

docker run --rm --name mosaic-keycloak \
  -p 8080:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:26.1 start-dev

Then configure:

KEYCLOAK_ISSUER=http://localhost:8080/realms/master
KEYCLOAK_CLIENT_ID=mosaic
KEYCLOAK_CLIENT_SECRET=...
NEXT_PUBLIC_KEYCLOAK_ENABLED=true

Web flow

The web login page renders provider buttons from NEXT_PUBLIC_*_ENABLED flags. Each button links to /auth/provider/{providerId}, and that page initiates Better Auth's signIn.oauth2 flow before handing off to the provider.

Failure mode

Provider config is optional, but partial config is rejected at startup. If any provider-specific env var is present without the full required set, @mosaicstack/auth throws a bootstrap error with the missing keys instead of silently registering a broken provider.