Files
computer-playbook/roles/web-app-moodle/files/playwright/addons/auth_oidc.spec.js
kevinveenbirkenbach 3dff3fd606 fix(moodle): make the auth_oidc addon carry its own proof
Commit 1cd9578b8 moved the OIDC plugin version out of a hardcoded string
into meta/addons/auth_oidc.yml so the update pipeline tracks it. That
declaration is service-coupled (enabled reads services.sso.enabled), which
obliges the role to ship an integration hook and a per-addon Playwright
spec. Both were missing, so test_addons_integration_tasks and
test_addons_playwright_spec went red.

The hook has no work to do: files/build/install/auth-oidc.sh bakes the
plugin into the image and tasks/04_oidc.yml configures it, included by
tasks/01_manager_ops.yml on the same services.sso.enabled flag. It records
where the wiring actually lives so the coupling stays greppable.

The spec does not follow the pretix shape of hunting a login-page link,
because tasks/04_oidc.yml sets alternateloginurl and /login/index.php
bounces straight to the plugin. It asserts the bounce instead: the login
page must land on the Keycloak openid-connect authorization endpoint
carrying a client_id and a redirect_uri pointing back at auth/oidc.

Rendering the addon flags into playwright.env.j2 is what makes that spec
real. Without lookup('addon_env_flags'), AUTH_OIDC_ADDON_ENABLED is
undefined, skipUnlessAddonEnabled skips forever and the spec is a check
that can never fail.
2026-09-08 15:22:38 +02:00

38 lines
1.6 KiB
JavaScript

const { test, expect } = require("@playwright/test");
const { resolveTimeout } = require("../timeouts");
const { skipUnlessAddonEnabled } = require("../addon-gating");
const { skipUnlessServiceEnabled } = require("../service-gating");
const { gotoOnion } = require("../personas");
test.use({ ignoreHTTPSErrors: true });
test("addon auth_oidc: the login page bounces to the Keycloak authorization endpoint with the OAuth client", async ({ page }) => {
skipUnlessAddonEnabled("auth_oidc");
skipUnlessServiceEnabled("sso");
const appBaseUrl = (process.env.APP_BASE_URL || "").replace(/\/$/, "");
test.skip(!appBaseUrl, "APP_BASE_URL not set for this role");
await page.context().clearCookies();
await gotoOnion(page, `${appBaseUrl}/login/index.php`, { waitUntil: "domcontentloaded" }).catch(() => {});
await page.waitForURL(/openid-connect\/auth/i, { timeout: resolveTimeout(30_000) }).catch(() => {});
const target = page.url();
expect(
target,
"Moodle /login/index.php must land on the Keycloak openid-connect authorization endpoint: auth_oidc installed under auth/oidc and alternateloginurl pointed at it",
).toMatch(/openid-connect\/auth/i);
const authUrl = new URL(target);
expect(
(authUrl.searchParams.get("client_id") || "").length,
"Keycloak authorization request from Moodle must carry the configured OAuth client_id",
).toBeGreaterThan(0);
const redirectUri = authUrl.searchParams.get("redirect_uri") || "";
expect(
/auth\/oidc/i.test(redirectUri),
`Authorization request redirect_uri must point back at the Moodle auth_oidc callback (got: ${redirectUri || "<none>"})`,
).toBe(true);
});