Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cy.origin() does not fit when frontend redirects to another domain login page #21201

Closed
edudelta opened this issue Apr 26, 2022 · 22 comments
Closed
Assignees
Labels
stage: investigating Someone from Cypress is looking into this topic: cy.origin Problems or enhancements related to cy.origin command

Comments

@edudelta
Copy link

What would you like?

According cy.origin() docs it's needed to step directly to a multidomain page and make all steps needed, being the multidomain required in advance.
However it does not fit when frontend redirects to a login page in another domain when it's not signed in, for instance. This is needed due frontend needs to create tokens, else, and then send to a login page that will redirect back to the main site.

It can be something like:
mydomain/page ---(not signed in)---> anotherdomain/login
Perform login steps...
anotherdomain/login ---(signed in!) ---> back to mydomain/page

Why is this needed?

I don't have enough resources to call anotherdomain/login page and any direct access to login page, in another domain, is not a valid user flow if does not came from main domain.

Other

No response

@AtofStryker AtofStryker added the topic: cy.origin Problems or enhancements related to cy.origin command label Apr 26, 2022
@mschile
Copy link
Contributor

mschile commented Apr 26, 2022

@edudelta, cy.origin should be able to handle redirects. Here is some example code from your proposed scenario. If you have a more specific test case to provide, that may help with any further investigation.

it('server redirects to login page', () => {
  cy.origin('https://anotherdomain.com', () => {
    cy.visit('https://mydomain.com/page') // server responds with a 3xx status code to redirect to anotherdomain.com/login

    // perform login steps
    cy.get('#login-button').click() // clicking login button redirects back to mydomain.com
  })

  cy.get('#user').should('contain', 'username')
})

it('client redirects to login page', () => {
  cy.visit('https://mydomain.com/page') // server responds with a 2xx status code and client redirects to anotherdomain.com/login

  cy.origin('https://anotherdomain.com', () => {
    // no visit is needed here since we've already been redirected
    // cy.visit('https://mydomain.com/page')

    // perform login steps
    cy.get('#login-button').click() // clicking login button redirects back to mydomain.com
  })

  cy.get('#user').should('contain', 'username')
})

@edudelta
Copy link
Author

Hi @mschile thank you so much by your help.
My situation is covered by client redirection, but when Cypress tries to perform first step in cy.origin() the Test Runner stop responding, the page is no more loaded (stuck partially loaded) and then hangs forever.
I need to force close browser even after finishing Cypress process.

Browsers: Chrome 100, Electron 94, Edge 100
Mac Monterey 12.3.1

@mschile
Copy link
Contributor

mschile commented Apr 26, 2022

Are you trying to use a public login provider? Do you have a test case you could provide? Do you see any errors in the browser? Instead of redirecting the login page through cy.origin, what happens if you just visit the login page directly using cy.visit?

it('visits login page', () => {
  cy.visit('https://anotherdomain.com/login')
})

@edudelta
Copy link
Author

edudelta commented Apr 26, 2022

I'm using a SAP integration to perform login cross-domain and unfortunately I don't have public logs to share. ;/
When I called cy.visit() with login domain I got successfully access. Looks like Cypress, at least Test Runner, is crashing during redirections. (I got same issue with cypress run)

@edudelta
Copy link
Author

When I try to run tests and it hangs, as mentioned, this is what I have:
image

image

Mac cooler work fast as I never saw and it stop running when I finish Cypress processing.

@mshima
Copy link

mshima commented Apr 27, 2022

@mschile I've have some problems with multi-domain too.
Here's the current implementation (I did a lot of alternative implementations to test, ex: hardcoding the secondary domain):

  login: (username: string, password: string) => {
    cy.session(
      [username, password],
      () => {
        cy.visit('/');
        cy.get('#signIn').click();                                     // The client uses some lib here, prefer to use it instead of calculating the url.
        cy.url({ timeout: 10000 }).should('includes', '/realms/');     // If I take this url and move to another browser, it logs in successfully.
        cy.url().then(url => {
          const { protocol, host } = new URL(url);                     // sometimes we use keycloak domain, others localhost.
          // eslint-disable-next-line @typescript-eslint/no-shadow
          cy.origin(`${protocol}//${host}`, { args: { url, username, password } }, ({ url, username, password }) => {
            // Reload oauth2 login page due to cypress origin change.
            cy.visit(url);                                             // Reload page otherwise below implementation doesn't work. Selectors times out.
            cy.get('input[name="username"]').type(username);
            cy.get('input[name="password"]').type(password);
            cy.getCookies({ log: true });                              // Cookies are empty, we should have some Keycloak cookies here.
            cy.get('input[type="submit"]').click();                    // Fails with We are sorry... An error occurred, please login again through your application.
          });
        });
        cy.url({ timeout: 10000 }).should('eq', Cypress.config().baseUrl + 'tabs/home');
      },
      {
        validate: () => {
          cy.authenticatedRequest({ url: '/api/account' }).its('status').should('eq', 200);
        },
      }
    );
  },

My guess is that cypress is failing to manage cookies at the secondary domain.

@mjhenkes
Copy link
Member

@mshima
I don't think your code example will work currently specifically using cy.url after the cy.click. I assume you're currently running with chromeWebSecurity: false? When enabled this test will hang.

        cy.get('#signIn').click();                                     // This redirects, we wait for a non cross origin load unless a cy.origin command is next
        cy.url({ timeout: 10000 }).should('includes', '/realms/');     // This command is ran on the 'localhost' origin but tries to interact with the new aut origin and would have a cross origin failure.
        cy.url().then(url => {

@mjhenkes
Copy link
Member

@edudelta, I'm not sure how to proceed helping you debug. I think we'd need a reproducible test case that we could access.

@mshima
Copy link

mshima commented Apr 28, 2022

@mjhenkes I’ve removed url and used hardcoded url without success.
I can create a repro if needed.

@mschile
Copy link
Contributor

mschile commented Apr 28, 2022

@mshima, yes, a reproducible project would be great.

@edudelta
Copy link
Author

mmm... What type of log could help in this case? tail of DEBUG=cypress:* is good enough?

@mshima
Copy link

mshima commented Apr 29, 2022

@PentoreXannaci
Copy link

When I try to run tests and it hangs, as mentioned, this is what I have: image

image

Mac cooler work fast as I never saw and it stop running when I finish Cypress processing.

i had the simmilar issue, just tried chrome instead of the electron browser, it still runs slow but alteast it wont hang anymore.

@cypress-bot cypress-bot bot added stage: backlog stage: investigating Someone from Cypress is looking into this and removed stage: backlog labels Apr 29, 2022
@mjhenkes mjhenkes self-assigned this Apr 29, 2022
@mjhenkes mjhenkes added experiment: origin and removed topic: cy.origin Problems or enhancements related to cy.origin command labels Apr 29, 2022
@mshima
Copy link

mshima commented Apr 30, 2022

@mschile the repro is https://github.com/mshima/cypress-origin, and step are at the README.
I've simplified the login process to don't be dynamic by default.
https://github.com/mshima/cypress-origin/blob/20843888c1098e6074169c96513f6c045ec2ad2b/ionic4j/cypress/support/commands.ts#L41-L51

This bug looks Keycloak specific. Okta and Auth0 seems to be ok.

Failure screenshot:
jhipster/generator-jhipster-ionic#660 (comment)

@mschile
Copy link
Contributor

mschile commented May 2, 2022

@mshima, thanks for the repro. As you suspected, the issue is with cookies in the secondary domain. We added some temporary logic that assumes either localhost or https. Since keycloak is setup on http, the cookies are not being handled correctly. We have #20685 logged to remove the temporary fix and handle cookies more appropriately. That issue will be completed before the experimental flag is removed for cy.origin. In the meantime, if you are able to run keycloak on https or use localhost instead of keycloak, that may fix the issue.

@mshima
Copy link

mshima commented May 2, 2022

@mschile localhost works.
But since we can have multiple applications deployed on docker for microservices test, not sure it's possible to have it deployed to localhost.
In any case, we have it implemented by api, so we will stick to it for now.

@edudelta
Copy link
Author

edudelta commented May 3, 2022

@mschile I'm using Oauth2 and I will wait for the fix changing to try once more. thank you

@mjhenkes
Copy link
Member

mjhenkes commented May 3, 2022

Closing as a duplicate, please follow #20685 for any updates.

@thisismydesign
Copy link

@mschile This is in fact an issue as described originally: when the 'frontend redirects' the page load of https://mydomain.com/login is a 200 and results in a cross-origin error. For auth flows that happen on the frontend the server won't respond with 3xx. For example, oauth flow via Nuxtjs's auth module works like this.

Can this be reopened?

@pezholio
Copy link

I'm getting some deeply odd behaviour. I visit my homepage, get redirected, and then log in like so:

  const username = Cypress.env('username') || throwMissingCypressEnvError('username')
  const password = Cypress.env('password') || throwMissingCypressEnvError('password')

  cy.visit('/')

  cy.url().then(url => {
    const { protocol, host } = new URL(url)
    cy.origin(`${protocol}//${host}`, { args: { username, password } }, args => {
      cy.get('input[name="username"]').type(args.username)
      cy.get('input[name="password"]').type(args.password, { log: false })

      cy.get('.govuk-button').contains('Sign in').click()
    })
  })

My first test passes, but subsequent tests fail with:

The following error originated from your test code, not from Cypress.

> on only accepts instances of Function

When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.

@nagash77
Copy link
Contributor

@pezholio Can you please open a separate issue?

@aavilla-riparian
Copy link

@pezholio Can you somehow link this to your new ticket once created? I am interested in this as well.

@emilyrohrbough emilyrohrbough added the topic: cy.origin Problems or enhancements related to cy.origin command label Dec 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: investigating Someone from Cypress is looking into this topic: cy.origin Problems or enhancements related to cy.origin command
Projects
None yet
Development

No branches or pull requests