[KongchangAI]
· 2 min read· 1,243 words

SSO Just-in-Time Provisioning: How to Safely Match Logins with Existing Users

SSO Just-in-Time Provisioning: How to Safely Match Logins with Existing Users

The core of SSO just-in-time provisioning is a fixed resolution order; email matching is safe only under the precondition of prior verification.

The article points out that SSO just-in-time provisioning is often misunderstood as "auto-creating an account on first login," but it is actually a fixed resolution order defined in the callback: first check explicit bindings, then attempt email matching, and finally consider auto-creation. Bindings take precedence over email matching because they come from trusted operations and are the strongest signal. The security of email matching depends on whether the identity provider has verified the email—if not, attackers can forge emails to achieve account takeover. Therefore, the system must read the email verification claim in the assertion, not just the email value. After a successful match, the stable identifier on the identity provider side and the binding source should be stored, making email only a one-time bridge. Auto-creation should be a configurable policy; enterprise environments are better off denying or entering approval.

Just-in-time provisioning in Single Sign-On (SSO) is often simplistically understood as "automatically creating an account when a user logs in for the first time," but the real challenge isn't creation—it's matching: when the same email already exists in the system, how do you determine that this login should be linked to an existing user rather than creating a duplicate identity? The original article points out that just-in-time provisioning is essentially a resolution order defined within the SSO callback, and whether email matching is safe depends on one key condition.

SSO just-in-time provisioning resolution order diagram

The Core of Just-in-Time Provisioning Is a Resolution Order

Think of just-in-time provisioning as a fixed sequence of decision logic, not a toggle switch. After the SSO callback returns an identity assertion, the system needs to answer several questions in order: Is this identity already bound to a user? If not, can it be matched to an existing user via email? If still not, is automatic creation of a new user allowed?

The significance of this order is that bindings take precedence over email matching. An existing explicit binding is the strongest signal because it comes from a previous trusted login or an explicit action by an administrator. Only in the absence of a binding does the system proceed to email matching. The original article emphasizes that this order must be fixed and cannot be swapped for implementation convenience—otherwise, logins that should be linked would become new accounts, or unfamiliar logins would be incorrectly merged into someone else's account.

Beyond the order, the behavior after each step's failure must also be defined. Whether to deny login, enter a pending-approval state, or automatically create an account when no user is matched is a policy choice, but it must be separated from the resolution order to avoid tangled logic.

Identity Assertion is structured data issued by the Identity Provider (IdP) in the SSO callback, typically appearing as a SAML assertion or OIDC ID Token. It contains the user's unique identifier (such as NameID or sub), email, name, and other attributes, along with the identity provider's claims about these attributes. The system reads this assertion during just-in-time provisioning, so the completeness and trustworthiness of the fields in the assertion directly determine whether the matching logic is reliable. The signature and encryption mechanisms of assertions differ across protocols, but the core principle is the same: only assertions that have passed signature verification can be used as a basis for identity decisions; otherwise, any field could be tampered with.

Security Conditions for Email Matching

The key conclusion from the original article is: email matching is only safe when the email has been verified by the identity provider. This condition sounds simple, but it determines the trustworthiness of the entire just-in-time provisioning process.

The email field in an SSO assertion is just a string. If the identity provider has not verified this email, a user could enter any address, including the email of an existing user in the system. If the system then matches directly by email, an attacker only needs to change their email on the identity provider side to the target user's address to be linked to an existing account upon login, resulting in account takeover.

Therefore, the decision logic must read the claim in the assertion that indicates the email verification status, not just the email value itself. Only when the identity provider explicitly declares that the email is verified can email matching become a candidate. The original article does not elaborate on the specific claim field differences across identity providers, but the prerequisite of "verified" is clear.

This also means that the reliability of just-in-time provisioning partly depends on the trust configuration for the identity provider. If an identity source with unverified emails is allowed to connect, the email matching gate becomes useless.

Email Verification Claim is a boolean or enumerated field attached to the assertion by the identity provider to indicate whether the email has been verified. In OIDC, this is typically represented by the email_verified claim; in SAML, it may be expressed through attribute claims or AuthnContext. The system must not assume that an email appearing in an assertion is necessarily verified; it must explicitly read this claim and decide whether to allow email matching accordingly. If the identity provider does not provide such a claim, or the claim is false, email matching should be considered unsafe and skipped. This requires the integrating party to clearly determine, when configuring the identity source, whether it supports and correctly transmits the verification status.

What to Store After a Successful Match

Just-in-time provisioning isn't just about "finding the person"—it also needs to leave a reusable binding so that email matching doesn't have to be repeated on every login. The original article mentions the need to store binding information, but what exactly to store depends on the design of the resolution order.

A reasonable approach is to associate the unique identifier on the identity provider side with the local user, forming a stable binding. Subsequent logins can then directly hit the binding without relying on email. Email matching thus becomes a one-time bridging action rather than a long-term dependency.

At the same time, it's necessary to record how this binding was established. A binding established through email matching is not at the same trust level as one manually established by an administrator. Retaining source information allows for auditing in the event of anomalous logins later, and helps determine whether re-verification is needed after an email change on the identity provider side.

The original article does not provide a specific data table structure, but from a security perspective, the focus of storage is on stable identifiers and binding sources, rather than repeatedly using email as a primary key.

Stable Identifier refers to a unique locator on the identity provider side that does not change with user attribute changes, such as OIDC's sub or SAML's NameID (in persistent format). Unlike email, a stable identifier remains unchanged after a user changes their name or email, making it suitable as the primary key for binding relationships. Associating the stable identifier with the local user ID ensures that subsequent logins directly hit the binding without relying again on the potentially changing email field. The binding record should also include the identity provider's identifier to distinguish the same user from different sources when multiple identity sources coexist.

Common Pitfalls and Practical Recommendations

A common misconception is equating just-in-time provisioning with automatic registration. Automatic registration is only the last step of the resolution order and should be a configurable policy, not the default behavior. For enterprise environments, a safer approach is to deny login or enter approval when no user is matched, rather than directly creating an account.

Another misconception is ignoring binding priority. If the system looks up by email first and then checks bindings, there is a risk that a bound user's login could be incorrectly matched by another identity with the same email. If the order is wrong, even the strictest security conditions can be bypassed.

For implementation, a three-step check can be used: confirm that bindings precede email matching in the resolution order; confirm that email matching only takes effect when the identity provider declares the email verified; and confirm that binding records include stable identifiers and source information. These three points do not require complex infrastructure changes, but they can significantly reduce the risk of account takeover and identity duplication.

#SSO just-in-time provisioning#email matching#identity provider#account takeover#identity assertion#stable identifier
Share:

Related articles