Skip to content

[bug] SSO fails with any IdP that returns email_verified only from /userinfo #1972

Description

@Silentphantom62

Executor version

1.6.8

How do you run Executor?

Self-host (Docker)

Operating system

Linux

Integration involved

SSO / OIDC (genericOAuth provider, Okta)

What happened

All SSO sign-ins fail against a stock Okta tenant. Two different errors depending on
whether the local user already exists:

  • new user → /api/auth/error?error=Sign-ups_are_restricted_to_verified_%40example.com_accounts.
  • existing user → /api/auth/error?error=account_not_linked

Both come from emailVerified being undefined, because Executor only reads
email_verified from the ID token and never falls back to /userinfo. In better-auth's
generic-oauth plugin, fetchUserInfo() returns as soon as the ID token has sub and
email (index.ts#L120-L139):

if (decoded?.sub && decoded?.email) {
  return { id: decoded.sub, emailVerified: decoded.email_verified, ... };  // undefined
}
if (!userInfoUrl) return null;
const userInfo = await betterFetch(userInfoUrl, ...);   // never reached

Okta issues a thin ID token when the issuer is the tenant root
(https://<tenant>.okta.com, i.e. not one of the /oauth2/<id> authorization servers) —
which is what you get out of the box. I exchanged a real auth code with Executor's client
ID and scopes
(openid email profile) to confirm:

  • ID token: email present, no email_verified
  • /userinfo: email_verified: true

This is spec-legal, not a misconfiguration: OIDC Core §5.4 places email-scope claims at
the UserInfo endpoint for the code flow, and in the ID token only when no access token is
issued. Dex and oauth2-proxy both handle thin ID tokens explicitly for this reason.

What you expected

Sign-in to succeed when the IdP asserts email_verified: true at /userinfo — i.e. fall back to the UserInfo endpoint when the ID token doesn't carry the claim.

Steps to reproduce

  1. Register an OIDC app in an Okta tenant and point it at the tenant-root issuer
    (https://<tenant>.okta.com) rather than an /oauth2/<id> authorization server — the
    out-of-the-box setup, with no custom claims configured.
  2. Run self-host with EXECUTOR_SSO_DISCOVERY_URL=https://<tenant>.okta.com/.well-known/openid-configuration,
    client ID/secret, and EXECUTOR_SSO_ALLOWED_DOMAINS=example.com.
  3. Sign in with an @example.com user.
  4. Redirected to /api/auth/error?error=Sign-ups_are_restricted_to_verified_...

100% reproducible. Adding email_verified to the ID token is the only thing that fixes
it, and at that issuer custom claims aren't configurable at all.

Diagnostics / logs

No response

Before you submit

  • I searched the open issues for a duplicate.
  • I removed all keys, tokens, and credentials from this report.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions