Browser Automation: Using the Gmail API to Retrieve MFA Codes

In a separate article, we introduced the concept of performing synthetic transactions with LogicMonitor to ensure website services are up and running correctly.   It may be necessary to authenticate with a website before you can fully monitor it, and authentication may require presenting an MFA code that has been delivered via email. Let’s take this a step further and incorporate an MFA (Multifactor Authentication) Challenge.  This challenge consists of requesting that an MFA code is sent to a registered email address (Gmail), retrieving the MFA code, and presenting the code to the website to complete the MFA challenge.  

Setup the Gmail API

We will use Gmail as the public verified email address since Gmail has a robust API that makes this process fairly easy.  The MFA service check will access the Gmail account to get the MFA code requested from the web page.

First, we have to enable the API and authenticate to Gmail.  This can be done by following their Quickstart guide.

Step 1: Enable the Gmail API

Click the “ENABLE THE GMAIL API” form button to generate the credentials.json file.  Place this file in the same directory as your Python script.

Step 2: Install the Google Client Library

Run the following pip command in your Python environment.

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

Step 3: Setup and run the sample script

The sample script will authenticate to the Gmail account.  Run the script as any other Python file. A popup window will ask you to authenticate to Google, and once authenticated, a token.json file will be generated.  Copy this file to the same directory containing your Python script and the credentials.json file.

 

Python Script

Add these imports to your Python script to access the Gmail API:

from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools

 

Add this code to your Python script to enable authentication to the Gmail account:

# Get Creds for Gmail

store = file.Storage(‘token.json’)

creds = store.get()

 

if not creds or creds.invalid:

flow = client.flow_from_clientsecrets(‘credentials.json’, SCOPES)

creds = tools.run_flow(flow, store)

service = build(‘gmail’, ‘v1’, http=creds.authorize(Http()))

 

To read the MFA code we use two Gmail functions.

The first function is ListMessagesMatchingQuery

def ListMessagesMatchingQuery(service, user_id, query=”):

“””List all Messages of the user’s mailbox matching the query.

Args:

  service: Authorized Gmail API service instance.

  user_id: User’s email address. The special value “me”

  can be used to indicate the authenticated user.

  query: String used to filter messages returned.

  Eg.- ‘from:user@some_domain.com’ for Messages from a particular sender.

Returns:

  List of Messages that match the criteria of the query. Note that the

  returned list contains Message IDs, you must use get with the

  appropriate ID to get the details of a Message.

“””


This function returns a list of messages matching the query.  In this case, we are using a query to get the MFA code from a specific sender ([email protected]).  

messLst = ListMessagesMatchingQuery(service, ‘me’, ‘from:DoNotReply@MFACodesRus.com‘)

The Next on is GetMessage


def GetMessage
(service, user_id, msg_id):

“””Get a Message with given ID.

Args:

  service: Authorized Gmail API service instance.

  user_id: User’s email address. The special value “me”

  can be used to indicate the authenticated user.

  msg_id: The ID of the Message required.

 

Returns:

  A Message.

“””

The ListMessageMatchingQuery function returns a list of messages in the order they were received; the most recent message will have an index of 0. We can retrieve the most recent message with the following code:

body = GetMessage(service, ‘me’, messLst[0][‘id’])

Next, we need to use a regular expression to extract the MFA code.  The appropriate regular expression may vary depending on the contents the MFA email. In this example, the message appears as:


You’ve requested a one-time passcode for authentication purposes; your one-time passcode is 519643.

Once you use this code, you will need to request a new code the next time you are asked to provide one. If you believe that you are receiving this email in error, or if you did not request the code to be sent to your email address, please contact Logicmonitor Credit Union at (888) 415-6442 for further assistance.

Please do not reply to this email.


I kept this simple and just used a ‘\d+’ to look for digit codes.  

Browcode = re.findall(‘\d+’, body[‘snippet’])

The MFA code is now stored in a variable and can be used where needed by your Python script.  

In this article, we expanded the use of synthetic transactions to include performing MFA challenges.  This functionality allows you to fully automate the multifactor authentication process required by the website you wish to monitor.   

Implementing browser automation for your business doesn’t have to be daunting or cumbersome. The LogicMonitor Professional Services team has the talent and is up for the challenge! Ask about a free LogicMonitor Professional Services scoping call or free trial.