When can email_verified be removed or reset on a user created through an enterprise SAML connection with Organizations?

Context:

I user the invitation flow to onboard the user. but only SSO connections have the auto-membership enabled and likely blocked when postlogin deny access based on the email_verified key.
• Users sign in through enterprise SAML connections (Okta as the IdP). Users arrive via an Organization invitation: invitation email → Auth0 page → Continue → SAML login at the IdP → back to Auth0 → application.
• We have a post-login Action that denies access unless event.user.email_verified === true .
• No code of ours sets email_verified for SSO users. Our backend only PATCHes user_metadata , and the only deletions are of organization membership.

What we see
An SSO user logs in successfully, so email_verified was true at that point. Later(not suddenly) but after some days in future the user (not all saml connection user) is not having that email_verified key or even the raw json is seen completly different, and the Action denies the login.

Questions

  1. What is the full lifecycle of email_verified for a user created through an enterprise SAML connection? Who sets it to true on creation, or on invitation acceptance?
  2. Is email_verified re-evaluated from the IdP on every login for SAML connections? Does an assertion with no email_verified attribute reset it?
  3. Can email_verified disappear from the user’s raw JSON, as opposed to being set to false ? If so, in which cases?
  4. Does “Sync user profile attributes at each login” ( set_user_root_attributes ) affect email_verified , or only name, nickname, given_name, family_name and picture?
  5. Which events reset it besides an email change through the Management API?
  6. Does deleting and re-creating the user (just-in-time provisioning at the first SSO login) produce a user without email_verified ? Is there a supported way to mark SAML users as verified?

What we’ve verified: the tenant logs show no delete ( du ) of the user (fill in after checking), and the Management API calls we make touch only user_metadata and org membership.

Hi @vignesh.ramalingam

Welcome back to the Auth0 Community!

You are asking how the email_verified value is set and maintained for users who sign in through an enterprise SAML connection with Okta as the identity provider, and why the value disappears or changes for some SSO users after several days, causing your Post-Login Action to deny access.

Summary: For enterprise connection users, email_verified is governed by the identity provider’s profile data and by the Auth0 user record, not by the Organization invitation step, so the Post-Login Action should check the connection type and the user’s identity record before it relies on that value.

Root Cause: A Post-Login Action that requires email_verified === true for every user treats the claim as a reliable signal for all connection types. For enterprise connections, the value comes from the identity provider’s profile and can be absent or replaced when the profile is synchronized on login. A user record that is recreated, linked, or updated with a different connection can also show a different raw JSON structure. The Post-Login Action then sees a missing or false value and denies access.

Now to answer your questions in order:

What is the full lifecycle of email_verified for a user created through an enterprise SAML connection? Who sets it to true on creation, or on invitation acceptance?

  • Creation via SAML JIT (First Login / Invitation Acceptance):
    When a user accepts an Organization invitation and completes authentication at Okta, Auth0 provisions the user record Just-In-Time (JIT) under the SAML connection (saml-p|{connection-name}|{user-id}).

  • Who sets it?

    1. Direct SAML Assertion mapping: If the SAML Response contains an attribute explicitly mapped to email_verified, Auth0 parses that boolean.

    2. Auth0 Default Enterprise Heuristic: By default, if the SAML response does not provide an email_verified attribute, Auth0 assumes enterprise IdP assertions for verified domains are trusted and sets email_verified: true at user creation (or marks the root property email_verified = true).

    3. Organization Invitation: Accepting an invitation does not independently flip or guarantee email_verified; it is the identity provider profile creation logic during the first successful callback that establishes the initial user profile.

Is email_verified re-evaluated from the IdP on every login for SAML connections? Does an assertion with no email_verified attribute reset it?

  • Yes, it is re-evaluated if upstream attribute sync is active.

  • What happens if the SAML assertion omits email_verified?

    • If the SAML response never carried email_verified, Auth0 typically retains the initial value unless upstream attribute mapping or synchronization is triggered.

    • However: If an IdP sends an attribute that maps to email_verified with a null, empty string, or missing value, or if Okta changes how user claims are emitted (e.g., app-level SAML attribute statements altered or mapped conditionally), Auth0 overwrites the cached normalized profile attribute with what was received.

    • If no assertion attribute is mapped to email_verified, standard logins usually preserve the existing user root record.

Can email_verified disappear from the user’s raw JSON, as opposed to being set to false ? If so, in which cases?

Yes. email_verified can be completely absent (undefined) from the user JSON in two primary scenarios:

  1. User Identity Linking or Secondary Identity Resolution:

    • If an account linking event occurs (e.g., an automatic or manual link between a database user / social user and a SAML user), event.user in the Post-Login Action reflects the primary identity.

    • If the SAML identity was linked as a secondary identity to a primary profile that does not have an email verification flag, or vice versa, the root event.user.email_verified will reflect the primary record, causing email_verified to appear missing or altered.

  2. Profile Re-provisioning / User ID Switching (The “Completely Different Raw JSON” clue):

    • You noted: “even the raw json is seen completely different”. This strongly points to Auth0 seeing a different user identity or different user_id, rather than modifying the existing one:

      • In SAML, the Auth0 user_id is derived from the SAML Subject NameID: saml-p|{connection_name}|{NameID}.

      • If Okta sends a different NameID format or value (e.g., previously sent email user@domain.com, but later Okta sent an internal Okta user ID 00u123456..., or persistent/transient pseudonym), Auth0 creates a completely new, separate user record!

      • Depending on whether Okta included an email or email_verified claim in the assertion for this new NameID, this new user profile can look completely different and lack email_verified.

Does “Sync user profile attributes at each login” ( set_user_root_attributes ) affect email_verified , or only name, nickname, given_name, family_name and picture?

  • In enterprise connections (SAML / WS-Fed), connection-level synchronization options control how upstream attributes update root attributes.

  • set_user_root_attributes strictly synchronizes root profile attributes (name, given_name, family_name, nickname, picture).

  • However, under the hood, SAML mappings mapped via the connection’s mappings dictionary (or default SAML attribute parsers) synchronize attributes on every login. If an assertion supplies an email or email_verified attribute, Auth0 updates the root email_verified to reflect the latest incoming token if upstream synchronization applies.

Which events reset it besides an email change through the Management API?

  1. SCIM Synchronization (Okta SCIM):

    • If you have SCIM enabled (as in your Okta Workforce integration), user updates pushed via SCIM (PUT /api/v2/users/{id}) or JIT updates can overwrite user attributes. If Okta’s SCIM app schema does not send or explicitly maps emails[primary=true].verified, Auth0’s SCIM endpoint can clear or fail to set email_verified.
  2. Direct Management API updates:

    • Calling PATCH /api/v2/users/{id} with an email field resets email_verified: false unless email_verified: true is explicitly passed in the same payload.
  3. IdP Assertion Changes:

    • Okta profile changes (e.g., admin updated the primary email, changed domain, or modified custom SAML attribute statements).

Does deleting and re-creating the user (just-in-time provisioning at the first SSO login) produce a user without email_verified ? Is there a supported way to mark SAML users as verified?

  • Re-creation: If a user is deleted and re-created via pure SAML JIT with no explicit SAML attribute for email_verified, the outcome depends on whether the IdP domain matches the connection’s domain whitelist / configuration. If it doesn’t match or the mapping omits it, it can be created without email_verified.

[Recommended and Supported Solutions]

  1. In your Post-Login Action (Best Practice for Enterprise/SAML):
    Enterprise users authenticated via corporate SAML / SSO connections (Okta) are inherently verified by their enterprise identity provider. Requiring event.user.email_verified === true without checking connection strategy is a common pitfall because SAML assertions frequently do not emit an email_verified claim.

    Update your Post-Login Action to treat enterprise/SAML connections as verified:

exports.onExecutePostLogin = async (event, api) => {
  const isEnterprise = event.connection.strategy.startsWith('saml') || 
                       event.connection.strategy === 'enterprise' ||
                       event.connection.strategy === 'waad' ||
                       event.connection.strategy === 'okta';

  const isEmailVerified = event.user.email_verified === true || isEnterprise;

  if (!isEmailVerified) {
    api.access.deny('Please verify your email address before signing in.');
  }
};
  1. Explicitly Map email_verified in Okta SAML & Auth0 Connection:

    • In Okta: Add an Attribute Statement:

      • Name: email_verified (or http://schemas.auth0.com/email_verified)

      • Value: true (or user.email != null)

    • In Auth0 SAML Connection Options:
      Under the connection mappings, map the incoming SAML attribute to email_verified:

     {
       "mappings": {
         "email_verified": "email_verified"
       }
     }
  1. Auto-verify via Post-Login Action or Management API:
    If you must have the root database field set to true, you can set it in a Post-Login Action using the Management API client if event.connection.strategy === 'samlp' and !event.user.email_verified:
const ManagementClient = require('auth0').ManagementClient;
// PATCH /api/v2/users/{id} with { email_verified: true }

Kind Regards,
Nik