48 lines
2.2 KiB
TypeScript
48 lines
2.2 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { OAUTH_TARGETS, url, BASE_DOMAIN } from '../targets';
|
|
import { completeAuthentikLogin } from '../helpers/authentik';
|
|
|
|
// OIDC/OAuth federation flow — the real SSO integration signal. A healthy app pod
|
|
// does NOT prove SSO works: client mis-registration, redirect-URI mismatch, issuer
|
|
// cert, or a broken Authentik provider all fail HERE, not at the pod. Each test:
|
|
// 1. open the app,
|
|
// 2. click its "sign in via Authentik" control,
|
|
// 3. complete the Authentik login on the redirect,
|
|
// 4. assert we return to the app authenticated.
|
|
const USER = process.env.AK_ADMIN_USER ?? 'akadmin';
|
|
const PASS = process.env.AK_ADMIN_PASSWORD;
|
|
|
|
for (const t of OAUTH_TARGETS) {
|
|
test(`${t.name} SSO login via Authentik`, async ({ page }) => {
|
|
test.skip(!PASS, 'AK_ADMIN_PASSWORD not set — provide via secret to run OAuth flows');
|
|
|
|
await page.goto(url(t), { waitUntil: 'domcontentloaded' });
|
|
|
|
// Click the SSO control.
|
|
const b = t.ssoButton;
|
|
const btn = b.selector
|
|
? page.locator(b.selector).first()
|
|
: page.getByRole((b.role as any) ?? 'link', { name: b.name! }).first();
|
|
await expect(btn, `${t.name}: SSO login control not found`).toBeVisible();
|
|
await btn.click();
|
|
|
|
// We should be redirected to the Authentik domain (or already have a session).
|
|
await page.waitForLoadState('domcontentloaded');
|
|
if (page.url().includes(`.${BASE_DOMAIN}`) && /authentik|\/if\/flow/i.test(page.url())) {
|
|
await completeAuthentikLogin(page, USER, PASS!);
|
|
} else {
|
|
// Not obviously on Authentik — still attempt, in case creds render inline.
|
|
await completeAuthentikLogin(page, USER, PASS!).catch(() => {});
|
|
}
|
|
|
|
// Back in the app, authenticated.
|
|
const s = t.success;
|
|
if (s.urlRe) await expect(page).toHaveURL(s.urlRe, { timeout: 25_000 });
|
|
if (s.selector) await expect(page.locator(s.selector).first()).toBeVisible({ timeout: 25_000 });
|
|
if (s.text) await expect(page.getByText(s.text).first()).toBeVisible({ timeout: 25_000 });
|
|
|
|
await expect(page.getByText(/invalid|unauthorized|access denied|redirect_uri/i)).toHaveCount(0);
|
|
await page.screenshot({ path: `test-results/oauth-${t.name}.png`, fullPage: true });
|
|
});
|
|
}
|