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?
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:
-
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.
-
Profile Re-provisioning / User ID Switching (The “Completely Different Raw JSON” clue):
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?
-
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.
-
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.
-
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]
-
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.');
}
};
-
Explicitly Map email_verified in Okta SAML & Auth0 Connection:
-
In Okta: Add an Attribute Statement:
-
In Auth0 SAML Connection Options:
Under the connection mappings, map the incoming SAML attribute to email_verified:
{
"mappings": {
"email_verified": "email_verified"
}
}
- 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