Bypass 2FA with Playwright .NET
Playwright is a tool for end-to-end (e2e) browser testing. Most business logic usually requires a logged-in user, so we need to authenticate the test user from our code programmatically.
One of the challenges of automatic login in e2e testing is 2-factor authentication or 2FA. Even though it doesn’t make much sense to have 2FA enabled for test users, being able to log in with a 2FA user can be very handy sometimes.
In this article, we explore how we can utilize an authenticated browser state and manual login to bypass 2-factor authentication in our playwright tests.
What is Playwright’s authenticated browser state?
Technically, it’s just a json file that contains a browser state - cookies and local storage. This file can be reused between test executions and, thus, cookies and local storage are also reused.
Since web app authentication is usually implemented based on cookies or tokens (stored in the local storage), we can:
- log in with a user
- save the browser state to a file
- load the state for each test, eliminating the need to log in each time
How to save Playwright’s browser state to a file?
We can save a browser state either programmatically or manually. Since it is hard to programmatically log in with a 2FA user, we are going to do it manually.
The following command opens the browser and, once the window is closed, the browser cookies and local storage data will be written to auth.json
:
pwsh playwright.ps1 open --save-storage=auth.json
Execute this command from the folder where playwright.ps1
is located. For me, it’s bin/Debug/net7.0/
, but your path can slightly differ depending on the .NET version you are using. Make sure you have built your project, you won’t be able to find playwright.ps1
otherwise since it’s generated during the first build for Playwright .NET.
Once a new browser window is opened, log in with your user and close the browser. At this point, you should have the auth.json
file generated, open it and validate that the local storage and cookies are indeed saved.
How to use a browser state file in Playwright .NET tests?
We can now use the file we generated in the previous step to reuse the cookies and local storage of the logged-in user in our tests:
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new()
{
Headless = false,
SlowMo = 2000,
});
// Create a new context with the saved storage state.
var context = await browser.NewContextAsync(new()
{
StorageStatePath = "auth.json"
});
// Page will be using the context from auth.json,
// so you can write your test assuming the user is already logged in.
var page = await context.NewPageAsync();
await page.GotoAsync("https://github.com/");
Summary
- Ideally, users, used for end-to-end tests, do not have 2FA enabled.
- If we have to use a user with 2FA in our Playwright tests, we can do it with authenticated browser state feature.
- Browser state file can be generated by executing
pwsh playwright.ps1 open --save-storage=auth.json
command, logging in manually and closing the browser. - Once the browser state file is generated, we can use it in our tests by supplying a
BrowserNewContextOptions
object withStorageStatePath
tobrowser.NewContextAsync
method. - Do not commit your browser state file to a repo, make sure it is ignored in
.gitignore
. - For Node.js playwright, the command is
npx playwright open --save-storage auth.json
.