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

text
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

1Sign in to your Okta admin console (a free Integrator Free Plan account works fine for testing — developer.okta.com).
2Go to Applications → Applications → Create App Integration.
3Choose "OIDC — OpenID Connect" as the sign-in method and "Single-Page Application" as the application type, then Next.
4Under Sign-in redirect URIs, add the exact URL your app redirects back to — for the nostackai playground this is its Settings page's own URL (https://playground.nostackai.com/settings).
5Save. You land on the app's detail page — note the tabs: General, Sign On, Assignments.
6Open the Sign On tab. Under Grant type, check "Implicit (hybrid)" and enable "Allow ID Token with implicit grant type." This is off by default — the SPA template assumes authorization-code + PKCE.
7Open the Assignments tab and assign the app to the Okta users/groups who should be able to sign in — an unassigned user gets blocked at the Okta login step with no useful error on your side.
8Back on the General tab, copy the Client ID.

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

1Sign in to your Auth0 dashboard (manage.auth0.com).
2Go to Applications → Applications → Create Application, name it, and choose "Single Page Web Applications," then Create.
3You land on the application's Settings tab — this is where Domain and Client ID are shown (top of the page); copy both. Your issuer is https://{yourAuth0Domain}/ — note the trailing slash, Auth0's issuer always has one, unlike Okta's.
4Still on Settings, scroll down to Application URIs. Set Allowed Callback URLs to the exact URL your app redirects back to (for the playground, its Settings page URL). Add the same URL to Allowed Logout URLs if you plan to use sign-out. Click Save Changes at the bottom of the tab.
5Scroll to the bottom of the same Settings tab and expand the collapsed "Advanced Settings" panel. It opens its own row of sub-tabs (Application Metadata, Device Settings, OAuth, Grant Types, WS-Federation, Certificates, Endpoints) — click Grant Types and check "Implicit" (Authorization Code and Refresh Token are on by default; leaving them checked too is harmless). New Auth0 applications don't have Implicit on by default, so this must be turned on explicitly, same reasoning as Okta. Save Changes again.
6Switch to the application's Connections tab (next to Settings, not inside Advanced Settings) and confirm at least one connection is toggled on for this specific app — e.g. "Username-Password-Authentication." A new application sometimes starts with none enabled, which silently blocks every sign-in with no error shown on the Settings tab.

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

1In https://dev-console.nostackai.com, open Tenant Management → your tenant → Settings tab → SSO.
2Paste your issuer into Issuer URL. The Authorize, Token, and Logout endpoint fields auto-fill from it — the form detects Okta's issuer shape (…/oauth2/{authServer}) and uses Okta's /v1/* paths, or falls back to Auth0's paths (/authorize, /oauth/token, /.well-known/jwks.json, /oidc/logout) for anything else. Double-check the auto-filled values if your provider is neither.
3Fill in Email domain — the domain of the emails your users at this tenant will sign in with, e.g. acme.com. This is what resolves sign-in to this tenant; get it wrong and no one can sign in even with an otherwise-perfect config.
4Paste in the Client ID from whichever walkthrough you followed above. Client secret is optional — this flow doesn't use one.
5Save. The form won't let you save until Issuer URL, Email domain, JWKS URI, and Client ID are all filled in.
  • 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 value nostackai-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

text
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

text
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 iss claim 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 profile in 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 profile by 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.