How to test 2FA OTP login using SMS codes with Playwright

The ultimate guide to testing OAuth one-time-password flows with real SMS MFA. Use Playwright to automate authentication tests with programmable TXT message APIs.

Using Playwright automation to test user sign up in a real application. We can login with a phone number we control in code and capture the SMS sent verification code.

What is OTP and why would I use it?

One time passwords (OTP) with MFA are a popular mechanism for securing web applications. Many applications today rely on multi-factor authentication (2FA/MFA) to login and signup users as it is considered more secure than a basic username/password flow.

Load
An example SMS verification form on our demonstration application

MFA means that a user must provide more than a simple password to access an application - they must also verify their identity by another means.

Usually secondary authentication is performed via an SMS one time password that is sent to a user's mobile phone. This code is unique and expires (hence the name OTP or one time password). The user must receive the code and enter it to a confirmation window during sign up. This proves that the user is who they say they are.

Testing MFA and OTP

Testing auth/OAuth using real phone numbers is an excellent way to automate your integration/end-to-end test suite and ensure that your application is properly handling user authentication and security. Using a phone number automation service such as MailSlurp we write a test as follows:

  • create a test phone number
  • use Playwright browser automation to load our application
  • sign up for the app using the test number
  • capture the inbound SMS code in tests and submit it to the app
  • confirm we gain access to the application

In this guide we will show you this exact test using a dummy OAuth SMS app located at playground-sms.mailslurp.com.

Playwright setup

We will use Microsoft's great Playwright tool (avaible in C#, Java, Typescript, NodeJs, and Python) to write an automated browser test that loads our application in chrome and performs checks. We will use Typescript for this example. (Find the code on Github.)

Create a test project

First create a new project on your machine with NodeJS.

mkdir test
cd test
npm init -y

Install playwright

Setup playwright by installing and configuring it.

npm init playwright@latest

You'll see something like so in your directory:

playwright.config.ts
package.json
package-lock.json
tests/
  example.spec.ts
tests-examples/
  demo-todo-app.spec.ts

Running tests

Execute tests using the npx playwright test command and view the results in your terminal or with the npx playwright show-report command. Now let's write some tests for MFA login.

Testing user sign up

To test authentication end-to-end using MFA and SMS we need to use Playwright to load our application, fill out a sign-up form, then capture an SMS code and submit it. Let's do that.

Load the create account page

Create account page
Our dummy app asks for a phone number and password during sign up.

To begin testing use the page object in your test to load the playground login screen:

// load playground app
await page.goto("https://playground-sms.mailslurp.com");
await page.click('[data-test="sign-in-create-account-link"]');

Use a test phone number

We have created a US phone number in the MailSlurp dashboard and we can fetch it in our tests using the MailSlurp Javascript client.

// fetch a phone number in US from our account
const mailslurp = new MailSlurp({ apiKey })
const { content }= await mailslurp.phoneController.getPhoneNumbers({
  phoneCountry: GetPhoneNumbersPhoneCountryEnum.US
})
const phone = content?.[0]!!

Fill sign-up form

Next we can use the phone number to fill out the username and password form:

const password = "test-password-123"
// fill sign up form
await page.fill('input[name=phone_line_number]', phone.phoneNumber.replace("+1", ""));
await page.fill('input[name=password]', password);

The form will be filled in Playwright like so:

Fill form
Playwright will use our automated phone number to create a new account.

Wait for and capture SMS

Now we can use MailSlurp to wait for an expected SMS to arrive at our phone number and extract the verification code:

await page.click('[data-test="sign-up-create-account-button"]');
// wait for verification code
const sms = await mailslurp.waitController.waitForLatestSms({
  waitForSingleSmsOptions: {
    phoneNumberId: phone.id,
    unreadOnly: true,
    timeout: 30_000,
  }
})
// extract the confirmation code (so we can confirm the user)
const code = /([0-9]{6})$/.exec(sms.body)?.[1]!!;

Confirm user SMS OTP

Use the code we extracted to fill the username field:

// enter confirmation code
await page.fill('[data-test="confirm-sign-up-confirmation-code-input"]', code);
Confirm
Confirm the user by submitting the OTP passcode

Then submit the form:

await page.click('[data-test="confirm-sign-up-confirm-button"]');

Sign in and view user data

Now sign into the app:

// fill out username (email) and password
await page.fill('[data-test="username-input"]', phone.phoneNumber);
await page.fill('[data-test="sign-in-password-input"]', password);
Sign in
Sign in after confirmation

Submit the login form and expect a greeting:

// submit
await page.click('[data-test="sign-in-sign-in-button"]');
await page.waitForSelector("[data-test='greetings-nav']")

If successful we will see the greeting screen (a happy dog):

greeting

Conclusion

MFA login using two-factor authentication is an important technology for modern web apps. Testing OAuth SMS flows using SMS services like MailSlurp is a great way to verify user authentication in your application. See the developer docs for more information.

Related content

Test SMS phone numbers

Read text messages in code and webhooks to test applications and authentication end-to-end. Real phone numbers for developers and QA testers.

Golang email library for sending and reading emails

Golang Email Library for sending and receiving emails in Go over SMTP or HTTP/S.

Email for testing

Test email accounts for email testing. Alternatives to Mailinator, MailTrap, Mailosaur and more.

Best SMS apps for android

Best SMS apps for android

How to wait for Selenium to start during Codeception tests

Example tutorial for how to wait until webdriver and Selenium have started during Codeception PHP tests

Email API for email marketing and more

APIs for email marketing and social campaign testing. Send, receive, validate and test emails in code and online.

How to Schedule a Text Message

How to Schedule a Text Message

The Way to Ship a Text via Email (And an email through text): A Simple Guide

The Way to Ship a Text via Email (And an email through text): A Simple Guide

How to test an email address

Test email accounts for testing email addresses in code or online. Create fake email accounts for testing.

Instant messaging platforms compared

Use SMS/TXT messaging platforms to send and receive text at scale

How to start selenium in a background process and wait for it to start

Spawn Selenium server process before tests start for easier acceptance testing.

What is an SMS message segment?

Text messages are split into SMS segments when sent.

CypressJS Example

Test email sign-up. password verification and more with Cypress JS and MailSlurp.

CypressJS Email Testing

Use real email accounts in CypressJS to test user sign-up, email verification, and more.

Golang mail Library (SMTP)

How to send and receive emails in Go (test email addresses).

Java JVM Examples

Test email sending and receive emails without a mail server.

TestNG Selenium Java Example

Testing user sign up in Java using TestNG and MailSlurp test email accounts

Codeception PHP acceptance testing using real email address APIs

Write acceptance tests in PHP with real email addresses using Codeception and MailSlurp

PHP Email Test Plugins: send and receive email in PHPUnit (example code)

How to send and receive emails in PHPUnit tests.

PyTest Email Testing

Send and receive email in Pytest Python tests.

Java, Selenium

Receive emails in Java test suites using MailSlurp, Junit, and Selenium.

Receive email in PHP: using MailSlurp to send and receive emails

Test email in PHP using real email addresses

Testing authentication using real email addresses in Ruby with Capybara, Cucumber, and Selenium

Cucumber example project using Capybara to test user authentication using real email addresses.

Test applications with real emails using Serenity BDD, JBehave and Selenium

Email acceptance testing with Serenity and MailSlurp. Test applications with real email addresses.

Specflow user sign-up testing with MailSlurp accounts

How to test .NET authentication and sign-up using real email accounts with MailSlurp and SpecFlow.

Jest, Puppeteer

Test email accounts in React with Jest and Puppeteer. Send and receive emails in Javascript.

.NET Selenium C#

Send and receive email in DotNET Nunit tests using Selenium and MailSlurp.

Cucumber, Ruby

Generate test email accounts with Ruby and Cucumber. Test email sign-up, password verification and more.

Webdriver, JS, WDIO

Test email related processes like sign-up and verification using WDIO WebDriver and MailSlurp.

TestCafe end-to-end MFA testing for user sign-up and email verification

End-to-end testing with MailSlurp, NodeJS, and TestCafe.

How To Test Emails Before You Send

There are many free tools to test emails before sending. This can help prevent spam warnings and increase deliverability.

Testing OTP password link username and password for 2 factor authentication (2FA)

Testing OTP password link username and password for 2 factor authentication (2FA)

Test email address

Free test email address for testing emails online with web dashboard or REST API.

How to test 2FA OTP login using SMS codes with Playwright

The ultimate guide to testing OAuth one-time-password flows with real SMS MFA. Use Playwright to automate authentication tests with programmable TXT message APIs.

Testing guide

Integration testing with disposable email accounts using CypressJS, Selenium and many other frameworks. Test OTP password login, transactional emails, notifications and more.

Testing SMS based authentication (2FA/OTP)

How to test applications that use two-factor authentication and one-time TXT message passwords.

Testing email with Cypress test email accounts

Test email accounts for CypressJS. End-to-end testing with real email addresses using MailSlurp Cypress plugin.

Testing Webhooks

How to test HTTP webhooks using MailSlurp test hooks.

Receive inbound SMS TXT messages with API and webhooks

How to create phone numbers and read text messages in code and tests

Testing Email with Cypress JS and MailSlurp

Email testing with Cypress JS

Ready to dive in?Start building email applications today.