Skip to content

v1.5.1 - SSO account linking requires a verified email

Latest

Choose a tag to compare

@ibuilder ibuilder released this 09 Aug 10:24
· 1 commit to main since this release

A security fix for single sign-on. If you run ScopeMaker with
OIDC_ENABLED=1, upgrade.

An unverified email claim could take over an existing account

provision_sso_user matched an incoming OIDC identity on the issuer's subject
first and the email claim second. The email fallback would bind that identity to
any pre-existing local account with the same address — including one that
had a password, an admin role, and a project's worth of documents.

That trusts the identity provider to have verified the address, and not all do.
A multi-tenant IdP with self-service signup will happily issue a token asserting
somebody else's email. Whoever held such a token inherited the victim's account,
their organizations and their documents, without ever knowing the password.

The fix. Linking to an account that already exists now requires the provider
to report email_verified, and an absent claim counts as unverified — an issuer
that says nothing has confirmed nothing.

Two things deliberately unchanged:

  • Subject matching. A subject is issued by the provider and cannot be chosen
    by the person signing in, so it was never the risk. Someone whose email
    changes at the IdP still keeps their account.
  • Creating a new account from an unverified address. It lands in its own
    organization and can reach nothing that already exists.

OIDC_REQUIRE_VERIFIED_EMAIL=0 restores the previous behaviour for an identity
provider you operate that omits the claim entirely.

Who is affected: deployments with OIDC_ENABLED=1 whose identity provider
can issue tokens for addresses it has not verified. Password-only and
Procore-only deployments are unaffected.

How it was found

The function had no direct test coverage. Writing that coverage surfaced the
bug: the test demonstrating the takeover was written first and failed against
the old code.

A real identity provider is only needed for the OAuth handshake — the matching
logic takes a plain claims dict, so it was testable all along. There are now 20
tests covering subject matching, email changes at the provider, provider
scoping, the domain allowlist and organization attachment. Coverage of
accounts.py went from 47% to 86%.

One of those tests pins down a decision that looks like a bug and is not: with
no OIDC_DEFAULT_ORG configured, two SSO users sharing an email domain each get
their own organization rather than being grouped. Grouping people who merely
share a domain would put strangers in one tenant the first time somebody signed
in with a consumer address.

Also

The project page now describes what
the product actually does — it had drifted four releases behind, and never
mentioned the coverage analysis that finds the scope gaps its own opening
argument is about.

Upgrading

No migration. No configuration change required; OIDC_REQUIRE_VERIFIED_EMAIL
defaults to on.

Full changelog: https://github.com/ibuilder/scopemaker/blob/main/CHANGELOG.md