cypress Cypress detected a cross origin error on login redirect in CI - how to fix
Fixes Cypress cross-origin failures when a login flow redirects through a second origin in CI. Use when the run fails with Cypress detected a cross origin error during login or SSO. Covers identifying both origins, wrapping second-origin steps in cy.origin(), and keeping the primary-origin session setup intact. Not for same-origin logins or API-level authentication.
TL;DR
Cypress drives one origin per test by default, so when the app redirects login through a different origin, an identity provider or a second domain, Cypress stops the test with a cross origin error. In CI this often appears for the first time because the CI environment points at a real SSO provider while local development stubs it. Wrap the post-redirect steps in cy.origin() so Cypress explicitly permits the second origin, keep chromeWebSecurity enabled, and do the session setup in the primary origin so the origin block stays as small as possible.
The query
cypress Cypress detected a cross origin error on login redirect in CI - how to fixUse this when
- login redirects to a different origin (SSO, OAuth, SAML) in CI
- Cypress detected a cross origin error appears in the CI output
- local development stubs the identity provider but CI uses the real one
Not for
- a same-origin login form (no cy.origin needed at all)
- authenticating via API with cy.request() instead of the UI (prefer that when possible)
- the error is about iframes or postMessage, not a top-level navigation
Steps
1. Confirm the two origins from the CI log and the app config
Read the cross origin error in the CI output: it names the origin Cypress was on and the origin it tried to navigate to. Verify both against the app's auth configuration for the CI environment.
Cypress detected a cross origin error on page load:
> cy.visit() failed because you are attempting to visit a URL
> that is of a different origin than the one you are currently on.Expected output: both origins are identified: the app origin and the login redirect origin.
2. Wrap the second-origin steps in cy.origin()
Keep everything before the redirect in the primary origin, then put only the steps that run on the second origin inside cy.origin(). Pass any needed values as args, since aliases from the primary origin are not visible inside.
cy.visit('/login');
cy.get('#login-button').click(); // triggers redirect to the identity provider
cy.origin('https://auth.example.com', { args: { user: '[test user]', pass: '[test password]' } },
({ user, pass }) => {
cy.get('#username').type(user);
cy.get('#password').type(pass);
cy.get('button[type=submit]').click();
}
);
cy.url().should('include', '/dashboard');Expected output: the redirect completes and the test continues on the app origin after login.
3. Do session setup in the primary origin
Create the session or seed the login state before the redirect happens, or use cy.session() with a validate function that runs on the app origin. Do not put app-origin assertions inside the cy.origin() callback.
cy.session('login', () => {
cy.visit('/login');
// ... login steps including the cy.origin() block ...
});Expected output: repeat runs reuse the session and the origin block executes only when needed.
4. Verify in CI with the run video
Run the spec in CI and watch the video artifact around the redirect. A passing run with no cross origin error, plus a dashboard page after login, is the acceptance check.
npx cypress run --spec cypress/e2e/login.cy.jsExpected output: the spec passes in CI and the video shows the full redirect round-trip.
Tool compatibility
- Cypress 12 - 14 (cy.origin() stable)
- Cypress 9.6 - 11 (experimentalSessionAndOrigin flag required)
- any browser Cypress supports
Variant phrasings
- Cypress detected a cross origin error on login redirect
- Blocked a frame with origin from accessing a cross-origin frame during login
- cy.origin is not a function (Cypress too old for cross-origin support)
Why it happens
Cypress's automation model historically bound each test to a single origin for security. A login redirect to an identity provider is a genuine cross-origin navigation, so Cypress blocks it unless the test explicitly opts the second origin in with cy.origin(). Local stubs hide this because the stub usually lives on the same origin.
Edge cases / pitfalls
- values and aliases do not cross the origin boundary: pass data through the args option
- do not disable chromeWebSecurity as a shortcut; it changes the security model for the whole run and masks real issues
- third-party cookie blocking in CI browsers can break the return trip even after cy.origin() succeeds; check the session cookie is set
- if the app uses multiple identity providers per environment, parametrize the origin instead of hardcoding it
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_mAVG7ymTh9PRUSynXCLKPA