Skip to content

feat: add option to skip email verification for SSO registrations - #179

Open
heudev wants to merge 2 commits into
NodeBB:mainfrom
heudev:feat/skip-email-verification
Open

feat: add option to skip email verification for SSO registrations#179
heudev wants to merge 2 commits into
NodeBB:mainfrom
heudev:feat/skip-email-verification

Conversation

@heudev

@heudev heudev commented Aug 12, 2026

Copy link
Copy Markdown

Adds a per-strategy "Skip email verification for people who register using SSO?" option, mirroring the setting the first-party SSO plugins expose.

Why

trustEmailVerified only confirms an email when the provider sends an email_verified claim that is truthy:

const email_verified =
	parseInt(trustEmailVerified, 10) &&
	(payload.email_verified || payload.email_verified === true);

Not every provider sends that claim. Microsoft's https://graph.microsoft.com/oidc/userinfo is one — a real response contains sub, givenname, familyname, email, locale and picture, and no email_verified at all. The address is there and is the one the account is registered with, but trustEmailVerified can never fire, so every user arriving through that strategy stays unverified and hits the "posting in some categories is enabled once your email is confirmed" wall.

There is currently no way to express "I trust this provider's addresses outright". Loosening trustEmailVerified to treat a missing claim as verified would silently change behaviour for existing installs, so this adds an explicit opt-in instead and leaves trustEmailVerified exactly as it was.

What changed

  • New skipEmailVerification checkbox on the strategy editor, registered in editStrategy's checkbox list so it is normalised to 1/0 like its siblings.
  • The trust decision moves into OAuth.isEmailTrusted(strategy, payload): the new option short-circuits to true, otherwise the existing trustEmailVerified behaviour is unchanged.
  • OAuth.login returns early for users who already have an association, which meant the email was only ever confirmed at registration time. Turning the option on therefore did nothing for accounts that had already signed in once. confirmEmailIfTrusted closes that gap, and refuses to act when the account is already confirmed or when the stored address differs from the one the provider just sent.

The email fallback is deliberately left alone

OAuth.login matches an incoming address against existing users before creating an account:

if (email && email_verified) {
	uid = await user.getUidByEmail(payload.email);
}

Routing the new option through that same flag would mean "skip email verification" also silently grants "attach this provider to whatever account already owns the address it claims" — an account takeover vector for any provider that does not actually verify its addresses, up to and including an admin's account. So the two decisions are separated: isEmailTrusted (which the new option relaxes) governs confirmation, while isEmailVerifiedByProvider still demands a genuine email_verified claim before any account is matched by email.

Testing

Verified on a live NodeBB 4.14.10 forum against a Microsoft strategy. With the option enabled, an account that had signed in previously moved to email:confirmed = 1 and joined verified-users on its next login; with the option off, behaviour is identical to before. npx eslint . is clean.

heudev added 2 commits August 12, 2026 15:42
trustEmailVerified only confirms an email when the provider actually
sends an email_verified claim. Providers that omit it entirely, such as
Microsoft's OIDC userinfo endpoint, leave every SSO user unverified with
no way to opt out.
Matching an incoming address against an existing account is an account
takeover vector when the provider has not actually verified it, so that
path stays keyed off a genuine email_verified claim.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant