We’re currently working on building a portal for our users and were recommended to use Auth0 for our use case. I’d like to share our intended flow below and get your advice on whether we should make any changes to align with Auth0 best practices:
Our Use Case
User Identity Verification: During signup, users provide their name, email, and the last 4 digits of their SSN. This information is validated against our backend API to ensure authenticity.
Email Verification Flow: Upon successful identity validation, users receive a verification email and are directed to set up a password after confirming their email.
Two-Factor Authentication (2FA): During login, users authenticate using email + password, and we enforce an additional OTP verification sent via SMS for enhanced security.
Current Status
Using Auth0, I was able to customize the signup form and add a Pre-User Registration Action to validate users against our backend. That part is working correctly. However, I’m not sure how to move forward with the email verification → login flow portion, and would appreciate your guidance on the best way to enforce this using Auth0.
Could you confirm if our approach is aligned with Auth0 best practices, and recommend any adjustments we should make?
Regarding your current implementation, I would advise the following approach:
The password must be used as an Authentication method unless your application is set up to use a different method (such as passwordless), meaning that you would need to allow the users to set up a password when signing up on your application and then enforce email verification by going to the database connection you are using for your application → Attributes → Email → Configure → Verify Email on signup. Unless the user verifies their email, you can restrict access to the application.
Unfortunately, you will not be able to allow users to set a password after they have verified their email if you are looking to authenticate these users using email + password.
Once the user is created, you can enforce SMS MFA via a PostLogin Trigger
An alternative approach would be:
Build your own UI where the users enter their details (name, email and last 4 digits of the SSN).
Create an user with a dummy password using the Management API
Thank you for your response. It worked! I was able to create a custom signup page to collect email and the last 4 digits of SSN, then use the Management API to create a user with a dummy password and send a verification link. Once the user clicks the link, I allow them to set their password.
I am still using the Auth0-hosted login page for login. Would you consider it a concern or not best practice to use a custom signup flow but still rely on the Auth0-hosted login page?
Also, I need some help with MFA:
Environment
Framework: Next.js App Router (v15)
Auth: @auth0/nextjs-auth0 v4.9.0
MFA: SMS (Auth0 hosted, Twilio as provider)
Scale: Large user base (millions) — need simple, fast, maintainable setup
MFA requirement
On every login, we need to fetch the user’s phone number from our backend API and send the verification code to that number.
Can you please guide me on how best to achieve this with Auth0 recommended practices?
As far as I am concerned regarding your implementation, it is not frowned upon to have your own custom signup flow while relying on the Auth0 Universal Login at the same time. If the Universal Login customization or flow presents any kind of limitation (such as in your use case where you want to prevent the user to set their password), you can rely on your own custom signup UI. However, the only concern that I can think of at the moment regarding this would be to also handle any kind of error that can happen during signup (ex: the user already exists).
Regarding the MFA implementation, why do you need to fetch their phone number from your backend API?
Can you not prompt the users to add a phone number as well in the signup flow and set in on the account? If you have done so, you can simply use actions to enforce MFA on any login. You can learn how to do so by reading our documentation on Customizing MFA. Basically, you would need to enroll the users to MFA if they are not enrolled or challenge them if they are. For example:
exports.onExecutePostLogin = async (event, api) => {
if (event.user.enrolledFactors.length) {
// already enrolled, challenge
api.authentication.challengeWith({type: 'phone'})
}
else {
// not enrolled; choose a factor to enroll now
api.authentication.enrollWith({type:'phone');
}
};
This way, even if they have signed up with a phone number or not, they will be asked to enroll and adding a phone number for the MFA or they will be challenged if they are already enrolled.
Thanks for pointing that out. In my case, I’m already handling the scenario where a user exists:
I am
Checking with mgmtFindUsersByEmail(email)
Updating app_metadata if needed
If the user is already verified → returning a flag (alreadyVerified: true)
On the UI, telling the user “Your account is already verified, please proceed to login.”
So the duplicate signup case is already covered in my flow.
And for MFA
In our case, we’re using a third-party backend system where we don’t control how phone numbers are managed. Users can change their phone number directly in that backend, and our frontend doesn’t get notified of those changes.
That’s why our plan is to call the backend API on every login attempt to fetch the latest phone number, instead of relying on what’s stored in Auth0. This way, if the user updates their phone number in the backend, we always have the freshest data for MFA.
I see. Thank you for shading more light on the matter.
I believe the best approach would be to use the Management API to Update All the Authentication Settings. This way, once the user updates their phone number, you can make a request to update the enrolled MFA to the new number instead of having the user’s re-enroll by disabling their MFA (since SMS MFA enrollment is number specific).
I believe this operation might be the most suitable one since the phone number is updated dynamically in your backend .
If I can help with anything else or if you have any challenged on implementing this, let me know!
Thank you for clarifying and for the helpful guidance . I do have a couple more questions:
How can we remove the “Remember my device for 30 days” checkbox from the MFA screen?
To customize the Universal Login and MFA screens (branding, removing Auth0 icons, etc.), do we need to set up a custom domain and use page templates as prerequisites? If yes , How much control we will have on UI Customization?
We’ve disabled sign-ups on the Database connection (so the Sign up tab is hidden)
What we want
We have a custom signup page in our app (/signup) that does pre-user validation against our backend . We’d like the hosted New Universal Login Provider (login/MFA) to show a link or button that sends users back to our app’s /signup page.
Is there any supported way in New Universal Login provider to add a custom link/button that goes to our app’s /signup?