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

In OIDC login, call back page doesn't load completely #26020

Open
MajidBabaeifar opened this issue Mar 6, 2023 · 16 comments
Open

In OIDC login, call back page doesn't load completely #26020

MajidBabaeifar opened this issue Mar 6, 2023 · 16 comments
Labels
E2E Issue related to end-to-end testing Reproducible Can be reproduced Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. type: bug

Comments

@MajidBabaeifar
Copy link

MajidBabaeifar commented Mar 6, 2023

Current behavior

I have a website that uses Open ID for login and after the login is successful, the provider website sends the user back to a URL to the actual website and I can't control this. for example user has to go to "localhost:3000" click on login button and then gets redirected to "someLoginProvider.com/login" and then after the login, user will come back to "myOnlineVersionOfLocalhost.com/callbackFromLogin" !
Here is the way I've tried to do this:
In cypress.js file I set the basic origin to localhost. and for login I try like below:

Cypress.Commands.add(
  "newLogin",
  (username = Cypress.env("username"), password = Cypress.env("password")) => {
    cy.visit("/welcome");
    cy.get("button").contains("ورود").click();
    cy.origin(
      "https://someLoginProvider.com.com",
      { args: { username, password } },
      ({ username, password }) => {
        cy.get("input[name='username']").focus().type(username);
        cy.get("input[name='password']").focus().type(password);
        cy.get("button[type='submit']").click();
      }
    );
    cy.origin("https://myOnlineVersionOfLocalhost.com", () => {
      cy.visit("/");
      cy.getAllLocalStorage().then((localStorage) => {
        Cypress.env("jxdf", localStorage["https://myOnlineVersionOfLocalhost.com"].jxdf);
        Cypress.env("elcd", localStorage["https://myOnlineVersionOfLocalhost.com"].elcd);
      });
    });
   cy.visit("/");
    window.localStorage.setItem(
      "s",
      "***"
    );
    window.localStorage.setItem("jxdf", Cypress.env("jxdf"));
    window.localStorage.setItem("elcd", Cypress.env("elcd"));
  }

The idea is since my login is based on JWT stored in local storage, I wanted to do the login on my actual website, pickup the values from local storage, then visit my localhost and paste the values inside local storage. The problem is that when I run this test, after the click on submit, the browser doesn't go back in the https://myOnlineVersionOfLocalhost.com. Actually the website shows up on screen but the URL doesn't change. So it get stuck in load page situation.

Desired behavior

After I click the submit button in login page, It should redirect me back to my online website. It shouldn't stuck on page loading for no reason.

Test code to reproduce

Cypress.Commands.add(
  "newLogin",
  (username = Cypress.env("username"), password = Cypress.env("password")) => {
    cy.visit("/welcome");
    cy.get("button").contains("ورود").click();
    cy.origin(
      "someLoginProvider.com",
      { args: { username, password } },
      ({ username, password }) => {
        cy.get("input[name='username']").focus().type(username);
        cy.get("input[name='password']").focus().type(password);
        cy.get("button[type='submit']").click();
      }
    );
    cy.origin("myOnlineVersionOfLocalhost.com", () => {
      cy.visit("/");
      cy.getAllLocalStorage().then((localStorage) => {
        Cypress.env("jxdf", localStorage["myOnlineVersionOfLocalhost.com"].jxdf);
        Cypress.env("elcd", localStorage["myOnlineVersionOfLocalhost.com"].elcd);
      });
    });
    cy.visit("/");
    window.localStorage.setItem(
      "s",
      "***"
    );
    window.localStorage.setItem("jxdf", Cypress.env("jxdf"));
    window.localStorage.setItem("elcd", Cypress.env("elcd"));
  }
);

Cypress Version

12.6.0

Node version

16.14.2

Operating System

windows 10

Debug Logs

Timed out after waiting 60000ms for your remote page to load.



Your page did not fire its load event within 60000ms.



You can try increasing the pageLoadTimeout value in cypress.config.ts to wait longer.



Browsers will not fire the load event until all stylesheets and scripts are done downloading.



When this load event occurs, Cypress will continue running commands.

Other

No response

@mjhenkes
Copy link
Member

mjhenkes commented Mar 7, 2023

So it sounds like you make it past log in and load the deployed version of your site but you aren't able to interact with it with the second cy.origin block?

You could try a couple of things.

  1. Double check the origin your interacting with and make sure it's the same.
  2. Can you remove the visit in the second origin block? It doesn't seem nessesary

Also you should check into our cy.session command. You can capture sessions from one url and apply it to another, that may help with your use case.

@MajidBabaeifar
Copy link
Author

@mjhenkes Thank you very much for the response and for your awesome library.
I checked out 1 and 2 and they are ok and I still have that problem. Can you give me an example of how a session can replace the functionality I'm trying to achieve in my code?
And something else I wanted to mention that might help is that I found a way around it but it has some problems too. I changed the base origin in cypress.config to my https://myonlineversionoflocalhost.com and tried to put someLoginProvider.com and localhost:3000 in the local origins and it actually worked. But the problem is that I have to run the rest of my code inside an cy.origin() and the problem I have with this is that I can't use custom commands inside cy.origin() and I have to repeat some lines over and over. I tried to use cy.require() but it keeps giving me a typescript missing message.
origin("http://localhost:3000",()=>{ // here goes all my tests })

@mjhenkes
Copy link
Member

mjhenkes commented Mar 9, 2023

Maybe try this flow?

*apply tokens to localhost

It certainly isn't ideal having to run your main test body in a cy.origin block, however we will be fixing the typescript cy.require issue in our next release:
#25931

As for applying cy.session, it's job is to capture and cache cookies, local and session storage and restore it. Off the top of my head I'm not quite sure how to apply it to other sites, you might need to play around with it to get it right.

@MajidBabaeifar
Copy link
Author

Thank you very much for the time you are putting in. I appreciate it.
However the solution you mentioned above is pretty much the code that I mentioned at the beginning of this issue, and unfortunately it doesn't work as I mentioned. I tried to use the session but that didn't work either. I would really appreciate it if you could help me with any other way I can perform this test.
Thank you again

@mjhenkes
Copy link
Member

@MajidBabaeifar, my suggestion is close to what you had above, but not quite the same. Specfically the first cy.origin call to https://myonlineversionoflocalhost.com/.

Did you try that and did it still fail?

@mjhenkes mjhenkes assigned AtofStryker and unassigned mjhenkes Mar 14, 2023
@AtofStryker
Copy link
Contributor

I am going to close this due to inactivity, but if this is still an issue let us know @MajidBabaeifar !

@MajidBabaeifar
Copy link
Author

Hi again,
sorry it was new year holidays in my country and I didn't have access to the source code till today. I tried out the last solution that @mjhenkes offered and didn't work either.
So after that I chose to do the login by myself and copy the tokens manually in cypress.env and then run the test. This is not ideal but I thought if in the future version the OIDC login problem got solved in Cypress, all I have to change is the login method. this way the rest of my code wouldn't need refactoring.
Thank you for the time,
Looking forward to hear from you

@AtofStryker AtofStryker reopened this Mar 28, 2023
@ntvinhit
Copy link

ntvinhit commented Mar 28, 2023

Same issue.
In my case is:

I can login normally, and very fast if I don't use cy.session wrap the cy.origin.
If I use cy.session wrap cy.origin, the page inside cy.origin takes ~10 minutes to trigger page load event.

Still have no clue.


Edit:

  • It very fast for both case (wrap with session or not) in my local machine.
  • But very slow on CircleCI if I wrap with session, don't wrap is okay.

@AtofStryker
Copy link
Contributor

Interesting. Is there anyway we can either get a full reproduction repository where we can reproduce the issue from cloning a git repository? I think I have seen this issue before when logging into twitter with Cypress, but the issue hasn't been present for some time (with twitter at least). I think the struggle currently is going to be able to reproduce this, which will allow us to identify and solve the problem. Would either of you be able to provide a fully reproducible example?

@ntvinhit
Copy link

I have updated the above comment.
It's very hard to make a reproduction repository because:

  • It's related to private thing on my organization
  • It works fine on my machine, just not work on CircleCI

I have tried to SSH to CircleCI to debug but still have no clue, everything look good, just page load event not fired

@stephenmee
Copy link

I have a similar issue and have been communicating with @canourrea23 on it. I shared a repository and credentials which she has been able to use to reproduce this issue. The issue is a blocker for us so it would be great if this issue could be prioritised.

@AtofStryker
Copy link
Contributor

Hi @stephenmee. We have the reproduction and are able to reproduce it. I am going to route this issue over to the e2e team.

@AtofStryker AtofStryker added Reproducible Can be reproduced and removed Needs Reproduction labels May 23, 2023
@nagash77 nagash77 added E2E Issue related to end-to-end testing Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. labels May 30, 2023
@stephenmee
Copy link

Hi @AtofStryker @canourrea23 is there any update on this issue? It is a complete blocker for our automation.

@pookdeveloper
Copy link

Same problem here login not finish
image

@pookdeveloper
Copy link

I have solved it by doing the normal login with a cypress command. I leave an example: the important thing is to use cy.origin

My env:

env: {
    URL: 'http://localhost:4200',
    EMAIL: 'xxx',
    PASSWORD: 'xxx'
  }
Cypress.Commands.add('login', (url, email, password) => {
  cy.session('appLogin', () => {
    cy.clearData();
    cy.visit(url);
    cy.origin('https://login.microsoftonline.com',
      {args: [email, password]},
      ([email, password]) => {
        cy.get('#otherTile').then(($element) => {
          if ($element.length !== 0) {
            $element.click();
            cy.log('Elemento encontrado');
          }
        });
        cy.get('input[type=\'email\']').click({force: true});
        cy.get('input[type=\'email\']').type(email);
        cy.get('input[type=\'submit\']').click({force: true});
        cy.get('input[name=\'passwd\']').type(password);
        cy.get('input[type=\'submit\']').click({force: true});
        cy.get('[type="checkbox"]').check()
        cy.get('input[type=\'submit\']').click({force: true});
      });
    cy.wait(3000);
    cy.visit(url);
  });
});
describe('TestFormComponent', () => {
  beforeEach(() => {
    cy.login(Cypress.env('URL'), Cypress.env('EMAIL'), Cypress.env('PASSWORD'));
    cy.wait(3000);
    cy.visit(Cypress.env('URL'));
  });

 xit('should disable yearSubscriptionInput date', () => {
    cy.get('[formControlName="yearEffect"]').type('2020');
    cy.get('[formControlName="yearSubscription"]').should('be.empty');
    cy.get('[formControlName="yearSubscription"]').should('be.disabled');
    cy.get('[formControlName="yearEffect"]').should('have.value', '2020');
  });
});

@MajidBabaeifar
Copy link
Author

@pookdeveloper
Thank you for the time you put in. Unfortunately I don't have access to that project anymore but as I remember I'm pretty sure I tried this solution as well and it didn't work.
But just out of curiosity, why did you use both cy.wait(3000) and cy.visit() twice? once in your login custom command and once in your beforeEach() method?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E2E Issue related to end-to-end testing Reproducible Can be reproduced Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. type: bug
Projects
None yet
Development

No branches or pull requests

9 participants