Skip to main content

OpenID Connect

Semaphore supports authentication via OpenID Connect (OIDC).

Links:

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:

ParameterDescription
display_nameProvider name which displayed on Login screen.
iconMDI-icon which displayed before of provider name on Login screen.
colorProvider name which displayed on Login screen.
client_idProvider client ID.
client_id_fileThe path to the file where the provider's client ID is stored. Has less priorty then client_id.
client_secretProvider client Secret.
client_secret_fileThe path to the file where the provider's client secret is stored. Has less priorty then client_secret.
redirect_url
provider_url
scopes
username_claimUsername claim expression*.
email_claimEmail claim expression*.
name_claimProfile Name claim expression*.
orderPosition of the provider button on the Sign in screen.
allow_idp_initiatedEnable IdP-initiated login for this provider. Default false.
return_via_statePass 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 iss and target_link_uri.
  • Keycloak / Authentik / Ping / OneLogin — set the application's launch / home URL to the Initiate Login URI.
  • Azure AD / EntraMy Apps uses an SP-initiated start URL and does not always send iss; point the start URL at https://your-domain.com/api/auth/oidc/<provider-id>/login instead.

Security

  • IdP-initiated login is off by default and must be enabled per provider.
  • The iss parameter is validated against the configured issuer to prevent provider mix-up.
  • target_link_uri is accepted only when it points back to Semaphore (no open redirects).
  • The flow goes through the full Authorization Code exchange with CSRF state and a nonce, 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:

Screenshot of the Semaphore login page, with two login buttons. One says "Sign In", the other says "Sign in with MySSO"