Testing Authentication
This page explains how to test authentication in your application using Playwright and the Keycloak and Credentials providers.
Setting Up Playwright
Playwright is a powerful testing framework that allows you to automate browser interactions. To set up Playwright for testing Auth.js, follow these steps:
- Install Playwright:
npm install -D @playwright/test
- Create a Playwright configuration file:
// playwright.config.js
const { defineConfig, devices } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 30 * 1000,
expect: {
timeout: 5000
},
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
actionTimeout: 0,
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
webServer: {
command: 'npm run dev',
port: 3000,
reuseExistingServer: !process.env.CI,
},
});
Testing with Keycloak
Keycloak is an open-source identity and access management solution that can be used for testing authentication. Here's how to set it up and use it for testing:
Setting Up Keycloak for Testing
- Run Keycloak locally using Docker:
docker run -p 9090:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev
-
Create a realm and user:
- Create a realm named
auth-js - Create a user with username
biyani701and passwordpassword - Create a client with client ID
my-next-auth-app
- Create a realm named
-
Configure environment variables:
# Keycloak OAuth
AUTH_KEYCLOAK_ID=my-next-auth-app
AUTH_KEYCLOAK_SECRET=your-client-secret
AUTH_KEYCLOAK_ISSUER=http://localhost:9090/realms/auth-js
# Test user credentials
TEST_KEYCLOAK_USERNAME=biyani701
TEST_KEYCLOAK_PASSWORD=password
Writing Keycloak Tests
Here's an example of a Playwright test for Keycloak authentication:
// tests/keycloak-auth.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Keycloak Authentication', () => {
test('should show Keycloak provider on sign-in page', async ({ page }) => {
await page.goto('/api/auth/signin');
const keycloakButton = page.getByRole('button', { name: /Keycloak/i });
await expect(keycloakButton).toBeVisible();
});
test('should redirect to Keycloak login page when clicking the provider button', async ({ page }) => {
await page.goto('/api/auth/signin');
const keycloakButton = page.getByRole('button', { name: /Keycloak/i });
await Promise.all([
page.waitForURL(/.*keycloak.*/, { timeout: 10000 }),
keycloakButton.click()
]);
await expect(page).toHaveURL(/.*keycloak.*/);
await expect(page.getByLabel('Username or email')).toBeVisible();
});
test.skip('should successfully sign in with valid Keycloak credentials', async ({ page }) => {
await page.goto('/api/auth/signin');
const keycloakButton = page.getByRole('button', { name: /Keycloak/i });
await keycloakButton.click();
await page.waitForURL(/.*keycloak.*/);
await page.getByLabel('Username or email').fill(process.env.TEST_KEYCLOAK_USERNAME || 'biyani701');
await page.getByLabel('Password').fill(process.env.TEST_KEYCLOAK_PASSWORD || 'password');
await page.getByRole('button', { name: 'Sign In' }).click();
await page.waitForURL(/.*localhost:3000.*/);
await expect(page.getByText(/Signed in as/)).toBeVisible();
});
});
Testing with Credentials Provider
The Credentials provider allows you to test authentication without external dependencies. Here's how to use it:
Setting Up Credentials Provider for Testing
- Add the Credentials provider to your Auth.js configuration:
import Credentials from "next-auth/providers/credentials"
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
// Other providers...
Credentials({
id: "test-credentials",
name: "Test Credentials",
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
if (credentials?.email && credentials?.password) {
return {
id: "1",
name: "Test User",
email: credentials.email,
};
}
return null;
}
}),
],
// Rest of your configuration
})
Writing Credentials Tests
Here's an example of a Playwright test for Credentials authentication:
// tests/credentials-auth.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Credentials Authentication for Testing', () => {
test('should be able to sign in with test credentials', async ({ page }) => {
await page.goto('/api/auth/signin');
await page.getByLabel('Email').fill('test@example.com');
await page.getByLabel('Password').fill('password');
await page.getByRole('button', { name: /sign in with credentials/i }).click();
await page.waitForURL('/');
await expect(page.getByText(/signed in as/i)).toBeVisible();
});
test('should be able to sign out', async ({ page }) => {
// First sign in
await page.goto('/api/auth/signin');
await page.getByLabel('Email').fill('test@example.com');
await page.getByLabel('Password').fill('password');
await page.getByRole('button', { name: /sign in with credentials/i }).click();
await page.waitForURL('/');
// Then sign out
await page.getByRole('button', { name: /sign out/i }).click();
await expect(page.getByText(/not signed in/i)).toBeVisible();
});
});
Running Tests
To run the tests, use the following command:
npx playwright test
To run a specific test file:
npx playwright test tests/keycloak-auth.spec.js
To run tests in debug mode:
npx playwright test --debug