How to Handle OAuth2.0 Authentication in API Testing with Playwright
To test authenticated APIs in our dev/stage/prod environment using OAuth 2.0, we can create a new request context with the token from the OAuth 2.0 authentication. In the Playwright test file, we can add the logic for creating the new request context in the test.beforeAll
hook.
My test file code is
import { test, expect, APIRequestContext } from '@playwright/test';
import { getRequestContext } from '../utils/playwright-context';
import postEnquiryData from '../mocks/request_body/post-enquiry';
import patchEnquiryData from '../mocks/request_body/patch-enquiry';
let apiContext: APIRequestContext;
const id = '01FRQW9R32AT50CS5BWE3JCWZR';
test.describe('Enquiries E2E tests', () => {
test.beforeAll(async () => {
apiContext = await getRequestContext({
apiEndpoint: process.env.API_ENDPOINT as string,
tokenEndpoint: process.env.OIDC_TOKEN_URL as string,
tokenClientId: process.env.OIDC_CLIENT_ID as string,
tokenClientSecret: process.env.OIDC_CLIENT_SECRET as string,
});
});
test('Create an Enquiry', async () => {
const enquiryCreateResponse = await apiContext.post(`/`, {
data: postEnquiryData,
});
expect(enquiryCreateResponse.ok()).toBeTruthy();
const enquiryCreateInfo = await enquiryCreateResponse.json();
expect(enquiryCreateInfo.data).toHaveProperty('id');
});
test('Patch an Enquiry', async () => {
const patchResponse = await apiContext.patch(`/XXXX`, {
data: patchEnquiryData,
});
expect(patchResponse.ok()).toBeTruthy();
});
test.afterAll(async () => {
await apiContext.dispose();
});
});
and my playwright-context.ts
content is
import { request, expect } from '@playwright/test';
type TestConfig = {
apiEndpoint: string;
tokenEndpoint: string;
tokenClientId: string;
tokenClientSecret: string;
};
function getBearerToken(clientId: string, secret: string) {
const btoa = (str: string) => Buffer.from(str).toString('base64');
const credentialsBase64 = btoa(`${clientId}:${secret}`);
return credentialsBase64;
}
export async function getRequestContext(testConfig: TestConfig) {
const authContext = await request.newContext({
baseURL: testConfig.tokenEndpoint,
extraHTTPHeaders: {
Authorization: `Basic ${getBearerToken(testConfig.tokenClientId, testConfig.tokenClientSecret)}`,
},
});
const signinResponse = await authContext.post('', {
form: {
grant_type: 'client_credentials',
},
});
expect(signinResponse.ok()).toBeTruthy();
const authInfo = await signinResponse.json();
const token = authInfo.access_token;
const apiContext = await request.newContext({
baseURL: testConfig.apiEndpoint,
extraHTTPHeaders: {
Authorization: `Bearer ${token}`,
},
});
return apiContext;
}