This signs in your app's end-users, not your team
This page is per-tenant, for the real end-users of your deployed app. For your own team signing in to https://dev-console.nostackai.com, see Okta for your org — that's a different flow (authorization-code + PKCE, routed by email domain).
How it works
App user enters their work email ("Continue with Company Email" — same UX as the org level)
↓
Your app calls POST /app/{orgCode}/ssoconfig { email } with a client_id header
↓ (resolved by the email's domain — no tenant_code involved)
Browser redirects to your IdP's authorize endpoint (implicit flow — response_type=id_token)
↓
User authenticates with your IdP (SSO / MFA / whatever you've already configured there)
↓
IdP redirects back with the ID token in the URL fragment — no authorization code, no exchange step
↓
Your app calls GET /app/{orgCode}/token with that ID token — signed in Because there's no code-exchange step, this is deliberately simpler to stand up than the org-level flow: no client secret required, no server-side callback handler to write. Pick whichever provider you already use — Okta and Auth0 are covered step by step below; any other OIDC-compliant provider ends up needing the exact same six values, just from a different dashboard.
What you'll end up with
- An app integration/application in your IdP configured for the implicit grant (ID token via redirect, no client secret)
- A test user you can sign in with
- The six values Tenant Settings → SSO needs: issuer, email domain, authorize endpoint, JWKS URI, client id, and (optionally) token/logout endpoints
Option A — Okta
Implicit grant must be enabled explicitly
A freshly created Okta SPA integration defaults to authorization-code + PKCE only. If sign-in redirects back with an error instead of a token in the URL fragment, this is almost always why — go back to the app's Sign On tab and confirm "Allow ID Token with implicit grant type" is checked.
Your issuer is https://{yourOktaDomain}/oauth2/default (or your custom authorization server's own issuer, if you're not using the default one) — Security → API in the Okta admin console lists every authorization server and its issuer if you need to confirm.
Option B — Auth0
No Allowed Web Origins here — this isn't a missing step
The org-level (PKCE) flow needs it because the browser makes a direct fetch() to the token endpoint to exchange the code — a real cross-origin request. This implicit flow never does: the redirect to Auth0/Okta and the return trip are both full-page navigations (not fetch calls, so not subject to CORS at all), and the ID token arrives in the URL fragment, which the app reads directly off window.location — no network call to Auth0/Okta ever happens. Nothing to allow, so nothing to configure.
Two easy things to miss on Auth0, both outside the main Settings fields
Implicit grant lives under the Settings tab's collapsed "Advanced Settings" panel, on its own Grant Types sub-tab (alongside Application Metadata, OAuth, Certificates, and others) — not a separate top-level tab of the application itself. Having zero connections enabled is a separate, silent failure mode with no indication on Settings — check the Connections tab specifically if sign-in fails with no clear error.
The APIs section is not part of this
Auth0's top-level "APIs" area (audiences, access-token scopes) is for authorizing calls to your own backend API — unrelated to authenticating a user via OIDC. Skip it here; nostackai only ever consumes the ID token, never an access token against a custom API.
Register it under Tenant Settings → SSO
- Issuer URL, Email domain, JWKS URI, and Client ID are required to save.
- Client secret is optional and, if supplied, is encrypted at rest and never returned by any later read of this setting — leave it blank unless you're planning something that needs a server-side exchange.
- Token endpoint isn't read by tenant sign-in today (same reason — no code exchange) but is stored for completeness and any future auth-code-flow support.
- One email domain maps to exactly one tenant per org — saving a domain another tenant already registered is rejected with a 409, rather than leaving it ambiguous which tenant a matching user would land in.
- The stored field names are literally
okta_*even when the provider is Auth0 or anything else — any standards-compliant OIDC provider that exposes the same discovery URLs works identically. - The email domain must be proved before sign-in through it works: add a DNS TXT record on
_nostackai-challenge.<domain>with the valuenostackai-verify=tenant:<org code>:<tenant code>(Tenant Settings → SSO shows both) and press Verify. Until then the pre-login lookup finds no provider for that domain and its tokens are refused. Choosing "Account approved automatically" is also refused until the domain is verified. - Turn off the Active toggle to disable sign-in for this tenant without losing the saved configuration.
Your app never touches the secret
The pre-login endpoint your frontend calls (POST /app/{orgCode}/ssoconfig) returns only issuer, client_id, auth_endpoint, and scopes — never the secret, whether or not one was configured.
Reference — values summary
Okta (default org authorization server):
Issuer: https://{yourOktaDomain}/oauth2/default
Authorize endpoint: https://{yourOktaDomain}/oauth2/default/v1/authorize
Token endpoint: https://{yourOktaDomain}/oauth2/default/v1/token
JWKS URI: https://{yourOktaDomain}/oauth2/default/v1/keys
Logout endpoint: https://{yourOktaDomain}/oauth2/default/v1/logout
Auth0:
Issuer: https://{yourAuth0Domain}/ (trailing slash matters)
Authorize endpoint: https://{yourAuth0Domain}/authorize
Token endpoint: https://{yourAuth0Domain}/oauth/token
JWKS URI: https://{yourAuth0Domain}/.well-known/jwks.json
Logout endpoint: https://{yourAuth0Domain}/oidc/logout You can verify any of these against your provider's own discovery document — {issuer}/.well-known/openid-configuration for Auth0, or {issuer}/.well-known/oauth-authorization-server for Okta.
What to share with someone else who manages your IdP
Application type: Single-Page Application
Grant type: Implicit — with "ID token" enabled (NOT authorization code / PKCE)
Redirect URI: <the exact page in your app that completes sign-in>
Scopes requested: openid email profile
Client secret: Not needed — this flow never sends one They create the app integration and send back the Client ID and the Issuer URL — that, plus the email domain your users sign in with (something you already know, not something they need to tell you), is everything Tenant Settings → SSO needs.
Troubleshooting
- Provider shows "redirect_uri_mismatch" — the redirect URI your app sent doesn't exactly match what's registered (Sign-in redirect URIs on Okta, Allowed Callback URLs on Auth0). Copy the exact URL from the provider's error and add it there.
- Redirected back with an error instead of a token in the URL fragment — the implicit grant isn't enabled (Okta: Sign On tab → Grant type; Auth0: Advanced Settings → Grant Types). Both default this off.
- "invalid_client" or similar on the provider's side — the Client ID in Tenant Settings → SSO doesn't match the app integration. Re-copy it from the provider's dashboard.
- Sign-in succeeds at the provider but /token in nostackai rejects it — the issuer in your saved config doesn't exactly match the
issclaim in the ID token (decode it at jwt.io to check). Auth0 issuers need their trailing slash; Okta's don't have one. - Signed in but no email on the resulting profile — the requested scopes don't include email. Confirm Scopes is
openid email profilein Tenant Settings → SSO. - "User is not assigned" (Okta) or immediate silent failure (Auth0) — Okta: assign the user under the app's Assignments tab. Auth0: check the Connections tab has at least one connection enabled for this application.
- Sign-in works locally but not for a hosted environment — add that environment's exact redirect URL to the provider's allowed list too; these lists aren't wildcarded.
- POST /ssoconfig returns 404 "no SSO provider found for email domain" — no tenant in this org has that exact domain saved, or it's a typo (check for a trailing dot, wrong TLD, etc.). Re-check the Email domain field in Tenant Settings → SSO.
- POST /ssoconfig returns 403 "client_id not recognized" — the client_id header sent is your app's own registered client_id (the same one GET /token needs), not the Okta/Auth0 client id — these are unrelated values. Check what your app is actually sending.
- Saving Tenant Settings → SSO returns 409 — another tenant in this org already registered that email domain. One domain can only resolve to one tenant; pick a different domain or remove it from whichever tenant claimed it first.
FAQ
- Do I need a client secret? No — this is an implicit-flow sign-in with no server-side code exchange. Leave it blank unless you have a specific reason to store one.
- Can I use a custom Okta authorization server instead of the default one? Yes — use that server's own issuer and derived endpoints; nothing else changes.
- What scopes does nostackai request?
openid email profileby default, configurable in the Scopes field. The email, name, and picture claims are read from the ID token. - Can we run Okta/Auth0 sign-in alongside native email/password and Google? Yes, all three work simultaneously for the same tenant's end-users.
- Can we restrict which of our users can sign in? Yes, entirely on the provider's side — Okta's Assignments, or an Auth0 rule/action — nostackai has no separate allowlist of its own.
- What happens if I turn off Active? Sign-in for this tenant is disabled immediately, but the saved configuration (issuer, client id, etc.) is kept — turning it back on restores it with nothing to re-enter.
- How does nostackai know which tenant to sign me into? By the domain of the email you enter before redirecting — never a tenant_code. See the SSO overview's system diagram for the full request sequence.
- Can two tenants in the same org share an email domain? No — one domain maps to exactly one tenant per org. If your users could plausibly belong to more than one tenant on the same domain, this flow isn't the right fit for that case today.