Search code examples
cypressantiforgerytokensamesite

Cypress + 2 Super Domains + AntiforgeryToken = Cypress can't be redirect


I am currently working on setting-up a Cypress solution to test a product based on Nuxt and .NET. The product uses an SSO-based login page with a different super domain from the product.

This creates a problem with cookies. Indeed, access to the product generates a redirection to the SSO authentication page. And, following the validation of the authentication form, Chrome driven by Cypress enters a call loop with errors in the attributes of the cookie, in particular the value of the SameSite attribute which is incorrect compared to the expectation SSO side.

Currently, several features are disabled in the browser, namely :

  • SameSiteByDefaultCookies
  • CrossSiteDocumentBlockingIfIsolating
  • CrossSiteDocumentBlockingIfIsolating
  • IsolateOrigins
  • site-per-process

Excerpt of cypress/plugins/index.js

  on('before:browser:launch', (browser = {}, launchOptions) => {
    if (browser.family === 'chromium') {
      launchOptions.args.push(
        "--disable-features=SameSiteByDefaultCookies,CrossSiteDocumentBlockingIfIsolating,CrossSiteDocumentBlockingIfIsolating,IsolateOrigins,site-per-process"
      );
    }
    console.log(launchOptions.args);
    return launchOptions
  });

Even by disabling all the protections on the SSO, no way to make Cypress work.

Here is an Excel file with all of the HTML requests listed via the Chrome console. The file describes the differences between the Chrome driven by Cypress and a "classic" Chrome.

NB: adding "chromeWebSecurity": false, in the configuration of Cypress does not change anything

Not fully knowing what the underlying concerns are, I cannot describe the problem well. All the solutions proposed to similar problems exposed on various forums (StackOverFlow included) were not enough to solve mine. Can you help me please ?

Thanks in advance.

Regards, Alexander.


Solution

  • I finally found the solution for this SSO authentication.

    Here is the code:

    Cypress.Commands.add('authentificationSSO', (typedeCompte, login) => {
      let loginCompte = 'login';
      let motDePasseCompte = 'password';
      
      let baseUrlSSO = Cypress.env('baseUrlSSO') ? Cypress.env('baseUrlSSO') : '';
      let baseUrl = Cypress.config('baseUrl') ? Cypress.config('baseUrl') : '';
    
      cy.request(
        'GET',
        baseUrlSSO +
          '/Account/Login?${someParameters}%26redirect_uri%3D' +
          baseUrl
      ).then((response) => {
        let requestVerificationToken = '0';
        let attributsCookieGroupe = [];
        let nomCookie = '';
        let tokenCookie = '';
        const documentHTML = document.createElement('html');
        documentHTML.innerHTML = response.body;
        attributsCookieGroupe = response.headers['set-cookie'][0].split(';');
    
        const loginForm = documentHTML.getElementsByTagName('form')[0];
        const token = loginForm.querySelector('input[name="__RequestVerificationToken"]')?.getAttribute('value');
    
        requestVerificationToken = token ? token : '';
        nomCookie = attributsCookieGroupe[0].split('=')[0];
        tokenCookie = attributsCookieGroupe[0].split('=')[1];
    
        cy.setCookie(nomCookie, tokenCookie, { sameSite: 'strict' });
    
        cy.request({
          method: 'POST',
          url:
            baseUrlSSO +
            '/Account/Login?{someParameters}%26redirect_uri%3D' +
            baseUrl,
          followRedirect: false,
          form: true,
          body: {
            Login: loginCompte,
            Password: motDePasseCompte,
            __RequestVerificationToken: requestVerificationToken,
            RememberLogin: false
          }
        });
      });
    });