import { test, expect } from '@playwright/test'; /** * Integration: Authentication Middleware Cascade * * Purpose: Validate authentication flows through all middleware layers * Scenarios: Token validation, ACL enforcement, WAF, rate limiting, all in sequence * Success: Valid tokens pass all layers, invalid tokens fail at auth layer */ test.describe('Auth Middleware Cascade', () => { const testProxy = { domain: 'auth-cascade-test.local', target: 'http://localhost:3001', description: 'Test proxy for auth cascade', }; test.beforeEach(async ({ page }) => { await page.goto('/', { waitUntil: 'networkidle' }); await page.waitForSelector('[role="main"]', { timeout: 5000 }); }); test.afterEach(async ({ page }) => { try { await page.goto('/proxy-hosts', { waitUntil: 'networkidle' }); const proxyRow = page.locator(`text=${testProxy.domain}`).first(); if (await proxyRow.isVisible()) { const deleteButton = proxyRow.locator('..').getByRole('button', { name: /delete/i }).first(); await deleteButton.click(); const confirmButton = page.getByRole('button', { name: /confirm|delete/i }).first(); if (await confirmButton.isVisible()) { await confirmButton.click(); } await page.waitForLoadState('networkidle'); } } catch { // Ignore cleanup errors } }); // Missing token → 401 at auth layer test('Request without token gets 401 Unauthorized', async ({ page }) => { await test.step('Create test proxy', async () => { await page.goto('/proxy-hosts', { waitUntil: 'networkidle' }); const addButton = page.getByRole('button', { name: /add|create/i }).first(); await addButton.click(); await page.getByLabel(/domain/i).fill(testProxy.domain); await page.getByLabel(/target|forward/i).fill(testProxy.target); await page.getByLabel(/description/i).fill(testProxy.description); const submitButton = page.getByRole('button', { name: /create|submit/i }).first(); await submitButton.click(); await page.waitForLoadState('networkidle'); }); await test.step('Send request without Authorization header', async () => { const response = await page.request.get( `http://127.0.0.1:8080/api/protected`, { headers: { // Explicitly no Authorization header }, ignoreHTTPSErrors: true, } ); expect(response.status()).toBe(401); }); }); // Invalid token → 401 at auth layer test('Request with invalid token gets 401 Unauthorized', async ({ page }) => { await test.step('Create test proxy', async () => { await page.goto('/proxy-hosts', { waitUntil: 'networkidle' }); const addButton = page.getByRole('button', { name: /add|create/i }).first(); await addButton.click(); await page.getByLabel(/domain/i).fill(testProxy.domain); await page.getByLabel(/target|forward/i).fill(testProxy.target); await page.getByLabel(/description/i).fill(testProxy.description); const submitButton = page.getByRole('button', { name: /create|submit/i }).first(); await submitButton.click(); await page.waitForLoadState('networkidle'); }); await test.step('Send request with malformed token', async () => { const response = await page.request.get( `http://127.0.0.1:8080/api/protected`, { headers: { 'Authorization': 'Bearer invalid_token_xyz_malformed', }, ignoreHTTPSErrors: true, } ); expect(response.status()).toBe(401); }); await test.step('Send request with expired token', async () => { const expiredToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ'; const response = await page.request.get( `http://127.0.0.1:8080/api/protected`, { headers: { 'Authorization': `Bearer ${expiredToken}`, }, ignoreHTTPSErrors: true, } ); expect(response.status()).toBe(401); }); }); // Valid token passes through ACL layer test('Valid token passes ACL validation', async ({ page }) => { await test.step('Create proxy with ACL', async () => { await page.goto('/proxy-hosts', { waitUntil: 'networkidle' }); const addButton = page.getByRole('button', { name: /add|create/i }).first(); await addButton.click(); await page.getByLabel(/domain/i).fill(testProxy.domain); await page.getByLabel(/target|forward/i).fill(testProxy.target); await page.getByLabel(/description/i).fill(testProxy.description); const submitButton = page.getByRole('button', { name: /create|submit/i }).first(); await submitButton.click(); await page.waitForLoadState('networkidle'); }); await test.step('Send request with valid token', async () => { const validToken = await page.evaluate(() => localStorage.getItem('token')); const response = await page.request.get( `http://127.0.0.1:8080/api/test`, { headers: { 'Authorization': `Bearer ${validToken || ''}`, }, ignoreHTTPSErrors: true, } ); // Should pass auth (not 401), may be 404/503 depending on target expect(response.status()).not.toBe(401); }); }); // Valid token passes through WAF layer test('Valid token passes WAF validation', async ({ page }) => { await test.step('Create proxy with WAF', async () => { await page.goto('/proxy-hosts', { waitUntil: 'networkidle' }); const addButton = page.getByRole('button', { name: /add|create/i }).first(); await addButton.click(); await page.getByLabel(/domain/i).fill(testProxy.domain); await page.getByLabel(/target|forward/i).fill(testProxy.target); await page.getByLabel(/description/i).fill(testProxy.description); const wafToggle = page.locator('input[type="checkbox"][name*="waf"]').first(); if (await wafToggle.isVisible()) { const isChecked = await wafToggle.isChecked(); if (!isChecked) { await wafToggle.click(); } } const submitButton = page.getByRole('button', { name: /create|submit/i }).first(); await submitButton.click(); await page.waitForLoadState('networkidle'); }); await test.step('Send valid request (passes auth, passes WAF)', async () => { const validToken = await page.evaluate(() => localStorage.getItem('token')); const response = await page.request.get( `http://127.0.0.1:8080/api/legitimate`, { headers: { 'Authorization': `Bearer ${validToken || ''}`, }, ignoreHTTPSErrors: true, } ); // Should not be 401 (auth failed), not 403 (WAF blocked) expect([200, 404, 503]).toContain(response.status()); }); }); // Valid token passes through rate limiting layer test('Valid token passes rate limiting validation', async ({ page }) => { await test.step('Create proxy with rate limiting', async () => { await page.goto('/proxy-hosts', { waitUntil: 'networkidle' }); const addButton = page.getByRole('button', { name: /add|create/i }).first(); await addButton.click(); await page.getByLabel(/domain/i).fill(testProxy.domain); await page.getByLabel(/target|forward/i).fill(testProxy.target); await page.getByLabel(/description/i).fill(testProxy.description); const rateLimitToggle = page.locator('input[type="checkbox"][name*="rate"]').first(); if (await rateLimitToggle.isVisible()) { const isChecked = await rateLimitToggle.isChecked(); if (!isChecked) { await rateLimitToggle.click(); } } const limitInput = page.locator('input[name*="limit"]').first(); if (await limitInput.isVisible()) { await limitInput.fill('10'); } const submitButton = page.getByRole('button', { name: /create|submit/i }).first(); await submitButton.click(); await page.waitForLoadState('networkidle'); }); await test.step('Send multiple valid requests within limit', async () => { const validToken = await page.evaluate(() => localStorage.getItem('token')); for (let i = 0; i < 5; i++) { const response = await page.request.get( `http://127.0.0.1:8080/api/test-${i}`, { headers: { 'Authorization': `Bearer ${validToken || ''}`, }, ignoreHTTPSErrors: true, } ); // Should pass rate limiting expect(response.status()).not.toBe(429); } }); }); // Valid token passes ALL middleware layers test('Valid token passes auth, ACL, WAF, and rate limiting', async ({ page }) => { await test.step('Create proxy with all protections', async () => { await page.goto('/proxy-hosts', { waitUntil: 'networkidle' }); const addButton = page.getByRole('button', { name: /add|create/i }).first(); await addButton.click(); await page.getByLabel(/domain/i).fill(testProxy.domain); await page.getByLabel(/target|forward/i).fill(testProxy.target); await page.getByLabel(/description/i).fill(testProxy.description); // Enable WAF const wafToggle = page.locator('input[type="checkbox"][name*="waf"]').first(); if (await wafToggle.isVisible()) { const isChecked = await wafToggle.isChecked(); if (!isChecked) { await wafToggle.click(); } } // Enable rate limiting const rateLimitToggle = page.locator('input[type="checkbox"][name*="rate"]').first(); if (await rateLimitToggle.isVisible()) { const isChecked = await rateLimitToggle.isChecked(); if (!isChecked) { await rateLimitToggle.click(); } } const submitButton = page.getByRole('button', { name: /create|submit/i }).first(); await submitButton.click(); await page.waitForLoadState('networkidle'); }); await test.step('Send legitimate requests through full middleware stack', async () => { const validToken = await page.evaluate(() => localStorage.getItem('token')); const start = Date.now(); const response = await page.request.get( `http://127.0.0.1:8080/api/full-stack`, { headers: { 'Authorization': `Bearer ${validToken || ''}`, 'Content-Type': 'application/json', }, ignoreHTTPSErrors: true, } ); const duration = Date.now() - start; // Should pass all middleware expect([200, 404, 503]).toContain(response.status()); console.log(`✓ Request passed all middleware layers in ${duration}ms`); }); await test.step('Verify each middleware would block if violated', async () => { const validToken = await page.evaluate(() => localStorage.getItem('token')); // Test: Missing token → should fail at auth const noAuthResponse = await page.request.get( `http://127.0.0.1:8080/api/full-stack`, { ignoreHTTPSErrors: true, } ); expect(noAuthResponse.status()).toBe(401); // Test: Malicious payload → should fail at WAF (403) const maliciousResponse = await page.request.get( `http://127.0.0.1:8080/?id=1' UNION SELECT NULL--`, { headers: { 'Authorization': `Bearer ${validToken || ''}`, }, ignoreHTTPSErrors: true, } ); expect(maliciousResponse.status()).toBe(403); }); }); });