Home > OS >  Cypress Login with CSRF token
Cypress Login with CSRF token

Time:10-22

I would really like to expand on this topic "Logging in with CSRF token" as I have been banging my head against a wall for weeks now and I can't be the only one with this problem. All topics about logging in via POST or logging in with CSRF inevitably lead back to the above link.

Yet the recipes described in this link do not seem to work for me. They all assume that the CSRF token is created once you visit the Login page. But on our site, the CSRF token is only created once you login.

I tested with Postman and there is no CSRF token in the HTML or in the header before you are logged in.

I also tested it in Cypress with the following code:

describe('gimme dat csrf token', () => {

    it('try to get the csrf token', () => {
        cy.visit(Cypress.env('url'))
        cy.getCookie('YII_CSRF_TOKEN')
            .then(async (c) => {
                cy.log(c.value)
                return c.value
            })

    })
})

This will return an error as there is no YII_CSRF_TOKEN

Type Error
Cannot read properties of null (reading 'value')

If I add a login step before, it will return the value of the CSRF token as expected:

import {Login} from "../../pages/login/Login";

describe('gimme dat csrf token', () => {
    
   it('try to get csrf token', () => {
        cy.visit(Cypress.env('url'))
        login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass')) //added login
        cy.getCookie('YII_CSRF_TOKEN')
            .then(async (c) => {
                cy.log(c.value)
                return c.value
            })

    })
})

Therefore strategies #1 (parse token from HTML) and #2 (parse token from response headers) from the above link can not work.

Recipe #3 is also not feasible as we have several live systems to test and we can't expose a /csrf route

This only leaves us with the strategy #4, which we have been using so far.

Any ideas or are we stuck with adding the "manual" login step to every single spec file?

CodePudding user response:

I think strategies #1 & #2 rely on the browser remembering credentials and supplying them to the login page, as happens with the Stackoverflow page - you don't have to log in every time you visit.

The main difference is you have used cy.visit() instead of cy.request() as shown in the recipes.

If you still are not able to successfully grab the token, try using your login with cy.session(). It will only call the login function once per session.

/*
  Enable use of cy.session() and new behavior to handle caching 
  and restoring cookies, localStorage, and sessionStorage.
*/
Cypress.config('experimentalSessionSupport', true)

describe('...', () => {

  beforeEach(() => {
    cy.session(() => {
      login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass')) 
    })
  })

  it('try to get csrf token', () => {
    cy.getCookie('YII_CSRF_TOKEN')
      .then((c) => {
        cy.log(c.value)
      })
  })
})
  • Related