import assert from "node:assert/strict"; import { createHash, randomBytes } from "node:crypto"; import { chromium } from "playwright-core"; const keycloakUrl = process.env.KEYCLOAK_URL ?? "http://localhost:8080"; const password = process.env.MOCK_GOOGLE_USER_PASSWORD; assert.ok(password); const verifier = randomBytes(48).toString("base64url"); const challenge = createHash("sha256").update(verifier).digest("base64url"); const redirectUri = "http://localhost:8088/"; const browser = await chromium.launch({ executablePath: process.env.CHROME_BIN ?? "/usr/bin/google-chrome", headless: true, args: ["--no-sandbox"], }); try { const page = await browser.newPage(); const authorizationUrl = new URL( `${keycloakUrl}/realms/keycloak-patterns/protocol/openid-connect/auth`, ); authorizationUrl.search = new URLSearchParams({ client_id: "spa-public", redirect_uri: redirectUri, response_type: "code", scope: "openid profile email", state: crypto.randomUUID(), nonce: crypto.randomUUID(), code_challenge: challenge, code_challenge_method: "S256", kc_idp_hint: "mock-google", prompt: "login", }); await page.goto(authorizationUrl.toString()); await page.waitForURL(/\/realms\/mock-google\//u); await page.locator("#username").fill("mock-new-user"); await page.locator("#password").fill(password); await page.locator("#kc-login").click(); await page.waitForURL(/localhost:8088\/\?.*code=/u); const code = new URL(page.url()).searchParams.get("code"); assert.ok(code); const response = await fetch( `${keycloakUrl}/realms/keycloak-patterns/protocol/openid-connect/token`, { method: "POST", body: new URLSearchParams({ grant_type: "authorization_code", client_id: "spa-public", redirect_uri: redirectUri, code, code_verifier: verifier, }), }, ); assert.equal(response.status, 200); const tokens = await response.json(); const payload = JSON.parse( Buffer.from(tokens.access_token.split(".")[1], "base64url").toString(), ); assert.ok(payload.realm_access.roles.includes("employee-role")); console.log("Claim-to-role verified: hd=example.test -> employee-role"); } finally { await browser.close(); }