How to handle Google's 2-step verification

What is Google's 2-step authentication

Many sites have integrated Google Sign-In to authorize users as part of their sign-in process. Google's Sign-In process can also include a 2-Step verification phase, based on the Google Security settings. This verification can be done in other ways as well (like by SMS), but the main focus of this article is to show a way to manage the verification using an Authenticator application, which provides Time-based One-time Passwords (TOTP).

The SMS verification could be handled by registering a number with a service like Twilio (https://twilio.com) and then read the SMS content using the Twilio REST API, but that approach can be the subject of another article.

Our Authenticator application, in this case, will be a Python CLI script which has been linked with the user account. It is also possible to link the same user account to multiple Authenticators, like a mobile application.

Read more at https://www.google.com/landing/2step/#tab=how-it-works

This is the usual page showing the input field to verify Google Sign-In with an Authenticator TOTP code:

Google Sign-In Authenticator step

How to set up an Authenticator

Add the authenticator pip package into your conda.yaml file.

The package we will be using is https://pypi.org/project/authenticator/, which provides a CLI script that we will setup as one of the Google Authenticator applications.

channels:
  - defaults
  - conda-forge
dependencies:
  - python=3.7.5
  - pip=20.1
  - pip:
      - rpaframework
      - authenticator

The above step adds the authenticator to your environment, but for the manual set up phase where we link this authenticator to Google account it might be easiest to install also in your local terminal with the command:

pip install -U authenticator

Next go to https://myaccount.google.com/intro/security page using the Google account you want to use with your robot. On the 2-Step Verification page, select the Authenticator app option.

start authenticator setup

Select the phone type you want to setup as Authenticator app. This does not matter if you are only using this account with Python CLI authenticator, but select your phone type if you want to set it up as well at the same time.

select phone

Scan the barcode with your phone if you want to use that as well, but for our setup we will in any case click on the CAN'T SCAN IT? link.

cant scan barcode link

Copy the barcode code from the section shown below. Click NEXT and leave the browser window open, because we need to complete the last step of the Authenticator setup with the generated passcode that we will get from the Authenticator CLI script.

copy code key

Next, we need to set up the authenticator script with our Authenticator key:

authenticator --data /path/to/robot/resources/authdata add Google:[email protected]
No data file was found. Do you want to create your data file? (yes|no) [yes]: yes
Enter passphrase:
Confirm passphrase:
Enter shared secret:
  • the --data argument will determine the location of your authenticator. In the example above I am pointing it to the authdata subfolder in my robot resources folder. The authenticator will ask you to create a passphrase for the data, which will be needed in the robot to access the generated TOTP codes.
  • add your google account after the add argument
  • add a passphrase when asked

    REMEMBER to store the passphrase in a secure location, you will need it to generate TOTP codes with the authenticator script.

  • Paste the barcode key you copied in the previous step to Enter shared secret: when the authenticator commands asks for it.

Now we need to complete the Authenticator setup with a generated TOTP code.

Start to generate TOTP codes with the authenticator command. The command will ask for the passsphrase, and then start to print out codes every 5 seconds. The codes are renewed every 30 seconds.

authenticator --data /path/to/robot/resources/authdata gen

Copy the 6-digit TOTP code, paste it into the Set up Authenticator browser window, and click VERIFY to complete the Authenticator setup.

verify with generated code

Completing Google Sign-In in the robot

Now that we have a working authenticator app, as an example I will demonstrate how to complete the Google Sign-In on https://cloud.robocorp.com.

To use authenticator with the robot, we need to create a shell script, which we will call template.sh and place in the tasks folder.

The PASSPHRASE will be replaced with our passphrase in the Get Authenticator Code keyword.

#!/bin/bash

echo PASSPHRASE | authenticator --data /path/to/robot/resources/authdata generate --refresh once

Running this script will produce a single TOTP code which we will use to complete the Authenticator step.

Libraries

We need to use multiple libraries for this robot:

  • RPA.Browser: used to access https://cloud.robocorp.com and to interact with page elements.
  • RPA.core.notebook: not strictly necessary, but useful to print data to Robocorp Lab's notebook.
  • RPA.Robocloud.Secrets: used to access the user's Vault in Robocorp Cloud.
  • Robot Framework core library String: used for regular expression matching.
  • Robot Framework core library Process: used to Run Process and read stdout content from those processes.
  • Robot Framework core library OperatingSystem: used to Remove File which is created during robot run.

As a Task Teardown, we will close all browsers opened during the execution of the task.

*** Settings ***
Library         RPA.Browser
Library         RPA.core.notebook
Library         RPA.Robocloud.Secrets
Library         String
Library         Process
Library         OperatingSystem
Task Teardown   Close All Browsers

Variables

We will set some variables to not repeat text and to allow easier robot parameter modification. All sensitive variables have been stored into Robocorp Cloud Vault. The ${GOOGLEAUTH_TITLE} text need to match your account language setting.

*** Variables ***
${ROBOCORP_CLOUD}           https://cloud.robocorp.com
${GOOGLEAUTH_TITLE}         Sign in with Google
${GOOGLEAUTH_ID_NEXT}       //div[@id="identifierNext"]//button
${GOOGLEAUTH_PASSWD_NEXT}   //div[@id="passwordNext"]//button
${GOOGLEAUTH_TOTP_NEXT}     //div[@id="totpNext"]//button
${AUTHSCRIPT}               authcodes.sh

Keywords

Keyword Input text and proceed is used to incapsulate repeatable actions during the Google Sign-In process. As arguments, it gets an ${element} locator and the ${text} to input into the locator.

*** Keywords ***
Input text and proceed
    [Arguments]   ${element}  ${text}
    Wait until page contains element  ${element}
    Input Text      ${element}  ${text}

The keyword Get Authenticator Code will execute authenticator using the shell script ${AUTHSCRIPT}, which we create by modifying template.sh with the ${passphrase} given in a keyword argument.

Another keyword argument ${googleuser} is used to find the code in the authenticator output, which the keyword then returns.

*** Keywords ***
Get Authenticator Code
    [Documentation]  Authenticator needs to be setup for Google account
    [Arguments]     ${googleuser}  ${passphrase}
    Run Process     sed 's/PASSPHRASE/${passphrase}/g' template.sh > ${AUTHSCRIPT}  shell=yes
    Run Process     chmod +x ${AUTHSCRIPT}  shell=yes
    ${result}       Run Process   ./${AUTHSCRIPT}
    ${match}        Get Regexp Matches   ${result.stdout}  ${googleuser}: ([\\d]{6})  1
    Notebook Print  MATCH: ${match}[0]
    [Teardown]      Run Keyword And Ignore Error     Remove File  ${AUTHSCRIPT}
    [Return]        ${match}[0]

The Keyword Complete Google Signin is responsible for completing the Google Sign-In. This keyword gets the argument ${startelement}, which defines the element locator starting the process. The default value has been set here to the locator needed for the Robocorp Cloud sign-in process.

The keyword reads secrets from Robocorp Cloud Vault before it starts to interact with page elements.

Before the final stage of inputting the Authenticator code for 2-step verification, the code is retrieved with Get Authenticator Code keyword.

*** Keywords ***
Complete Google Signin
    [Arguments]     ${startelement}=link=Sign in with Google
    ${secret}       Get Secret   gmail
    Wait until page contains element  ${startelement}
    Click Element   ${startelement}
    Switch window   ${GOOGLEAUTH_TITLE}
    Input Text      //input[@type="email"]     ${secret}[account_user]
    Click Button    ${GOOGLEAUTH_ID_NEXT}
    Input text and proceed  //input[@type="password"]  ${secret}[account_password]
    Click Button    ${GOOGLEAUTH_PASSWD_NEXT}
    ${code}         Get Authenticator Code  ${secret}[account_user]  ${secret}[authenticator_passphrase]
    Input text and proceed  //input[@type="tel"]  ${code}
    Click Button    ${GOOGLEAUTH_TOTP_NEXT}

Task

We have a simple task that will open https://cloud.robocorp.com and sign-in using Google Sign-In process. As proof we take a screenshot when the page contains the Robocorp Cloud welcome text Welcome Mika! after successful sign-in.

Robocorp Cloud login page

*** Tasks ***
Complete Robocorp Cloud Google Sign-In
    Open Available Browser     ${ROBOCORP_CLOUD}
    Complete Google Signin
    Wait Until Page Contains   Welcome Mika!
    Capture Page Screenshot

Here is a Robot file containing all the code for the robot above: task.robot