Introduction:

With Cypress 10 we can automate  Single Sign On with Multi-Factor Authentication enabled. The new feature of Cypress 10 helps us to visit multi-domain in a single test. Now the cy.origin module helps us to do the same. We can visit the Single Sign-On site and make users authenticate and redirect to our main application domain. But usually, people find it difficult to automate Single Sign On-based applications and have multi-factor authentication for security. This Blog will help us to overcome both the challenges of Single Sign On with Multi-Factor Authentication using Cypress 10 and using a session that will make our test fast, saves time of login, and authenticate once login multiple times.

Test Goal: Automate Office 365 using Cypress 10

To Overcome both the challenges of SSO and the MFA  using Cypress 10 and using session.

What are the test requirements?

  1. Cypress 10 installed.
  2. The secret key for Office 365 account.
  3. And one npm package.

Let’s start the recipe.

How do I get a secret key for an office 365 account to generate OTP:

6th Choose the authenticator app option

7th Click on the link I want to use a different authenticator app 

8th Click on next

9th Click on the button can’t scan the image

10th Copy the secret key and paste it and click on next.

Installing NPM packages required using one of the below methods:-

  • npm i -D cypress-OTP
  • yarn add -D cypress-OTP

Single Sign On with Multi-Factor Authentication using Cypress 10

We are all set for the next steps now next part is in VS code

Open VS code 

Solution:

Go to supports/command.js

  • This is a custom command, we can use this command anywhere in the cypress test. We have to add parameters such as name, Email id, password, and token as a secret which we extracted for office 365 accounts. “login” is the command name we can use using cy.login()in our test.
Cypress.Commands. add("login", (email, password, token, path) => {
  const args = { email, password, token }
  • Visit the application URL
cy.visit(Cypress.config('apiLoginURL')) 
  cy.on('uncaught:exception', (err, runnable) => {
    return false
  })
  cy.wait(7000)
  • Here we have to click on the button which navigates us to the office 365 pages where we have to authenticate the user. This landed us on the office365 SSO page. 
cy.get('.microsoft').click()
  • The new feature for Cypress 10 is cy.origin which helps us navigate to multi-domain in the same test. Here we will pass the login URL for office 365.
 cy.origin('https://login.microsoftonline.com', { args }, ({ email, password, token }) => {
    cy.wait(7000)
    cy.get('body').then(body => {
      if (body.find('#otherTileText').length > 0) {
        cy.contains('Use another account').click()
  • Passing the Email address for office 365
cy.get('#i0116').type(email)
      }
      else {
        cy.get('#i0116').type(email)
      }  
    cy.get('#idSIButton9').click()
    cy.wait(3000)
  • Passing password for office 365
cy.get('#i0118').type(password)
    cy.contains('Sign in').click()
    cy.get('div.tile:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2)').click()
  • Now we have to pass the secret key which we have extracted in the above steps and pass it to the OTP-generate task. This step is responsible for generating the secret.
 cy.task("generateOTP", token).then(token => {
      cy.get("#idTxtBx_SAOTCC_OTC").type(token);
      cy.get('#idSubmit_SAOTCC_Continue').click()
      cy.wait(3000)
    })

For any exception, we are having the below block

 cy.on('uncaught:exception', (err, runnable) => {
      return false
    })
        cy.get('#idBtn_Back').click()
        cy.wait(16000)  
        })              
}) 
})
  • Now we have to use this custom command in our test. Generally, we have to log in each time before the actual test. So we can use Cypress hooks ‘before’ and ‘before each’ hook.

Let’s see the code

Create a file and name it ‘beforeafter.js’ inside the Cypress folder. And paste the below Code

before(() => {

Here, we are creating the session

  cy.session('1', () =>{

This is a custom command we are calling in the command.js file. It passes all required parameters like email, password, and Secret key.

cy.login(Cypress.env("email"),Cypress.env("password"),Cypress.env('secret'),Cypress.env('file'))
  })   
  })
beforeEach(() => {

  Here we are restoring the above session which will help us to authenticate the user and log in quickly to the application.

cy.session('1')
cy.wait(5000)
cy.visit(Cypress.config('apiLoginURL'))
cy.get('.microsoft').click()
cy.wait(15000) 
})

Usage in test

Cypress/Support/Command.js

Cypress.Commands.add("login", (email, password, token, path) => { 
  const args = { email, password, token }
  cy.visit(Cypress.config('apiLoginURL'))
  cy.on('uncaught:exception', (err, runnable) => {
    return false
  })
  cy.wait(7000)
  cy.get('.microsoft').click() 
  cy.origin('https://login.microsoftonline.com', { args }, ({ email, password, token }) => {
    cy.wait(7000)
    cy.get('body').then(body => {
      if (body.find('#otherTileText').length > 0) {
        cy.contains('Use another account').click()
        cy.get('#i0116').type(email)
      }
      else {
        cy.get('#i0116').type(email)
      }
    cy.get('#idSIButton9').click()
    cy.wait(3000)
    cy.get('#i0118').type(password)
    cy.contains('Sign in').click()
    cy.get('div.tile:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2)').click()
    cy.task("generateOTP", token).then(token => {
      cy.get("#idTxtBx_SAOTCC_OTC").type(token);
      cy.get('#idSubmit_SAOTCC_Continue').click()
      cy.wait(3000)
    })
    cy.on('uncaught:exception', (err, runnable) => {
      return false
    })  
        cy.get('#idBtn_Back').click()
        cy.wait(16000)      
        })            
}) 
})

Usage in test

BeforeAfter.js file

before(() => {
  cy.session('1', () =>{
    cy.login(Cypress.env("email"),Cypress.env("password"),Cypress.env('secret'),Cypress.env('file'))
  })
  })
Before(() => {
  cy.session('1')
cy.wait(5000)
cy.visit(Cypress.config('apiLoginURL'))
cy.get('.microsoft').click()
cy.wait(15000)
})

Conclusion:

We are successfully able to automate login to the application through SSO and automate MFA and reduce the login time using a session in Cypress. Here is a link to another good read around the same topic.

Read more blogs here

14