Self-Hosted Setup

End-to-end walkthrough for wiring SAML SSO into a self-hosted sfp deployment (one you run yourself with sfp server init).

SAML is enabled by default on every self-hosted deployment. Signing material is generated during sfp server init, the IdP is registered through an HTTP API, and the resulting provider ID and SSO domain are auto-published to every client. There's no config-file editing required.


Prerequisites

  • A running self-hosted deployment created with sfp server init and brought up with sfp server start (V3 or later).

  • Admin access to your SAML identity provider.

  • An owner-level JWT for the sfp API. The admin user created by sfp server init has the owner role, which is what /sfp/api/sso/providers requires. Application tokens (UUID-format, created via sfp server application-token create) are explicitly rejected on this endpoint — only the user JWT works.

    # Sign in once; the token is stored in your OS keyring under service
    # `sfp-pro`, account `supabase-token-<your-email>`.
    sfp server auth login --admin \
      --email admin@<tenant>.local \
      --sfp-server-url https://<your-domain>
    
    # Extract it into a shell variable for the curl calls below.
    export SFP_JWT=$(sfp server auth display --email admin@<tenant>.local --jwt)

    Headless / WSL / SSH session? The keyring backend needs an active D-Bus session and a running gnome-keyring-daemon (or equivalent). If sfp server auth display --jwt errors with no secret service provider or dbus session found, prefix with dbus-launch or run from a graphical session.


Step 1 — Configure your IdP

Create the SAML application in your identity provider and copy out the federation metadata URL.

Pick the matching guide:

Other SAML 2.0 providers follow the same shape — see Identity Providers for the URL convention and attribute mapping.

When you finish, you should have a metadata URL that looks something like:

https://login.microsoftonline.com/<tenant>/federationmetadata/2007-06/federationmetadata.xml?appid=<app>

Step 2 — Register the IdP with sfp

One API call hands the metadata URL to sfp:

curl -X POST "https://<your-domain>/sfp/api/sso/providers" \
  -H "Authorization: Bearer $SFP_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "metadataUrl": "<idp-metadata-url>",
    "domains": ["company.com"]
  }'

Auto-detect kicks in immediately — no restart needed. The response contains the provider id and the SAML entityId.

Verify

# List registered providers
curl "https://<your-domain>/sfp/api/sso/providers" \
  -H "Authorization: Bearer $SFP_JWT"

# Confirm /sfp/api/config publishes the SSO settings
curl "https://<your-domain>/sfp/api/config"
# -> sso.providerId and sso.domain are populated

Remove a provider

curl -X DELETE "https://<your-domain>/sfp/api/sso/providers/<id>" \
  -H "Authorization: Bearer $SFP_JWT"

Step 3 — Provision users

Self-registration is disabled by default, so users must be created before they can sign in. POST /sfp/api/users is the single entry point — it auto-detects the registered SSO provider and links the user to it:

User state on callWhat happens
New userCreated with SSO identity.
Existing email/password userConverted to SSO; identity linked to the IdP.
Existing SSO userIdempotent; team membership added if missing.

Via the API:

curl -X POST "https://<your-domain>/sfp/api/users" \
  -H "Authorization: Bearer $SFP_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@company.com",
    "firstName": "John",
    "lastName": "Doe",
    "team": "<team-slug>",
    "role": "member"
  }'

Or via the CLI:

sfp server user add \
  --firstname John \
  --lastname Doe \
  --target-email john.doe@company.com \
  --team <team-slug> \
  --role member \
  --email admin@<tenant>.local \
  --sfp-server-url https://<your-domain>

Step 4 — Sign in

CLI

# One-time configuration
sfp set server-url https://sfp.company.com --global
sfp set server-email user@company.com --global

# Authenticate
sfp auth login --provider saml

You don't need to pass --sso-domain or --sso-provider-id if a provider is registered — the CLI fetches them from /sfp/api/config. Override only when needed:

sfp auth login \
  --email user@company.com \
  --provider saml \
  --sso-domain company.com \
  --sfp-server-url https://sfp.company.com

The CLI opens your browser, completes the SAML round-trip, and stores the session in your OS keychain. SAML access tokens expire after about an hour; the CLI refreshes them automatically before expiry and on 401 responses. For long-running CI jobs, you can also force a refresh:

sfp auth refresh --email user@company.com
sfp auth refresh --all

Web UI

Open https://<your-domain> in a browser. The login screen pre-fills the SSO domain from the server config. Click Continue to redirect to your IdP.

Desktop app

Open the desktop app and sign in with SAML — the IdP redirect is captured through the app's custom protocol handler. No extra configuration needed beyond having the provider registered on the server.


API reference

All endpoints below are owner-only unless noted.

POST /sfp/api/sso/providers

Register a SAML IdP. Body:

{
  "metadataUrl": "https://...federationmetadata.xml",
  "domains": ["company.com"]
}

Returns { id, domains, entityId }.

GET /sfp/api/sso/providers

List registered providers.

DELETE /sfp/api/sso/providers/:id

Remove a provider.

GET /sfp/api/config (public)

Returns the public web-app configuration, including sso: { domain, providerId }.

POST /sfp/api/users

Create or link a user. Auto-detects the SSO provider; idempotent on re-runs.


Something not working?

See Troubleshooting.

On this page