Skip to content

OIDC SSO (external IdP)

This is the consumer side — Axowl federates to an external OIDC IdP. (For Axowl as an OIDC provider, see OIDC / OAuth2 reference.)

POST /api/org/{slug}/idp-connections with a custom-oidc or named-* (okta/entra/google/kakao/naver) type. Provide a discovery URL (endpoints auto-filled) or manual issuer + authorization + token endpoints, plus client_id/client_secret. An org can hold several active connections, each routed by email domain; the count is capped by plan (Pro 1 · Pro+ 3 · Business 10 · Enterprise unlimited). Kakao/Naver need the Korean Package add-on. See IdP connections.

RoutePurposeSource
GET /idp/{slug}/login-hintPre-auth: tells a login page whether the org has an IdP and which type, so it can branch (SSO redirect vs native form). Name and type only.IdpAuthEndpoints.cs:55
GET /idp/{slug}/loginRedirects to the chosen IdP’s authorization endpoint. With several connections, pass ?email= (or ?domain=): domain match → default (no-domain) connection → the only active one → otherwise idp_ambiguous. idp_not_configured when nothing is active.:88
GET /idp/{slug}/callbackExchanges the code and JIT-provisions the membership via FederatedLoginCommand.:162

3. Switching providers — Axowl-native fallback

Section titled “3. Switching providers — Axowl-native fallback”

There is no direct IdP→IdP switch. Deactivate first, then configure the new provider — this prevents email-mapping lockout.

  • POST /api/org/{slug}/idp-connections/deactivate — turn all active connections off (back to Axowl-native login).
  • POST /api/org/{slug}/idp-connections/{connectionId}/deactivate — turn one connection off, leaving the others routing.

The same connections also sign in your app’s end users on the hosted login page. When the org has at least one active OIDC connection, the page shows Continue with SSO below the social buttons. Nothing to register at the IdP: the round trip comes back through the same /idp/{slug}/callback you already registered.

RoutePurpose
GET /api/public/apps/{clientKey}/login-methodsmethods.sso = { enabled, emailRequired }. No connection names or domains are exposed. emailRequired is true when there are several connections and none is the default (no-domain) one.
GET /api/public/apps/{clientKey}/auth/sso/start?email=&redirect_url=Picks the connection with the same routing as /idp/{slug}/login, then redirects to the IdP.

After the IdP returns, the person lands on the portal’s /social-callback with a one-time code, exactly like social sign-in. Failures come back as ?error=:

  • sso_email_required — several connections, enter a work email first.
  • sso_not_configured — no active OIDC connection (or it was turned off mid-flight).
  • sso_domain_mismatch — the connection is bound to a domain and the IdP returned an email outside it.
  • not_public — new person, and the app group doesn’t allow public sign-up (same rule as social).

SAML connections don’t appear on the app sign-in page yet; they sign in org members only.