Security without compromise: Making MFA work for us

November 24, 2022 Published by Maor Zelinger QA & Automation Engineer, Netanel Katzburg Team Lead

tl;dr

In this blog post we explain:

  • How to run automated tests that require login using Google without being concerned about the MFA being hacked.
  • How we extracted the secret used to create a multi-factor authentication code from the QR image used to activate it.
  • How to use totp-generator to implement a client as part of an automated test.

Introducing the problem

At Reco, like many other companies that had only recently begun their journey, and have gathered their first few customers and design partners, we shortly discovered our need for an infrastructure to test our SaaS product web pages.

In order to provide our R&D group with a sense of security in a rapidly changing environment, we want to test the UI of our website automatically. Namely, end-to-end tests to make sure the functionality of our product’s website doesn’t break in between releases. This enables faster and more confident releases.

Naturally, we have some security policies in place to guard our web accounts. One of our security policies requires each user to have Multi-Factor Authentication (MFA) enabled for their accounts.

As a security product company, we couldn’t compromise our SOC2 security compliance and lower our standards for test users. So, when we started designing our automatic testing framework one of the first things we had to solve was how to automate the login process without creating a breach that someone could use against us.

Test user authentication

We use Google authentication for login, which is based on OAuth 2.0. This protocol is the industry standard for authorization flows for web applications, desktop applications, and mobile phones. The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner - by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.

What is MFA?

Multi-factor authentication (MFA) is an approach to securing web accounts and the data that is saved in those accounts. When you enable MFA in your web services (e.g. e-mail), users must provide a combination of two or more authenticators to verify their identity before access to your service is granted. Using MFA provides better protection for accounts than just using a password because it requires something you are or something you have in addition to something you know.

What are Google’s MFA login options and why don't they qualify for our automatic testing framework?

Let's take a look at Google’s MFA login options:

  1. Google prompts - Requires a physical device and a manual action.
  2. Authenticator app - No API, also requires a physical device.
  3. Voice or text message - Could be used with programmable communication tools like Twilio, which introduces additional cost and complexity.
  4. Backup codes - Only 10 at a time, need to be manually created and are one-time passcodes.

Reviewing all the options we couldn’t spot an immediate solution that could be automated as part of our testing process.

Solution: Creating an “alternative” MFA

After some research of the underlying technologies of the different options, we found that the Google authenticator uses the Time-based one-time password algorithm. So we decided to mock the application using a Node.js client.

To implement the algorithm we used the totp-generator package to create the 6-digit code. To get the secret from Google, we needed to extract it from the QR code made for the Authenticator app.

Let's get down to business, and get the secret:

  • Start setting up MFA for a Google user in this link.
  • Select the Authenticator option.
  • Download the QR code and decode it. The output should look like this:
otpauth://totp/Google%3Ajohnd%40reco.ai?secret=XXXXXXXXXXXXXXXXXXXXX&issuer=Google
  • Save the secret in a secret manager or a similar solution that is accessible and not public.

Now that we have the secret we must finish the MFA setup process.

This is important for two reasons:

  • You need to finish the process to activate the MFA for this user.
  • For local debugging, if you want to log in using the test user.

Scan the QR code using the Google authenticator app on your mobile phone. Click next and type the 6-digit code from the app. If you got a success message - you are good to go!

Implementation example

At Reco we use Playwright, written in Typescript. Here is some code not from StackOverflow you can copy and paste 😉.

import { test, expect } from '@playwright/test';
import totp from 'totp-generator';
 
test('Login using Google', async ({ page }) => {
   await page.goto('https://app.datadoghq.com/account/login');
   await page.locator('button', { hasText: 'Continue with Google' }).click();
   await page.locator('input[type="email"]').fill('userEmail');
   await page.locator('input#next').click();
   await page.locator('input[type="password"]').fill('userPassword');
   await page.locator('input#submit').click();
   if (!process.env.MFA) throw new Error('Missing MFA secret');
   const mfaCode = totp(process.env.MFA).toString();
   await page.locator('input[type="tel"]').fill(mfaCode);
   await page.locator('#totpNext').click();
   await expect(page.locator('h1.title')).toHaveText('You are logged in');
});

Conclusion

Having a universal security policy that requires login via Google shouldn't stop you from testing your UI. Nor should you have to take shortcuts that will compromise your organization. Instead, look for solutions that fit your organization’s needs from both a security and a functionality perspective. Or, if you need it, feel free to use ours.

Enjoy your new, secure, E2E tests!

Maor Zelinger is an Automation engineer at Reco with years of experience building test automation infrastructure for companies that range from startups to fortune 500 companies.

References