Hi Auth0 team, I’ve hit a critical blocker in my Just-In-Time (JIT) migration lab that I believe requires a backend review. I’ve included exhaustive logs and reproduction details below.**
Tenant:** dev-cnhsg0roe6qny5na
Region: US
Environment: Production-like lab setup (custom DB connection using Azure-based legacy backend APIs)
Impact: Change Password → JIT user creation blocked, halting full migration flow
Context
I’m building a Just-In-Time (JIT) migration flow for Azure AD B2C migration into Auth0.
The project has two core components:
-
JIT Sign-In: When a user logs in, Auth0 validates against my legacy API (
LocalAccountSignIn) and creates the user dynamically in Auth0. -
JIT Forgot Password / Change Password: When a migrated user triggers a password reset, Auth0 calls the same legacy API (
LocalAccountUserExists), and if the user is not yet in Auth0, it attempts to create them using the Management API (POST /api/v2/users).
What Works
- JIT Sign-In: Fully functional.
-Auth0 successfully calls my legacy endpoint, validates credentials, and creates users on-the-fly.
-Users appear correctly under the expected connection (b2c-migrated-users-v2).
-All environment variables and secrets are correctly configured.
Example log excerpt: LOGIN SUCCESS user_id=ray.garg@zappsec.com migration_status=completed
-
The login script creates users without going through
POST /api/v2/users -
The change password script is the only place where
POST /api/v2/usersis called (for JIT creation during reset).
In my current design:
JIT Sign-In (Login script):
Uses the legacyLocalAccountSignInAPI and returns a user profile directly to Auth0. This path does not use the Management APIPOST /api/v2/users. It works consistently.JIT Forgot Password / Change Password (Change Password script):
UsesLocalAccountUserExistsand then callsPOST /api/v2/users(Management API) only whenusers-by-emailreturns empty.
This is the path that fails with 409The user already exists.
What Fails
Forgot Password / Change Password flow fails consistently with:
POST /api/v2/users response status=409
{
“statusCode”: 409,
“error”: “Conflict”,
“message”: “The user already exists.”,
“errorCode”: “auth0_idp_error”
}
This occurs even when:
-
/api/v2/users-by-emailreturns empty ([]) -
No users exist under this connection (
b2c-migrated-users-v2) -
The user does not exist in any other connection
-
I verified this using multiple advanced API searches (see below)
What I Have Already Tried
1. Fresh Connection Creation
-
Created an entirely new custom DB connection (
b2c-migrated-users-v2) -
Copied verified scripts for
login,create,get user, andchange password -
Recreated all environment variables with identical key names
-
Ensured
contextobject was enabled in all scripts
-JIT Sign-In on b2c-migrated-users and b2c-migrated-users-v2 works reliably → confirms config + secrets + legacy APIs are correct.
-Only the (Forgot Password) Change Password → Management API create branch fails with 409.
2. Verified Application & M2M Toggles
-
Web App toggle → Enabled for
b2c-migrated-users-v2 -
M2M App toggle → Enabled for
b2c-migrated-users-v2 -
On the M2M app, Management API → Authorized with following scopes:
read:users
update:users
delete:users
create:users
update:users_app_metadata
create:user_tickets
read:connections
read:logs
3. cURL Verification (Direct Management API)
Generated M2M token:
curl --request POST \
--url https://dev-cnhsg0roe6qny5na.us.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{
"client_id": "<client id here >",
"client_secret": "<client secret here >",
"audience": "https://<tenant>.us.auth0.com/api/v2/",
"grant_type": "client_credentials"
}'
Validated no duplicate users:
# Search by email
curl --request GET \
--url "https://dev-cnhsg0roe6qny5na.us.auth0.com/api/v2/users?q=email%3A\"rgarg2%40ucsc.edu\"&search_engine=v3" \
--header "authorization: Bearer <access_token>"
# → []
# Search by connection prefix
curl --request GET \
--url "https://dev-cnhsg0roe6qny5na.us.auth0.com/api/v2/users?q=user_id%3A\"auth0%7Cb2c-migrated-users*\"&search_engine=v3" \
--header "authorization: Bearer <access_token>"
# → []
Both queries confirm there are no visible users with this email or connection prefix.
4. Confirmed Legacy API Responses
LocalAccountUserExists returns expected JSON with success=true and valid legacy attributes.
Response sample:
{
“success”: true,
“user”: {
“user_id”: “355f33ba-d08b-4170-9ca5-0f68cf43b7c8”,
“email”: “rgarg2@ucsc.edu”,
“email_verified”: true,
“name”: “Ray (UCSC JIT test) Garg”,
“app_metadata”: { “migration_status”: “completed” }
}
}
5. Full Change Password Log Trace
CHANGE-PW DEBUG: user not in Auth0 → calling LEGACY_EXIST
CHANGE-PW LEGACY EXIST status=200 body={…}
CHANGE-PW DEBUG: BRANCH=CREATE JIT localUserId=355f33ba-d08b…
CHANGE-PW DEBUG: POST /api/v2/users connection=b2c-migrated-users-v2
CHANGE-PW DEBUG: POST /users response status=409 body={“statusCode”:409,“error”:“Conflict”,“message”:“The user already exists.”,“errorCode”:“auth0_idp_error”}
Key Observation
-
/users-by-emailconsistently returns zero results. -
/userscreation call fails with 409 Conflict. -
This occurs even on a brand-new connection, suggesting the duplication check may be tenant-wide or cached, possibly at the normalized_email index layer.
What I Suspect (not confirmed)
At first I suspected a stale identity index or tombstone for rishug123@yahoo.com left behind by a previously deleted user in another connection.
However, this 409 behavior now occurs for every email I test in the JIT Forgot Password flow:
-
rgarg2@ucsc.edu -
rishug123@yahoo.com -
ray.garg@zappsec.com
For each of these:
-
GET /api/v2/users-by-emailreturns[] -
Search by
user_idprefix forauth0|b2c-migrated-users*returns[]
That makes me wonder if there is:
-
Some tenant-wide uniqueness constraint or
-
Some soft-deleted / cached entry that is not visible via
/api/v2/usersbut still blocksPOST /api/v2/users.
Request for Engineering Assistance
Please investigate at the tenant-level identity store for any residual or orphaned entries associated with:
-
email: rgarg2@ucsc.edu or rishug123@yahoo.com or ray.garg@zappsec.com.I’m not certain this is the root cause, but given the behavior, I’d really appreciate a deeper backend check to rule this out. -
previous connection:
b2c-migrated-users -
current connection:
b2c-migrated-users-v2
If a stale entry exists in the internal store, please purge or release it so I can test creation again.
If not, I’d like confirmation of:
-
Whether Auth0 enforces tenant-wide uniqueness on
emailacross multiple custom DB connections. Even if it does, i have made sure that the emails im testing with dont exist in the user directory before i try the jit forgot password flow. -
Whether the
/usersendpoint may still reference cached soft-deleted entries. -
Any recommended remediation beyond recreating connections (which I’ve already done).
Why This Matters
This issue blocks our JIT password-reset onboarding flow, a key stage in our Auth0 adoption.
Without resolution, no migrated user can complete their reset and activation process.
The JIT login portion works flawlessly, so we know the code path and APIs are configured correctly, this is purely a user creation conflict preventing our production go-live.
Expected Behavior
If /api/v2/users-by-email returns [], POST /api/v2/users should succeed in creating a new user under the specified connection.
Request Summary
Please assist in:
-
Verifying and clearing any orphaned identity index for
rgarg2@ucsc.edu/rishug123@yahoo.com/ray.garg@zappsec.com -
Confirming whether Auth0 imposes a hidden tenant-wide uniqueness constraint between deleted records and new connection user creation
-
Providing any mitigation or workaround that avoids the duplicate user creation error that comes from testing the jit forgot password flow
Key questions for the Auth0 team
-
Under what conditions can
POST /api/v2/usersreturn409 The user already existswhen:-
GET /api/v2/users-by-emailreturns[], and -
No users appear for the
user_idprefix tied to this connection?
-
-
Are there internal uniqueness constraints (e.g. normalized email + connection) or soft-deleted records that are not visible via
/api/v2/usersbut still block creation? -
Is there any tenant-level cache or index that might need to be rebuilt or cleared by Auth0 engineering when many test users have been created/deleted across multiple custom DB connections?
-
Is there any recommended alternative pattern for:
-
JIT creation during Change Password,
-
When the user is still only in the legacy system, and
-
users-by-emailreturns no visible Auth0 record?
-
Thank you in advance.
I’ve spent several days reproducing this issue methodically across multiple connections and configurations, and I’m confident it’s not a misconfiguration or script-level bug. At this point I’ve exhausted what I can see from the configuration and scripts, and I’m leaning strongly toward this being an internal uniqueness/indexing issue rather than a script-level bug.
At this point, I’m requesting a backend-level review of the tenant’s identity index and duplicate enforcement logic.
P.S If needed, I can securely share screenshots via DM or email.