How to test Multifactor Authentication (MFA/2FA) with Mailosaur

Learn how to test multifactor authentication using virtual authentication devices and/or SMS testing with Mailosaur.

What is Multifactor Authentication?

Products and websites often use something called “Two-Step Verification” or “Multifactor Authentication” (MFA), whereby a user is required to provide multiple ‘factors’ to prove they are who they claim to be. Three common kinds of factor are:

  • Something you know: Your password, or a memorable date.
  • Something you have: Your smartphone, or a secure USB key.
  • Something you are: Facial recognition, your fingerprint, etc.

Using the Mailosaur API you can test MFA functionality, either by using Mailosaur’s SMS Testing functionality, or by creating virtual security devices.

Using Virtual Security Devices

One of the most common ways to implement multifactor authentication is via an authenticator app, like Google Authenticator. Creating a Virtual Security Device allows you to mimic this functionality, by generating the same one-time passwords (OTP) that an authenticator app would. This makes it easy to create end-to-end tests that give you full coverage of the most sensitive areas of your product or service.

Automating OTP tests with virtual devices

For most end-to-end tests, you’ll simply need a way of getting the current one-time password (OTP) for a given shared secret (i.e. the value you would ask your user to setup Google Authenticator with).

You can do this with a couple of lines of code, using the otp method to get the current one-time password for a secret:

const sharedSecret = 'ONSWG4TFOQYTEMY=';
const currentOtp = await mailosaur.devices.otp(sharedSecret);

console.log(currentOtp.code); // "564214"
const sharedSecret = 'ONSWG4TFOQYTEMY=';

cy.mailosaurGetDeviceOtp(sharedSecret)
  .then(currentOtp => {
    cy.log(currentOtp.code); // "564214" 
  });
shared_secret = "ONSWG4TFOQYTEMY="
current_otp = mailosaur.devices.otp(shared_secret)

print current_otp.code # "564214"
String sharedSecret = "ONSWG4TFOQYTEMY=";
OtpResult currentOtp = mailosaur.devices().otp(sharedSecret);

System.out.println(currentOtp.code); // "564214"
var sharedSecret = "ONSWG4TFOQYTEMY=";
var currentOtp = mailosaur.Devices.Otp(sharedSecret);

Console.WriteLine(currentOtp.code); // "564214"
shared_secret = 'ONSWG4TFOQYTEMY='
current_otp = mailosaur.devices.otp(shared_secret)

print(current_otp.code) # "564214"
$sharedSecret = 'ONSWG4TFOQYTEMY=';
$currentOtp = $mailosaur->devices->otp($sharedSecret);

print($currentOtp->code); // "564214"
sharedSecret := "ONSWG4TFOQYTEMY="

currentOtp, _ := m.Devices.Otp(sharedSecret)
fmt.Println(currentOtp.Code) // "564214"

Creating a device for longer-term testing

If you need a device for a longer-period of time, you can simply create one within the Mailosaur Dashboard, or via the API:

  1. Go to the Devices page in the Mailosaur Dashboard.
  2. Click on Create Device at the top of the page.
  3. Next you need to provide the shared ‘secret’ for the account you are testing. This can be provided either by uploading an image of a QR Code, or by pasting in the secret itself.
  4. Once you have provided the secret, you will be able to give your device a recognisable name.
  5. When you are finished, click Create Device.
await mailosaur.devices.create({
  name: 'Test account',
  sharedSecret: 'ONSWG4TFOQYTEMY='
});
cy.mailosaurCreateDevice({
  name: 'Test account',
  sharedSecret: 'ONSWG4TFOQYTEMY='
});
name = "Test account"
shared_secret = "ONSWG4TFOQYTEMY="
options = DeviceCreateOptions(name, shared_secret)

mailosaur.devices.create(options)
DeviceCreateOptions options = new DeviceCreateOptions();
options.withName("Test account")
  .withSharedSecret("ONSWG4TFOQYTEMY=");

mailosaur.devices().create(options);
mailosaur.Devices.Create(new DeviceCreateOptions()
  {
      Name = "Test account",
      SharedSecret = "ONSWG4TFOQYTEMY="
  }
);
options = Mailosaur::Models::DeviceCreateOptions.new()
options.name = 'Test account'
options.shared_secret = 'ONSWG4TFOQYTEMY='

mailosaur.devices.create(options)
$options = new DeviceCreateOptions();
$options->name = 'Test account';
$options->sharedSecret = 'ONSWG4TFOQYTEMY=';

$mailosaur->devices->create($options);
m.Devices.Create(&DeviceCreateOptions{
  Name:         "Test account",
  SharedSecret: "ONSWG4TFOQYTEMY=",
})

Retrieving the current one-time password

You can get the current code for a saved security device within the Mailosaur Dashboard, or via the API:

  1. Go to the Devices page in the Mailosaur Dashboard.
  2. Find the device you need.
  3. Click the Reveal one-time password button.
  4. You’ll now see the current code, and can click on it to quickly copy the current value to your clipboard.
const result = await mailosaur.devices.list();
const targetDevice = result.items[0];

const otpResult = await mailosaur.devices.otp(targetDevice.id);
cy.mailosaurListDevices().then(result => {
  const targetDevice = result.items[0];
  return cy.mailosaurGetDeviceOtp(targetDevice.id);
}).then(otpResult => {
  cy.log(otpResult.code);
});
result = mailosaur.devices.list()
target_device = result.items[0]

otp_result = mailosaur.devices.otp(target_device.id)
DeviceListResult result = mailosaur.devices().list();
Device targetDevice = result.items().get(0);

String otpResult = mailosaur.devices().otp(targetDevice.id());
var result = mailosaur.Devices.List();
var targetDevice = result.Items[0];

var otpResult = mailosaur.Devices.Otp(targetDevice.Id);
result = mailosaur.devices.list()
target_device = result.items[0];

otp_result = mailosaur.devices.otp(target_device.id)
$result = $mailosaur->devices->all();
$targetDevice = $result->items[0];

$otpResult = $mailosaur->devices->otp($targetDevice->id);
devices, _ := m.Devices.List()
otpResult := m.Devices.Otp(devices.Items[0].Id)

Deleting a device

You can delete a virtual security device within the Mailosaur Dashboard, or via the API using the device’s unique identifier:

  1. Go to the Devices page in the Mailosaur Dashboard.
  2. Find the device you want to delete, and click the trash can icon.
  3. Confirm that you’ve selected the right device for deletion.
await mailosaur.devices.del('{DEVICE_ID}');
cy.mailosaurDeleteDevice('{DEVICE_ID}');
mailosaur.devices.delete("{DEVICE_ID}")
mailosaur.messages().delete("{DEVICE_ID}");
mailosaur.Devices.Delete("{DEVICE_ID}");
mailosaur.devices.delete('{DELETE_ID}')
$mailosaur->devices->delete('{DEVICE_ID}');
m.Devices.Delete("{DEVICE_ID}")

Using SMS

You can also use Mailosaur to test multifactor authentication processes that make use of SMS. For more information on this, check out our sms testing guide.