OpenID Connect
Semaphore supports authentication via OpenID Connect (OIDC).
Links:
- GitHub config
- Google config
- GitLab config
- Authelia config
- Authentik config
- Keycloak config
- Okta config
- PingFederate config
- Azure config
- Zitadel config
- Pocket-ID config
Example of SSO provider configuration:
{
"oidc_providers": {
"mysso": {
"display_name": "Sign in with MySSO",
"color": "orange",
"icon": "login",
"provider_url": "https://mysso-provider.com",
"client_id": "***",
"client_secret": "***",
"redirect_url": "https://your-domain.com/api/auth/oidc/mysso/redirect"
}
}
}
Configure via environment variable
When running in containers it may be convenient to configure providers using a single environment variable:
SEMAPHORE_OIDC_PROVIDERS='{
"github": {
"client_id": "***",
"client_secret": "***"
}
}'
This value must be a valid JSON string matching the oidc_providers structure above.
All SSO provider options:
| Parameter | Description |
|---|---|
display_name | Provider name which displayed on Login screen. |
icon | MDI-icon which displayed before of provider name on Login screen. |
color | Provider name which displayed on Login screen. |
client_id | Provider client ID. |
client_id_file | The path to the file where the provider's client ID is stored. Has less priorty then client_id. |
client_secret | Provider client Secret. |
client_secret_file | The path to the file where the provider's client secret is stored. Has less priorty then client_secret. |
redirect_url | |
provider_url | |
scopes | |
username_claim | Username claim expression*. |
email_claim | Email claim expression*. |
name_claim | Profile Name claim expression*. |
order | Position of the provider button on the Sign in screen. |
allow_idp_initiated | Enable IdP-initiated login for this provider. Default false. |
return_via_state | Pass the post-login return path via the OAuth state parameter instead of the redirect URL. Default true. |
endpoint.issuer | |
endpoint.auth | |
endpoint.token | |
endpoint.userinfo | |
endpoint.jwks | |
endpoint.algorithms |
*Claim expression
Example of claim expression:
email | {{ .username }}@your-domain.com
Semaphore is attempting to claim the email field first. If it is empty, the expression following it is executed.
The expression "username_claim": "|" generates a random username for each user who logs in through the provider.
IdP-initiated login
By default Semaphore only supports SP-initiated sign-in: the user opens Semaphore, clicks the provider button, and is redirected to the identity provider (IdP).
With IdP-initiated login the journey can start at the identity provider instead — for example by clicking the Semaphore tile in the Okta dashboard, Azure My Apps, or a Keycloak / Authentik application launcher.
Semaphore implements this using the standard Third-Party Initiated Login mechanism (OpenID Connect Core 1.0 §4). The IdP redirects the browser to a dedicated Initiate Login URI, and Semaphore then starts a normal Authorization Code flow. The actual authentication is still a full, secure code exchange — Semaphore never accepts an unsolicited token.
Enabling it
Set allow_idp_initiated to true for the provider:
{
"oidc_providers": {
"mysso": {
"display_name": "Sign in with MySSO",
"provider_url": "https://mysso-provider.com",
"client_id": "***",
"client_secret": "***",
"redirect_url": "https://your-domain.com/api/auth/oidc/mysso/redirect",
"allow_idp_initiated": true
}
}
}
Configuring the identity provider
In your IdP, set the application's Initiate Login URI to:
https://your-domain.com/api/auth/oidc/<provider-id>/initiate
where <provider-id> is the key under oidc_providers (for example mysso).
The IdP must send the iss (issuer) parameter to this endpoint; Semaphore rejects requests whose iss does not match
the configured provider. The optional login_hint parameter is forwarded to the IdP, and an optional target_link_uri
sets the page to open after login (it must point back to Semaphore, otherwise it is ignored).
Provider-specific notes:
- Okta — set Login initiated by to Either Okta or App (or App Only) and fill in the Initiate login URI. Okta
sends both
issandtarget_link_uri. - Keycloak / Authentik / Ping / OneLogin — set the application's launch / home URL to the Initiate Login URI.
- Azure AD / Entra — My Apps uses an SP-initiated start URL and does not always send
iss; point the start URL athttps://your-domain.com/api/auth/oidc/<provider-id>/logininstead.
Security
- IdP-initiated login is off by default and must be enabled per provider.
- The
issparameter is validated against the configured issuer to prevent provider mix-up. target_link_uriis accepted only when it points back to Semaphore (no open redirects).- The flow goes through the full Authorization Code exchange with CSRF
stateand anonce, so a captured or replayed token cannot be used to sign in.
Sign in screen
For each of the configured providers, an additional login button is added to the login page:
