Skip to content

Authentication Testing in Cypress

Nearly every real application requires logging in before testing most features. This lesson compares the main authentication testing strategies before diving deeper into login testing, cy.session(), JWTs, and protected routes.

Three Ways to Authenticate in Tests

You can log in through the actual UI (typing credentials and clicking submit), through a direct API call that returns a session token or cookie, or by caching a previously established session with cy.session() so repeated logins across tests are nearly instant.

// UI login: slow, but tests the real login flow itself
cy.visit('/login');
cy.get('[data-cy="email"]').type('user@example.com');
cy.get('[data-cy="password"]').type('SecurePass123!');
cy.get('[data-cy="submit"]').click();

// API login: fast, skips the UI entirely for setup purposes
cy.request('POST', '/api/login', { email: 'user@example.com', password: 'SecurePass123!' });

Both achieve "being logged in", but the API version is dramatically faster when login itself isn't what's under test.

Choosing a Strategy

UI login       -> use only in dedicated login-flow tests
API login      -> use as setup for tests about other features
cy.session()   -> cache either UI or API login across many tests
  • Reserve UI-driven login for tests actually verifying the login experience itself.
  • Use API-based login as fast setup for tests focused on other features.
  • cy.session() caches a login (of either kind) so it doesn't need to be repeated for every test.

Authentication Strategy Cheat Sheet

Matching a strategy to the actual thing being tested.

Test's Actual Focus Recommended Login Strategy
The login page/flow itself UI-driven login
A feature that requires being logged in API login + cy.session()
Multiple tests needing the same logged-in user cy.session() caching
Different roles/permissions per test API login with role-specific credentials

Why API-Based Login Is Usually Better for Setup

If a test's actual purpose is to verify, say, a shopping cart feature, repeating a full UI login in every single test adds seconds of runtime and an extra point of failure unrelated to what's actually being tested. Logging in via a direct API call and setting the resulting cookie/token achieves the same authenticated state far faster and more reliably.

  • UI login couples every unrelated test to the login page's own stability.
  • API login is typically 5-20x faster than clicking through a real login form.
  • Dedicate a small number of tests specifically to verifying the UI login flow itself.

Common Authentication Mechanisms You'll Encounter

Applications authenticate users through several common mechanisms, each needing slightly different test setup: session cookies, JWTs stored in local storage or cookies, or third-party OAuth providers.

Mechanism Typical Test Setup
Session cookie API login sets the cookie automatically for the test's browser
JWT in localStorage API login response token set via window.localStorage.setItem()
JWT in cookie API login sets the cookie; Cypress includes it automatically
OAuth / SSO Typically stubbed or bypassed with a test-only backend shortcut

Common Mistakes

  • Logging in through the real UI in every single test file, regardless of what feature is actually under test.
  • Not distinguishing tests about the login flow itself from tests that merely require being logged in.
  • Forgetting that JWTs stored in localStorage need to be set manually after an API-based login.
  • Trying to test real third-party OAuth flows directly instead of stubbing or bypassing them in test environments.

Key Takeaways

  • UI login, API login, and cy.session() caching each serve a different purpose.
  • Reserve UI-driven login for tests specifically about the login experience.
  • API-based login is significantly faster and more reliable for unrelated feature tests.
  • Different auth mechanisms (cookies, JWTs, OAuth) need slightly different test setup approaches.

Pro Tip

Audit your suite periodically for tests that still perform a full UI login purely as setup, each one you convert to API login plus cy.session() typically saves several seconds per test, adding up to meaningful total suite runtime savings across hundreds of tests.