Skip to content

Teams and security

View as Markdown

Single sign-on setup

Where: Settings → Instance → Single sign-on (instance administrator only; Settings → Security links to it). What it does and does not protect is in login methods; this page is the recipe per identity provider.

Provider facts below were checked against each provider's documentation on 2026-10-26; the source is linked on each entry. They change: if a console has moved, the issuer and the redirect-URI rules still hold.

The same five steps everywhere#

  1. In NebulaCtrl click Connect your identity provider and pick the provider. The dialog fills in the name and the issuer pattern. Parts in {braces} are yours to replace (the first one is selected, so type over it); saving is blocked while one is left.

  2. Copy the Redirect URI the dialog shows. It is https://<your public URL>/api/v1/auth/oidc/<provider id>/callback and you can register it before you save: the dialog reserves the new provider's ID, so the address does not change when you save. Set NEBULACTRL_PUBLIC_URL first; without it NebulaCtrl uses the address your browser is on, which is only right for local development.

  3. At the provider create a confidential web client (it has a client secret), paste the redirect URI into the field named below, and copy the client ID and secret.

  4. Back in NebulaCtrl paste the client ID and secret, and click Test connection. It reads <issuer>/.well-known/openid-configuration without saving anything and answers in a sentence:

    Answer Meaning
    The host name does not resolve The domain in the issuer is misspelt.
    Could not connect to … Nothing answers there from the control plane (firewall, wrong port, private address).
    … did not answer in time Same, slower.
    … presented a TLS certificate this server does not trust A private CA or a self-signed certificate; the control plane does not accept it.
    … answered 404 for /.well-known/openid-configuration The issuer is not the base address of an OpenID Connect provider.
    … did not return a JSON OpenID configuration You entered a login page or a proxy answered.
    The provider says its issuer is "…", but you entered "…" The issuer must be identical, including any trailing slash. Copy the value it quotes.
    The OpenID configuration has no … The provider is not usable for sign-in (missing endpoints or key set).
  5. Set Allowed email domains (an empty list lets any verified email through), save, and sign in from a private window to try it. People are matched to accounts by verified email; a person with no account needs an invite or Allow open sign-up (login methods).

Providers#

Google#

Microsoft Entra ID#

  • Issuer: https://login.microsoftonline.com/{tenant}/v2.0, with {tenant} your Directory (tenant) ID (a GUID, on the app's Overview page). Not common, organizations or consumers: their discovery document reports a tenant-specific issuer, so the exact-match check fails (NebulaCtrl warns about it).
  • Console: Entra admin center → Entra ID → App registrations → New registration. Add a Web platform; field: Redirect URIs. Create a client secret under Certificates & secrets.
  • Entra never sends email_verified. Under Token configuration → Add optional claim → ID add email and xms_edov ("the email's domain owner is verified"). NebulaCtrl treats a true xms_edov as a verified email; without it every sign-in ends with email_not_verified.
  • Sources: https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc, https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference

Okta#

Auth0#

authentik#

  • Issuer: https://{domain}/application/o/{slug}/, per application, with the trailing slash (the default issuer mode).
  • Admin interface → Applications → Applications → New Application, with an OAuth2/OpenID Provider. Field: Redirect URIs (an exact URL is fine; authentik also accepts regular expressions).
  • Source: https://docs.goauthentik.io/add-secure-apps/providers/oauth2/

Keycloak#

  • Issuer: https://{domain}/realms/{realm}. A Keycloak older than 17, or one started with a relative path, serves it under /auth/realms/{realm}.
  • In the realm: Clients → Create client → OpenID Connect, Client authentication on, standard flow on. Field: Valid redirect URIs (compared as an exact string).
  • Source: https://www.keycloak.org/securing-apps/oidc-layers

Zitadel#

Pocket ID#

GitLab (gitlab.com or self-managed)#

GitHub (OAuth, not OpenID Connect)#

Any other OpenID Connect provider#

Pick Any OpenID Connect provider and enter the issuer exactly as the provider's discovery document states it (https://openid.net/specs/openid-connect-discovery-1_0.html: the issuer in the document must be identical to the one used to fetch it). Requirements: a confidential web client, the authorization-code flow with PKCE, and an ID token that carries email and email_verified: true (or the userinfo endpoint does).

If sign-in fails afterwards#

The sign-in page shows the code; the control-plane log has the detail.

Code Usual cause
oidc_failed The provider is disabled or its discovery document is no longer reachable. Run Test connection from Edit.
oidc_exchange_failed Wrong client secret, or the redirect URI at the provider differs from the one NebulaCtrl sent.
oidc_invalid_token The ID token's audience, issuer or nonce did not check out (a wrong client ID).
email_not_verified The provider sent no verified email (Entra: add xms_edov; GitHub: verify the primary email).
domain_not_allowed The email's domain is not in the provider's allowed list.
signup_disabled The person has no account and no invite; turn on Allow open sign-up or invite them.