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
- 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.
- 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.
- Sign in with an
@example.com user.
- 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
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:
/api/auth/error?error=Sign-ups_are_restricted_to_verified_%40example.com_accounts./api/auth/error?error=account_not_linkedBoth come from
emailVerifiedbeingundefined, because Executor only readsemail_verifiedfrom the ID token and never falls back to/userinfo. In better-auth'sgeneric-oauth plugin,
fetchUserInfo()returns as soon as the ID token hassubandemail(index.ts#L120-L139):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:emailpresent, noemail_verified/userinfo:email_verified: trueThis is spec-legal, not a misconfiguration: OIDC Core §5.4 places
email-scope claims atthe 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: trueat/userinfo— i.e. fall back to the UserInfo endpoint when the ID token doesn't carry the claim.Steps to reproduce
(
https://<tenant>.okta.com) rather than an/oauth2/<id>authorization server — theout-of-the-box setup, with no custom claims configured.
EXECUTOR_SSO_DISCOVERY_URL=https://<tenant>.okta.com/.well-known/openid-configuration,client ID/secret, and
EXECUTOR_SSO_ALLOWED_DOMAINS=example.com.@example.comuser./api/auth/error?error=Sign-ups_are_restricted_to_verified_...100% reproducible. Adding
email_verifiedto the ID token is the only thing that fixesit, and at that issuer custom claims aren't configurable at all.
Diagnostics / logs
No response
Before you submit