Testing OTP codes in Selenium with dummy authenticators
Secure application are often a complex process involving multiple factors of authentication. Many developers use services like Auth0, Firebase and Azure AD/Entra to build user login and sign up flows that connect applications to enterprise IdPs using MFA and 2FA flows. These methods often involve receiving verification codes and time-based one-time passwords (TOTP) to verify accounts. Hint: TOTP stands for time-based one-time password. You might have used TOTP with Google Authenticator or Duo on a mobile device. With strict compliance and regulatory requirements testing these apps end-to-end is crucial. This requires special QA techniques and disposable authenticator devices which we will demonstrate in this post. For this example we will use Selenium and Java but the methods for testing TOTP passcodes apply to any integration testing framework. What we are testing Let's test a typical MFA authentication flow that uses an Auth0 integration and time-based one-time pass codes to sign-up and verify user accounts. The process looks like this: We have a basic VueJS app that uses the Auth0 vue library to launch the authentication flow and handle the user authentication. The process is as follows: User opens the Vue application and navigates to the sign-up page. User enters their email and password to create a new account. Application prompts the user to set up MFA (TOTP). Auth0 displays a QR code for TOTP configuration. User scans the QR code with an authenticator app (or test device). User enters the generated TOTP code to verify setup. Upon successful verification, the user is logged in and MFA is enabled for future logins. Note you can find all the code for this example on Github Testing requirements In order to test this reliably and without manual intervention we will need: Disposable user email accounts Virtual MFA Authenticators Luckily, MailSlurp is a free service that provides all these and more. We can use the official MailSlurp Java SDK to create email accounts and generate new OTP codes that work seamlessly with IdPs like Auth0. How to test OTP in Selenium Okay let's get started. We assume you have a selenium Java project setup up in maven and the necessary drivers installed. In order to create email accounts and TOTP devices for this test we will also need the mailslurp-client-java library we can obtain from maven central. Install MailSlurp For maven, add to your pom.xml: com.mailslurp mailslurp-client-java 16.2.1 For Gradle add the following: implementation group: 'com.mailslurp', name: 'mailslurp-client-java', version: '16.2.1' Note: MailSlurp is free, you just need to create an API KEY We can then import MailSlurp in our tests like so: import com.mailslurp.apis.InboxControllerApi; import com.mailslurp.apis.MfaControllerApi; import com.mailslurp.clients.ApiClient; import com.mailslurp.clients.ApiException; import com.mailslurp.models.CreateInboxDto; import com.mailslurp.models.CreateTotpDeviceOtpAuthUrlOptions; Open app and begin login Great, now for our test. The first step will be to open our demo application that has the Auth0 library installed. This app will begin the MFA flow that asks for a TOTP code. // navigate to our test app that uses Auth0 MFA for authentication driver.get(APP_URL); String body = wait.until(visibilityOfElementLocated(By.tagName("body"))).getText(); assertTrue(body.contains("Login"), "Expect home page"); Once opened we click the login button: // click new sign up wait.until(elementToBeClickable(By.id("qsLoginBtn"))).click(); wait.until(elementToBeClickable(By.cssSelector("a[href^='/u/signup']"))).click(); Create an isolated test account In order to sign-up we need an email address. Let's create one in MailSlurp. This will be a real disposable email account that can send and receive emails. // setup mailslurp api client var apiClient = new ApiClient(); apiClient.setApiKey(MAILSLURP_API_KEY); // create disposable email account var inboxController = new InboxControllerApi(apiClient); var inbox = inboxController.createInboxWithOptions(new CreateInboxDto().expiresIn(300_000L)).execute(); String emailAddress = inbox.getEmailAddress(); String password = "testPassword123!"; Fill sign-up form Once we have an email account we use it to fill out the username. Next we add a randomized password and click submit. // fill in the sign up form and submit wait.until(visibilityOfElementLocated(By.id("email"))).sendKeys(emailAddress); wait.until(visibilityOfElementLocated(By.id("password"))).sendKeys(password); wait.until(elementToBeClickable(By.cssSelector("button[type='submit']"))).click(); Once filled the app will look like this: After submitting the sign-up we will see a QR code in order to attach a TOTP device: Extract OTPAuth url A MFA TOTP connection typically involves a QR code th

Secure application are often a complex process involving multiple factors of authentication. Many developers use services like Auth0, Firebase and Azure AD/Entra to build user login and sign up flows that connect applications to enterprise IdPs using MFA and 2FA flows. These methods often involve receiving verification codes and time-based one-time passwords (TOTP) to verify accounts.
Hint: TOTP stands for time-based one-time password. You might have used TOTP with Google Authenticator or Duo on a mobile device.
With strict compliance and regulatory requirements testing these apps end-to-end is crucial. This requires special QA techniques and disposable authenticator devices which we will demonstrate in this post. For this example we will use Selenium and Java but the methods for testing TOTP passcodes apply to any integration testing framework.
What we are testing
Let's test a typical MFA authentication flow that uses an Auth0 integration and time-based one-time pass codes to sign-up and verify user accounts. The process looks like this:
We have a basic VueJS app that uses the Auth0 vue library to launch the authentication flow and handle the user authentication. The process is as follows:
- User opens the Vue application and navigates to the sign-up page.
- User enters their email and password to create a new account.
- Application prompts the user to set up MFA (TOTP).
- Auth0 displays a QR code for TOTP configuration.
- User scans the QR code with an authenticator app (or test device).
- User enters the generated TOTP code to verify setup.
- Upon successful verification, the user is logged in and MFA is enabled for future logins.
Note you can find all the code for this example on Github
Testing requirements
In order to test this reliably and without manual intervention we will need:
- Disposable user email accounts
- Virtual MFA Authenticators
Luckily, MailSlurp is a free service that provides all these and more. We can use the official MailSlurp Java SDK to create email accounts and generate new OTP codes that work seamlessly with IdPs like Auth0.
How to test OTP in Selenium
Okay let's get started. We assume you have a selenium Java project setup up in maven and the necessary drivers installed. In order to create email accounts and TOTP devices for this test we will also need the mailslurp-client-java
library we can obtain from maven central.
Install MailSlurp
For maven, add to your pom.xml
:
com.mailslurp
mailslurp-client-java
16.2.1
For Gradle add the following:
implementation group: 'com.mailslurp', name: 'mailslurp-client-java', version: '16.2.1'
Note: MailSlurp is free, you just need to create an API KEY
We can then import MailSlurp in our tests like so:
import com.mailslurp.apis.InboxControllerApi;
import com.mailslurp.apis.MfaControllerApi;
import com.mailslurp.clients.ApiClient;
import com.mailslurp.clients.ApiException;
import com.mailslurp.models.CreateInboxDto;
import com.mailslurp.models.CreateTotpDeviceOtpAuthUrlOptions;
Open app and begin login
Great, now for our test. The first step will be to open our demo application that has the Auth0 library installed. This app will begin the MFA flow that asks for a TOTP code.
// navigate to our test app that uses Auth0 MFA for authentication
driver.get(APP_URL);
String body = wait.until(visibilityOfElementLocated(By.tagName("body"))).getText();
assertTrue(body.contains("Login"), "Expect home page");
Once opened we click the login button:
// click new sign up
wait.until(elementToBeClickable(By.id("qsLoginBtn"))).click();
wait.until(elementToBeClickable(By.cssSelector("a[href^='/u/signup']"))).click();
Create an isolated test account
In order to sign-up we need an email address. Let's create one in MailSlurp. This will be a real disposable email account that can send and receive emails.
// setup mailslurp api client
var apiClient = new ApiClient();
apiClient.setApiKey(MAILSLURP_API_KEY);
// create disposable email account
var inboxController = new InboxControllerApi(apiClient);
var inbox = inboxController.createInboxWithOptions(new CreateInboxDto().expiresIn(300_000L)).execute();
String emailAddress = inbox.getEmailAddress();
String password = "testPassword123!";
Fill sign-up form
Once we have an email account we use it to fill out the username. Next we add a randomized password and click submit.
// fill in the sign up form and submit
wait.until(visibilityOfElementLocated(By.id("email"))).sendKeys(emailAddress);
wait.until(visibilityOfElementLocated(By.id("password"))).sendKeys(password);
wait.until(elementToBeClickable(By.cssSelector("button[type='submit']"))).click();
Once filled the app will look like this:
After submitting the sign-up we will see a QR code in order to attach a TOTP device:
Extract OTPAuth url
A MFA TOTP connection typically involves a QR code that has a special link encoded in it. This link follows a pattern like:
otpauth://totp/dev-28vff4a6lyu4gize:contact%40mailslurp.dev?secret=LJCTOYKGGBAWCMSHJRZGITCVLIXCG4JY&issuer=dev-28vff4a6lyu4gize&algorithm=SHA1&digits=6&period=30
Notice the optauth://
schema. The rest of the URL contains various elements but the most important is the secret
. This is a base32 encoded secret that allows the TOTP device to generate codes. In our test application we can extract the full OTP Auth url by reading it from the dom. Auth0 adds a special data
attribute that contains this value:
We can extract this code like this:
// expect MFA QR code to be displayed then extract the otpauth:// URI from the QR code
wait.until(visibilityOfElementLocated(By.cssSelector("[data-qr-data]")));
String optAuthUrl = driver.findElement(By.cssSelector("[data-qr-data]")).getAttribute("data-qr-data");
assertTrue(optAuthUrl.startsWith("otpauth://"), "Expect otpauth:// URI in QR code");
Note: If you can't see the OTP Auth URL in the dom you can use various other methods to connect the TOTP device (including passing a secret directly, passing a screenshot of the QR code, or the QR code image source). See the TOTP docs
Create virtual TOTP device
Now we need to use an authenticator device for our user to verify the account. We will use MailSlurp to generate an TOTP device using the OTP auth url:
// next create a TOTP authenticator device in MailSlurp
var mfaController = new MfaControllerApi(apiClient);
var virtualTotpDevice = mfaController.createTotpDeviceForOtpAuthUrl(new CreateTotpDeviceOtpAuthUrlOptions()
// pass the QR code otpauth:// URI to MailSlurp
.otpAuthUrl(optAuthUrl)
).execute();
This device will let us generate valid confirmation codes for submitting to the app.
Generate time based one time password
Next we can generate a valid OTP code using the SDK. This code will be valid for a short time as specified in the arguments. We need to then submit it to Auth0 to finish the sign-up:
// now generate a secret code from the TOTP device and submit it
var oneTimeCode = mfaController.getTotpDeviceCode(virtualTotpDevice.getId())
// ensure code is valid long enough to be entered by selenium
.minSecondsUntilExpire(10)
.execute().getCode();
wait.until(visibilityOfElementLocated(By.id("code"))).sendKeys(oneTimeCode);
// submit the code
wait.until(elementToBeClickable(By.cssSelector("button[data-action-button-primary=\"true\"]"))).click();
wait.until(elementToBeClickable(By.cssSelector("button[name='action'][value='accept']"))).click();
The submission looks like this:
And afterwards we need to accept the connection:
Assert account is verified
Voila! Now we have a logged in user with a connected MFA device. We can assert that by checking the user profile:
// expect login home page and email address in the profile dropdown
wait.until(elementToBeClickable(By.id("profileDropDown"))).click();
wait.until(visibilityOfElementLocated(By.cssSelector("#profileDropDown + .dropdown-menu")));
String dropdownText = driver.findElement(By.cssSelector("#profileDropDown + .dropdown-menu")).getText();
assertTrue(dropdownText.contains(emailAddress), "Dropdown menu should contain the email address");
Here is a screenshot:
Testing logout / login
Now that our full sign-up is complete we can also test the logout and login process to check that the MFA TOTP connection functions:
// click logout
wait.until(elementToBeClickable(By.id("qsLogoutBtn"))).click();
// then try login again
wait.until(elementToBeClickable(By.id("qsLoginBtn"))).click();
wait.until(visibilityOfElementLocated(By.id("username"))).sendKeys(emailAddress);
wait.until(visibilityOfElementLocated(By.id("password"))).sendKeys(password);
wait.until(elementToBeClickable(By.cssSelector("button[data-action-button-primary=\"true\"]"))).click();
// expect to see MFA code entry field again after login
wait.until(visibilityOfElementLocated(By.id("code")));
Once we log in with the email and password we generated we can see the MFA prompt asking for a new code. Using the same TOTP device we can generate that code and submit it:
// get another TOTP code from the same device and submit it to complete login
var oneTimeCode2 = mfaController.getTotpDeviceCode(virtualTotpDevice.getId())
.minSecondsUntilExpire(10)
.execute().getCode();
wait.until(visibilityOfElementLocated(By.id("code"))).sendKeys(oneTimeCode2);
wait.until(elementToBeClickable(By.cssSelector("button[data-action-button-primary=\"true\"]"))).click();
// expect logged in screen again
wait.until(elementToBeClickable(By.id("profileDropDown"))).click();
wait.until(visibilityOfElementLocated(By.cssSelector("#profileDropDown + .dropdown-menu")));
String dropdownText2 = driver.findElement(By.cssSelector("#profileDropDown + .dropdown-menu")).getText();
assertTrue(dropdownText2.contains(emailAddress), "Dropdown menu should contain the email address");
Conclusion
We just demonstrated how to test a multifactor authentication user flow using Selenium and MailSlurp's free test TOTP API. Using dummy authenticator devices is a great way to verify security compliance and app functionality in QA and automation environments.
To add MFA testing to your own application or IdP see the documentation or connect with our team.