cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.77k stars 3.16k forks source link

Cypress + AWS Cognito Hosted UI = /error ? #20784

Open DimiTech opened 2 years ago

DimiTech commented 2 years ago

Current behavior

We are testing a Web Application, and for some reason the AWS Cognito Sign In (using the Cognito Hosted UI) doesn't work -> Cognito just redirects to /error instead of the given redirect_uri. (see screenshots)

This Sign In flow works flawlessly when directly using the application.

Screen Shot 2022-03-25 at 4 26 22 PM Screen Shot 2022-03-25 at 4 25 00 PM Screen Shot 2022-03-25 at 8 21 13 PM

The most suspicious thing here is the Insecure HTTPS caused by cypress using its CypressProxyCA when running tests - I think there might be something wrong there?

We have tried adding the Amazon/CloudFront certificates but that doesn't work because we need the corresponding Private Keys (which we don't have of course).

Tried looking at the Cognito logs but there's nothing useful there either.

Tried playing with other settings/configuration but nothing works.

Is there any solution to this, has anyone used AWS Cognito and Cypress in this way before?

Thanks in advance!

Desired behavior

We expect the Cognito Hosted UI - OAuth2.0 Authorization Code flow to work the same as it does when using the Web Application directly.

Test code to reproduce

.

Cypress Version

9.5.2

Other

No response

suresh-raja-nxtgen commented 2 years ago

@DusanDimitric Were you able to resolve this error with some other workaround?

convers39 commented 2 years ago

same issue here, any solutions?

github-actions[bot] commented 1 year ago

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

RandomComm3nt commented 1 year ago

This is happening for me in the latest version of Cypress (12.12.0).

From my testing, I'm not sure this is anything to do with certificates, because if you open the Cognito Hosted UI in the Chrome instance Cypress uses you get the same insecure certificate warning, but the process works.

AtofStryker commented 1 year ago

Hi @RandomComm3nt. Are you able to get AWS Cognito login to work? We have a guide on how to perform hosted login with Cognito. The insecure certificate is likely a red herring, as the cypress proxy server generates certs in order to wrap your application with top being your test URL.

AtofStryker commented 1 year ago

Unfortunately we have to close this issue due to inactivity. Please comment if there is new information to provide concerning the original issue and we can reopen.

RandomComm3nt commented 1 year ago

Hi, I've only just had a chance to play with this some more.

I've created two tests that seem like they should be identical. The first test correctly authenticates with Cognito and is redirected back to localhost, but the second test gets a Cognito error (screenshot below).

describe("template spec", () => {
  it("passes", () => {
    cy.visit("localhost:3000");
    cy.get("a").click();

    cy.origin("cypress-test.auth.eu-west-2.amazoncognito.com", () => {
      cy.get(`input[name="username"]:visible`).type("test-user");
      cy.get(`input[name="password"]:visible`).type("Cypress1!");
      cy.get(`input[name="signInSubmitButton"]:visible`).click();
    });

    cy.get("a");
  });

  it("fails", () => {
    cy.visit("localhost:3000");
    cy.get("a")
      .invoke("attr", "href")
      .then((href) => {
        cy.visit(href);
      });

    cy.origin("cypress-test.auth.eu-west-2.amazoncognito.com", () => {
      cy.get(`input[name="username"]:visible`).type("test-user");
      cy.get(`input[name="password"]:visible`).type("Cypress1!");
      cy.get(`input[name="signInSubmitButton"]:visible`).click();
    });
    cy.get("a");
  });
});

image

Full source code of this example attached.

cognito-cypress-test.zip

AtofStryker commented 1 year ago

@RandomComm3nt I was able to give this a run and reproduce it. This looks like a bug to me. It doesn't seem to be an issue with cookie jar state or order of the test, but for some reason a cy.visit() on the direct amazon link causes a bad request. What I think might be happening is something in the proxy is modifying that request in a way that makes some of the Set-Cookie headers go missing Screenshot 2023-06-02 at 11 15 51 AM, which is likely why the error req follows, which tells me there is something wrong with this request in the second test case. In the mean time, are you able to leverage the first case in your tests as a work around?

xxluke commented 1 year ago

I'm wondering why this isn't fixed yet. In my opinion the underlying bug is a major issue that probably holds back many people from using Cypress at all, when you can't login through third-party providers using cookies.

I now made this workaround which seems to work for me:

const COGNITO_HOST = 'my-url.amazoncognito.com'
let xsrfToken: string;
cy.intercept({
  method: 'POST',
  url: '/login*'
}, (req) => {
  req.headers['Cookie'] = `XSRF-TOKEN=${xsrfToken}`;
});
cy.origin(COGNITO_HOST, () => {
  cy.get('input[name="username"]:visible').type('user');
  cy.get('input[name="password"]:visible').type('password');
  cy.getCookie('XSRF-TOKEN').its('value');
}).then((token: string) => xsrfToken = token);
cy.origin(COGNITO_HOST, () => {
  cy.get('form[name="cognitoSignInForm"]:visible').submit();
});
lorenzogrv commented 5 months ago

Reached here while setting-up a new e2e suite for an existing application.

Behavior is the same at Chrome, Firefox and Electron browsers: finishing at /error because form POST misses XSRF tokens

Tried @xxluke 's workaround without luck in this case. Cypress isn't able to access that XSRF-TOKEN cookie so we can't patch the form POST /login request. Some warning messages at consoles on different browsers which may relate:

Will still give a try to the "click on link" trickery because application uses server-side redirection, and report back here any findings

lorenzogrv commented 5 months ago

Adapting the "click on link" trickery which explains @RandomComm3nt here the flow can complete succesfully

tjoaoguimaraes commented 1 month ago

Did anyone find a solution? I am facing this error while using the origin. If I use cy.visit(), it works, but the screen reloads every test due to a domain change.

AtofStryker commented 1 month ago

Did anyone find a solution? I am facing this error while using the origin. If I use cy.visit(), it works, but the screen reloads every test due to a domain change.

@tjoaoguimaraes have you tried setting experimentalModifyObstructiveThirdPartyCode to true?

tjoaoguimaraes commented 1 month ago

Did anyone find a solution? I am facing this error while using the origin. If I use cy.visit(), it works, but the screen reloads every test due to a domain change.

@tjoaoguimaraes have you tried setting experimentalModifyObstructiveThirdPartyCode to true?

Yes, I did, but it does not work. My problem is that the cognito POST request returns a 400 status code, the same issue OP is facing.

tjoaoguimaraes commented 1 month ago

After more than two weeks of struggling to find a solution, I finally made it.

While inspecting the network requests made by Cypress during test execution, I noticed a warning in a request stating:

“This attempt to set a cookie via a Set-Cookie header was blocked because it had the ‘SameSite=Lax’ attribute but came from a cross-site response which was not the response to a top-level navigation.”

After some Googling, I found this blog post: https://www.tomoliver.net/posts/cypress-samesite-problem

By reproducing the steps provided, everything worked as expected.

Hope it helps!