mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	
		
			
	
	
		
			179 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			179 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | # Authentication
 | ||
|  | Playwright can be used to automate scenarios that require authentication. | ||
|  | 
 | ||
|  | Tests written with Playwright execute in isolated clean-slate environments called | ||
|  | [browser contexts](./core-concepts.md#browser-contexts). This isolation model | ||
|  | improves reproducibility and prevents cascading test failures. New browser | ||
|  | contexts can load existing authentication state. This eliminates the need to | ||
|  | login in every context and speeds up test execution. | ||
|  | 
 | ||
|  | > Note: This guide covers cookie/token-based authentication (logging in via the
 | ||
|  | app UI). For [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) | ||
|  | use [`browser.newContext`](./network.md#http-authentication). | ||
|  | 
 | ||
|  | <!-- GEN:toc --> | ||
|  | - [Automate logging in](#automate-logging-in) | ||
|  | - [Reuse authentication state](#reuse-authentication-state) | ||
|  |   * [Cookies](#cookies) | ||
|  |   * [Local storage](#local-storage) | ||
|  |   * [Session storage](#session-storage) | ||
|  |   * [Lifecycle](#lifecycle) | ||
|  |   * [Example](#example) | ||
|  |   * [API reference](#api-reference) | ||
|  | - [Multi-factor authentication](#multi-factor-authentication) | ||
|  |   * [Persistent authentication](#persistent-authentication) | ||
|  |   * [Lifecycle](#lifecycle-1) | ||
|  |   * [API reference](#api-reference-1) | ||
|  | <!-- GEN:stop --> | ||
|  | 
 | ||
|  | ## Automate logging in
 | ||
|  | 
 | ||
|  | The Playwright API can automate interaction with a login form. See | ||
|  | [Input guide](./input.md) for more details. | ||
|  | 
 | ||
|  | The following example automates login on GitHub. Once these steps are executed, | ||
|  | the browser context will be authenticated. | ||
|  | 
 | ||
|  | ```js | ||
|  | const page = await context.newPage(); | ||
|  | await page.goto('https://github.com/login'); | ||
|  | 
 | ||
|  | // Interact with login form | ||
|  | await page.click('text=Login'); | ||
|  | await page.fill('input[name="login"]', USERNAME); | ||
|  | await page.fill('input[name="password"]', PASSWORD); | ||
|  | await page.click('text=Submit'); | ||
|  | // Verify app is logged in | ||
|  | ``` | ||
|  | 
 | ||
|  | These steps can be executed for every browser context. However, redoing login | ||
|  | for every test can slow down test execution. To prevent that, we will reuse | ||
|  | existing authentication state in new browser contexts. | ||
|  | 
 | ||
|  | ## Reuse authentication state
 | ||
|  | 
 | ||
|  | Web apps use cookie-based or token-based authentication, where authenticated | ||
|  | state is stored as [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) | ||
|  | or in [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage). | ||
|  | The Playwright API can be used to retrieve this state from authenticated contexts | ||
|  | and then load it into new contexts. | ||
|  | 
 | ||
|  | Cookies and local storage state can be used across different browsers. They depend | ||
|  | on your application's authentication model: some apps might require both cookies | ||
|  | and local storage. | ||
|  | 
 | ||
|  | The following code snippets retrieve state from an authenticated page/context and | ||
|  | load them into a new context. | ||
|  | 
 | ||
|  | ### Cookies
 | ||
|  | 
 | ||
|  | ```js | ||
|  | // Get cookies and store as an env variable | ||
|  | const cookies = await context.cookies(); | ||
|  | process.env.COOKIES = JSON.stringify(cookies); | ||
|  | 
 | ||
|  | // Set cookies in a new context | ||
|  | const deserializedCookies = JSON.parse(process.env.COOKIES) | ||
|  | await context.addCookies(deserializedCookies); | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Local storage
 | ||
|  | Local storage ([`window.localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)) | ||
|  | is specific to a particular domain. | ||
|  | 
 | ||
|  | ```js | ||
|  | // Get local storage and store as env variable | ||
|  | const localStorage = await page.evaluate(() => JSON.stringify(window.localStorage)); | ||
|  | process.env.LOCAL_STORAGE = localStorage; | ||
|  | 
 | ||
|  | // Set local storage in a new context | ||
|  | const localStorage = process.env.LOCAL_STORAGE; | ||
|  | await context.addInitScript(storage => { | ||
|  |   if (window.location.hostname === 'example.com') { | ||
|  |     const entries = JSON.parse(storage); | ||
|  |     Object.keys(entries).forEach(key => { | ||
|  |       window.localStorage.setItem(key, entries[key]); | ||
|  |     }); | ||
|  |   } | ||
|  | }, localStorage); | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Session storage
 | ||
|  | Session storage ([`window.sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)) | ||
|  | is specific to a particular domain. | ||
|  | 
 | ||
|  | ```js | ||
|  | // Get session storage and store as env variable | ||
|  | const sessionStorage = await page.evaluate(() => JSON.stringify(sessionStorage)); | ||
|  | process.env.SESSION_STORAGE = sessionStorage; | ||
|  | 
 | ||
|  | // Set session storage in a new context | ||
|  | const sessionStorage = process.env.SESSION_STORAGE; | ||
|  | await context.addInitScript(storage => { | ||
|  |   if (window.location.hostname === 'example.com') { | ||
|  |     const entries = JSON.parse(storage); | ||
|  |     Object.keys(entries).forEach(key => { | ||
|  |       window.sessionStorage.setItem(key, entries[key]); | ||
|  |     }); | ||
|  |   } | ||
|  | }, sessionStorage); | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Lifecycle
 | ||
|  | 
 | ||
|  | Logging in via the UI and then reusing authentication state can be combined to | ||
|  | implement **login once and run multiple scenarios**. The lifecycle looks like: | ||
|  | 
 | ||
|  | 1. Run tests (for example, with `npm run test`). | ||
|  | 2. Login via UI and retrieve authentication state. | ||
|  |     * In Jest, this can be executed in [`globalSetup`](https://jestjs.io/docs/en/configuration#globalsetup-string). | ||
|  | 3. In each test, load authentication state in `beforeEach` or `beforeAll` step. | ||
|  | 
 | ||
|  | This approach will also **work in CI environments**, since it does not rely | ||
|  | on any external state. | ||
|  | 
 | ||
|  | ### Example
 | ||
|  | 
 | ||
|  | [This example script](examples/authentication.js) logs in on GitHub.com with | ||
|  | Chromium, and then reuses the logged in cookie state in WebKit. | ||
|  | 
 | ||
|  | ### API reference
 | ||
|  | - [class `BrowserContext`](./api.md#class-browsercontext) | ||
|  | - [`browserContext.cookies`](./api.md#browsercontextcookiesurls) | ||
|  | - [`browserContext.addCookies`](./api.md#browsercontextaddcookiescookies) | ||
|  | - [`page.evaluate`](./api.md#pageevaluatepagefunction-arg) | ||
|  | - [`browserContext.addInitScript`](./api.md#browsercontextaddinitscriptscript-arg) | ||
|  | 
 | ||
|  | ## Multi-factor authentication
 | ||
|  | Accounts with multi-factor authentication (MFA) cannot be fully automated, and need | ||
|  | manual intervention. Persistent authentication can be used to partially automate | ||
|  | MFA scenarios. | ||
|  | 
 | ||
|  | ### Persistent authentication
 | ||
|  | Web browsers use a directory on disk to store user history, cookies, IndexedDB | ||
|  | and other local state. This disk location is called the [User data directory](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md). | ||
|  | 
 | ||
|  | Note that persistent authentication is not suited for CI environments since it | ||
|  | relies on a disk location. User data directories are specific to browser types | ||
|  | and cannot be shared across browser types. | ||
|  | 
 | ||
|  | User data directories can be used with the `launchPersistentContext` API. | ||
|  | 
 | ||
|  | ```js | ||
|  | const { chromium } = require('playwright'); | ||
|  | 
 | ||
|  | const userDataDir = '/path/to/directory'; | ||
|  | const context = await chromium.launchPersistentContext(userDataDir, { headless: false }); | ||
|  | // Execute login steps manually in the browser window | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Lifecycle
 | ||
|  | 
 | ||
|  | 1. Create a user data directory on disk | ||
|  | 2. Launch a persistent context with the user data directory and login the MFA account. | ||
|  | 3. Reuse user data directory to run automation scenarios. | ||
|  | 
 | ||
|  | ### API reference
 | ||
|  | - [class `BrowserContext`](./api.md#class-browsercontext) | ||
|  | - [`browserType.launchPersistentContext`](./api.md#browsertypelaunchpersistentcontextuserdatadir-options) |