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 initand brought up withsfp 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 inithas theownerrole, which is what/sfp/api/sso/providersrequires. Application tokens (UUID-format, created viasfp 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). Ifsfp server auth display --jwterrors withno secret service provider or dbus session found, prefix withdbus-launchor 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 populatedRemove 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 call | What happens |
|---|---|
| New user | Created with SSO identity. |
| Existing email/password user | Converted to SSO; identity linked to the IdP. |
| Existing SSO user | Idempotent; 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 samlYou 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.comThe 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 --allWeb 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.