Generate a Google Drive Access Token for Playwright Tests

When testing a browser-side application that uses Google Drive, the normal user flow usually looks like this:

Open the app
Click Google Drive authorization
Choose a Google account
Approve Google Drive access
Return to the app
Use Google Drive features

This works for real users, but it is not a good flow for automated Playwright tests.

Google sign-in and OAuth consent pages may reject automated browsers, require extra account checks, or show security warnings. For that reason, I do not want Playwright to automate the Google OAuth screen.

Instead, I want the test to start with an already-authorized Google Drive access token.

This article shows how to generate a Google Drive access token before running Playwright, then inject that token into a browser-side app.


Scope of This Article

This article focuses on SPA / browser-side Google Drive integrations.

In this kind of app, the browser receives a Google Drive access token and calls the Google Drive API directly.

This article does not cover the server-side pattern.

For a server-side web application, the backend should usually store the Google refresh token, exchange it for an access token, and call Google Drive from the server side. In that case, Playwright should not receive the Google token directly.


Assumption

This article assumes the application already works with Google Drive manually.

That means the normal Google Drive setup is already done:

Google Drive API is already enabled
OAuth consent screen is already configured
The app already has a Google OAuth client
The app can already ask the user to authorize Google Drive
The app can already call the Google Drive API after authorization

Those are normal Google Drive integration steps. They are not specific to Playwright.

This article only covers the extra setup needed to produce an access token before running Playwright tests.


Goal

The goal is to run Playwright tests against a real Google Drive account without manually clicking through the Google OAuth screen during every test run.

The final flow looks like this:

refresh_token
→ exchange for access_token
→ pass access_token to Playwright
→ inject access_token into the browser
→ browser-side app calls the real Google Drive API

This is useful when:

The test needs to use the real Google Drive API
The Google OAuth consent screen should not be automated by Playwright
The application already has a working Google Drive authorization flow
The test needs a repeatable way to start from an already-authorized Google Drive state

Why Not Automate the Google OAuth Page?

At first, it may seem reasonable to let Playwright open the app, click the Google authorization button, choose an account, and approve Google Drive access.

In practice, this is fragile.

It may fail because of:

Google browser automation detection
2-step verification
account security checks
unverified app warnings
consent screen changes
captcha or suspicious login detection

The goal of this test is to test the application’s Google Drive behavior, not Google’s login page.

So the better test design is:

Prepare a valid Google Drive access token before the test
Inject the token into the browser
Let the SPA call the real Google Drive API

Important Concept

There are three important values in this flow:

OAuth Client ID / Client Secret
Refresh Token
Access Token

They are related, but they are not the same thing.

  • OAuth Client ID and Client Secret

The OAuth Client ID identifies the Google OAuth app.

The OAuth Client Secret proves that the token exchange request is coming from that OAuth client.

For Playwright testing, the client secret should stay on the test machine or CI server.

Do not put the client secret in:

frontend code
browser localStorage
Playwright test files committed to Git
public repositories

Playwright itself does not need the client secret.

The test startup script uses the client secret only to generate a fresh access token.

  • Refresh Token

The refresh token represents a Google account that has already authorized the application to access Google Drive.

The refresh token is not used directly to call Google Drive APIs.

Instead, it is used to request a short-lived access token. Google’s OAuth documentation describes this model: store the refresh token for future use, use the access token to access Google APIs, and use the refresh token to obtain a new access token when the previous one expires.

Think of it like this:

refresh_token = long-term authorization
access_token  = short-term API token
  • Access Token

The access token is the token that is actually sent to the Google Drive API.

Example:

Authorization: Bearer ya29.xxxxx

The access token is short-lived, so it should be generated before each test run.

Playwright only needs this access token.


Why Refresh Token Alone Is Not Enough

A refresh token is bound to a specific OAuth client.

When exchanging a refresh token for an access token, Google needs to know:

Which OAuth client is making the request?
Does this OAuth client match the refresh token?
Did the user authorize this OAuth client?

That is why the token exchange requires:

client_id
client_secret
refresh_token

The response contains:

access_token

So the flow is:

client_id + client_secret + refresh_token
→ Google OAuth token endpoint
→ access_token

The access token is then passed to Playwright.


Create a Separate OAuth Client for E2E Token Generation

For automated testing, I use a separate OAuth client only for generating E2E test tokens.

Create this E2E OAuth client in the same Google Cloud project as the real application so the requested Drive scopes and OAuth consent configuration match the app being tested.

This keeps the token generation setup separate from the normal application OAuth client.

Go to:

Google Auth Platform
→ Clients
→ Create client

Create a new OAuth client:

Application type: Web application
Name: Google Drive E2E Token Generator

Add this Authorized redirect URI:

https://developers.google.com/oauthplayground

This redirect URI is needed because OAuth Playground will be used to generate the refresh token.

After creating the client, copy the following values:

OAuth Client ID
OAuth Client Secret

Do not share the client secret.


Get a Refresh Token with OAuth Playground

To generate access tokens automatically, you first need a refresh token.

This is a one-time setup.

Open:

https://developers.google.com/oauthplayground

Click the gear icon in the upper-right corner.

Use these settings:

OAuth flow: Server-side
Access type: Offline
Force prompt: Consent Screen
Use your own OAuth credentials: enabled

Enter the OAuth Client ID and OAuth Client Secret from the E2E token generator client.

Then close the settings panel.

This step is important. OAuth Playground notes that refresh tokens are automatically revoked after 24 hours unless you specify your own application OAuth credentials.

  • Select the Google Drive Scope

In OAuth Playground, select the Google Drive scope your test needs.

For limited file access:

https://www.googleapis.com/auth/drive.file

For read-only access:

https://www.googleapis.com/auth/drive.readonly

For full Google Drive access:

https://www.googleapis.com/auth/drive

Use the smallest scope that supports the test. Google’s Drive API documentation describes drive.file as a scope that lets users choose which files they share with the app, limiting the app’s access compared with broader Drive scopes.

Then click:

Authorize APIs

Choose the Google account used for E2E testing and approve the Google Drive permission request.

After authorization, OAuth Playground returns to Step 2.

Click:

Exchange authorization code for tokens

You should see:

access_token
refresh_token
expires_in
scope
token_type

Save the refresh_token.

The refresh token is the long-term value needed by the test machine.

Do not commit it to Git.


Store the Credentials on the Ubuntu Test Machine

On the Ubuntu test machine, create a private environment file:

nano ~/.google-drive-e2e.env

Add:

export GOOGLE_CLIENT_ID="your-e2e-oauth-client-id"
export GOOGLE_CLIENT_SECRET="your-e2e-oauth-client-secret"
export GOOGLE_REFRESH_TOKEN="your-refresh-token"

Lock down the file permissions:

chmod 600 ~/.google-drive-e2e.env

This file should exist only on the test machine or CI secret storage.


Generate a Fresh Access Token

Install jq if needed:

sudo apt update
sudo apt install -y jq

Load the environment file:

source ~/.google-drive-e2e.env

Exchange the refresh token for an access token:

ACCESS_TOKEN=$(curl -s https://oauth2.googleapis.com/token \
  -d client_id="$GOOGLE_CLIENT_ID" \
  -d client_secret="$GOOGLE_CLIENT_SECRET" \
  -d refresh_token="$GOOGLE_REFRESH_TOKEN" \
  -d grant_type=refresh_token \
  | jq -r .access_token)

echo "$ACCESS_TOKEN"

If successful, the output should be a long access token.

It may start with something like:

ya29.

Test the Access Token Against Google Drive API

Before using Playwright, test the token directly:

curl -s \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://www.googleapis.com/drive/v3/files?pageSize=10&fields=files(id,name,mimeType)" \
  | jq

If this returns JSON, the access token works.

Example response:

{
  "files": [
    {
      "id": "abc123",
      "name": "example.txt",
      "mimeType": "text/plain"
    }
  ]
}

Pass the Access Token to Playwright

Export the access token as an environment variable:

export E2E_GOOGLE_ACCESS_TOKEN="$ACCESS_TOKEN"

Then Playwright can read:

process.env.E2E_GOOGLE_ACCESS_TOKEN

Playwright does not need the refresh token or client secret.

Only the startup script needs those values.


Add E2E Token Support to the SPA

The browser-side app needs a small E2E-only path that accepts the injected token.

For example, during app startup:

const e2eToken = localStorage.getItem('E2E_GOOGLE_ACCESS_TOKEN');

if (e2eToken) {
  setGoogleAccessToken(e2eToken);
}

The actual function name depends on the application.

The idea is:

If E2E_GOOGLE_ACCESS_TOKEN exists in localStorage
→ skip the Google authorization button
→ treat Google Drive as already authorized
→ use this token for Google Drive API calls

This should only be enabled in a test or development environment.

For example:

if (import.meta.env.MODE === 'e2e') {
  const e2eToken = localStorage.getItem('E2E_GOOGLE_ACCESS_TOKEN');

  if (e2eToken) {
    setGoogleAccessToken(e2eToken);
  }
}

Do not allow arbitrary token injection in production.


Inject the Token in Playwright

In the Playwright test:

import { test, expect } from '@playwright/test';

test.beforeEach(async ({ page }) => {
  const accessToken = process.env.E2E_GOOGLE_ACCESS_TOKEN;

  if (!accessToken) {
    throw new Error('Missing E2E_GOOGLE_ACCESS_TOKEN');
  }

  await page.addInitScript((token) => {
    localStorage.setItem('E2E_GOOGLE_ACCESS_TOKEN', token);
  }, accessToken);

  await page.goto('/');
});

test('can open Google Drive feature', async ({ page }) => {
  await expect(page.getByText('Google Drive')).toBeVisible();

  // Continue with your real test steps here.
});

The important part is that page.addInitScript() runs before the SPA scripts execute. Playwright documents that this script is evaluated after the document is created but before the page’s own scripts run.

That allows the SPA to read the token during startup.


Create a Run Script

Create a script named:

run-e2e.sh

Content:

#!/usr/bin/env bash
set -euo pipefail

source "$HOME/.google-drive-e2e.env"

ACCESS_TOKEN=$(curl -s https://oauth2.googleapis.com/token \
  -d client_id="$GOOGLE_CLIENT_ID" \
  -d client_secret="$GOOGLE_CLIENT_SECRET" \
  -d refresh_token="$GOOGLE_REFRESH_TOKEN" \
  -d grant_type=refresh_token \
  | jq -r .access_token)

if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
  echo "Failed to generate Google access token"
  exit 1
fi

export E2E_GOOGLE_ACCESS_TOKEN="$ACCESS_TOKEN"

xvfb-run -a \
  --server-args="-screen 0 1920x1080x24 -ac -nolisten tcp +extension RANDR" \
  npx playwright test --headed

Make it executable:

chmod +x run-e2e.sh

Run the test:

./run-e2e.sh

Did this guide save you time?

Support this site

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top