Need Help Enforcing Email Uniqueness Across Social and Database Connections

It could be worth taking a step back to think about the limitations and quirks of email addresses and the management API, and then define your own expectations.

Matching email addresses across the tenant can be difficult because:

  1. /users-by-email is case-sensitive. (And alternative search functions are only eventually consistent.) [1]
  2. Custom database email addresses are stored in lower-case in Auth0.
  3. But social email addresses preserve the case of the federated provider (they may follow the RFCs which technically make email addresses case-sensitive).

This can lead to a scenario like:

  1. Alice@example.com registers using a federated provider that preserves case.
  2. alice@example.com begins to register using a custom database (lower-cased).
  3. The action searches getUsersByEmail("alice@example.com") which fails to locate Alice@example.com.
  4. If your resource server intended to treat Alice and alice as truly unique users (unlikely), then this is OK. But if they should be treated the same, alice will also complete signup/login and there will be unexpected duplicated users.

This can also unfold in the other direction: first register a lower-cased custom database user email, then a mixed-case federated provider user email. But in that situation, it might be a mitigation to lower-case the event email address before searching. However, if you ever intend to have two or more federated providers excluding each other, lower-casing the event email address may not be enough.

As an alternative approach, given there is already some HTTP request to your backend /public/users endpoint, consider using that as a source of truth for registered email addresses as your application sees it. Your application can choose its own interpretation of email address normalization like lower-case always, or preserve but lower-case on compare only, or truly distinguish case, and/or whether to deny or collapse or separate plus addresses (alice+test@example.com), and/or internationalization handling, etc. So in the post-login action: optimistically submit the user to your backend; then only if the backend accepts the submission and responds successfully, continue post-login, else deny.