Authentication in Playwright Tests
Almost every meaningful end-to-end test needs a logged-in user. Logging in through the UI in every test is slow (seconds per test, multiplied across hundreds of tests) and fragile (one login-page change breaks everything). Playwright solves this by authenticating once in a setup step, saving the browser's storage state (cookies and localStorage) to a file, and starting every test with that state already loaded.
Real applications add complications: several roles (admin, member, viewer), tests that modify user settings, SSO providers, MFA, and short-lived tokens. The patterns below scale from a simple app to complex multi-role suites, while keeping tests isolated and credentials secure.
TL;DR
- Create a setup project that logs in and saves
storageStateto a file; other projects depend on it and load that state. - Each test still gets a fresh context, pre-populated with the saved session.
- For multiple roles, save one state file per role and select it per project, file, or test (
test.use({ storageState })). - Log in via API when possible: it's faster and less brittle than UI login.
- Tests that mutate account state should use per-worker or per-test accounts.
- Keep credentials in environment variables or secrets, gitignore state files, and avoid real MFA in automated flows.
Quick Example
Core Concepts
Storage State
context.storageState({ path }) serializes cookies and localStorage (and optionally IndexedDB) for all origins to JSON. Loading it via use: { storageState: path } makes new contexts start with the same session, so the app sees an authenticated user immediately. Session storage isn't included; apps that keep tokens only in sessionStorage need an init script to restore them.
Setup Projects and Dependencies
A setup project is a normal Playwright project (matching *.setup.ts) that other projects list in dependencies. Playwright runs it first, and shows it in reports and traces. It's preferred over the older globalSetup because it supports fixtures, tracing, retries, and the HTML report.
Multiple Roles
Common approaches:
- Project per role: tests in
admin/run with the admin state, and others with the user state. test.use({ storageState })in a file or describe block to switch roles.- Multiple contexts in one test for interaction scenarios, such as an admin approving what a user submitted:
Accounts and Isolation
Sharing one account across parallel tests is fine for read-only tests. Tests that change account state (settings, cart, subscriptions) conflict when run in parallel. Options:
- Per-worker accounts: a worker-scoped fixture that logs in as
user-${workerIndex}(see fixtures). - Per-test accounts: create a fresh user via API in a fixture, and log in via API. It gives maximum isolation.
- Reset endpoints in test environments to restore known state.
API-Based Login
If your app supports it, authenticating via an HTTP call (request.post('/api/login')) and saving request.storageState() is faster and doesn't depend on the login UI. Keep one UI login test that covers the actual login page.
SSO, OAuth, and MFA
Third-party identity providers (SSO, OAuth) complicate automated login:
- Prefer a test-only login path in non-production environments, or dedicated test tenants and users in your identity provider with MFA disabled or satisfied by a known factor.
- For TOTP-based MFA, test accounts can store the TOTP secret (securely) and generate codes in the setup step.
- Avoid automating real users' MFA, CAPTCHAs, or production SSO flows. They're designed to stop automation, and bypassing them in production creates risk.
- Sessions expire: regenerate storage state per run (the setup project does), and handle token lifetimes shorter than the suite duration.
Security Considerations
- Credentials: read from environment variables or CI secrets (see secrets management), never hard-coded or committed.
- State files contain live session tokens: add
playwright/.auth/to.gitignore, and don't upload them as CI artifacts. - Test accounts should exist only in test environments, with minimal privileges and no access to real customer data.
- Traces and videos can capture typed passwords and tokens, so mask sensitive fields, and treat artifacts as sensitive.
Best Practices
Authenticate Once per Run, Not per Test
Setup projects plus storage state typically cut suite time dramatically, and remove the login page as a single point of failure for every test.
Keep a Dedicated Login Test
Because most tests bypass the login UI, have explicit tests for the login page itself: success, wrong password, lockout, and password reset.
Match Account Strategy to Test Behavior
Read-only tests can share an account, and mutating tests need isolated accounts. Design fixtures so tests declare which they need.
Verify Login Succeeded in Setup
Assert a post-login indicator (an account menu or a user name) before saving state. Saving state after a failed login makes every test fail confusingly.
Common Mistakes
Committing Storage State Files
playwright/.auth/*.json contains valid session cookies. Committing them leaks access to test environments. Gitignore them.
Parallel Tests Mutating a Shared Account
Two workers changing the same user's preferences or cart produce intermittent failures that look like application bugs. Use per-worker or per-test accounts.
Logging In Through the UI in beforeEach
It multiplies login time across every test, and makes the whole suite fail whenever the login page changes. Use setup projects and storage state.
FAQ
How do I avoid logging in before every Playwright test?
Log in once in a setup project, save storageState to a file, and configure dependent projects to load it with use: { storageState: 'path' }. Every test then starts authenticated, in its own isolated context.
How do I test with multiple user roles?
Save a storage state file per role in setup, and select the right one per project, test file, or test.use block. For scenarios involving several users at once, create multiple browser contexts in one test, each with its own storage state.
Can Playwright handle SSO or MFA logins?
It can automate them in test environments (with test IdP accounts, known TOTP secrets, or test-only login endpoints), but you should avoid automating production MFA or CAPTCHAs. Many teams configure identity providers with dedicated test users and relaxed MFA in staging.
Is storageState secure?
The files contain live session cookies and tokens, so treat them as secrets: gitignore them, avoid uploading them as artifacts, and use test-environment accounts with limited privileges.
Related Topics
- Playwright — The testing framework overview
- Playwright Fixtures — Worker-scoped accounts and projects
- Playwright in CI — Secrets and artifacts in pipelines
- Authentication — The flows being tested
- SSO — Testing with identity providers
- Secrets Management — Handling test credentials