- quadlet: OAUTH_*/OPENID_* env + EnvironmentFile for the client secret (secret stays off-repo in /home/dank/Containers/open-webui/env, mode 600) - authentik objects created live: application 'open-webui', OAuth2 provider 'Open WebUI' (Strict redirect URI), 'Open WebUI roles' scope mapping, entitlements Open WebUI Users/Admins bound to openwebui_users/admins - e2e: 18-openwebui-sso.spec.ts (silent SSO round-trip) + prefix in config - unit tests: OIDC wiring + secret-hygiene assertions - docs: SSO section + history entry
37 lines
1.5 KiB
TypeScript
37 lines
1.5 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
|
|
// OpenWebUI (ai.franksdank.cloud) authenticates through authentik via the
|
|
// OIDC authorization-code flow. With ONLY the standard authentik session,
|
|
// visiting the vhost must show the "Continue with authentik" button, and
|
|
// clicking it must complete the round-trip silently (no password prompt on
|
|
// the IdP) and land in the logged-in app.
|
|
|
|
test("SSO: OpenWebUI login completes through authentik silently", async ({ page }) => {
|
|
test.setTimeout(180_000);
|
|
await page.goto("https://ai.franksdank.cloud/");
|
|
|
|
// The app is a React SPA; the login page (no local session) renders the
|
|
// OAuth button labelled after the provider name.
|
|
const ssoButton = page.getByRole("button", { name: /continue with authentik/i });
|
|
await expect(ssoButton).toBeVisible({ timeout: 90_000 });
|
|
|
|
// The round-trip: ai -> auth (silent, the session is already there) ->
|
|
// back to ai with the code. No authentik password form may appear.
|
|
await ssoButton.click();
|
|
await expect
|
|
.poll(
|
|
async () => {
|
|
const body = (await page.locator("body").innerText()).toLowerCase();
|
|
return !body.includes("continue with authentik");
|
|
},
|
|
{ timeout: 90_000 },
|
|
)
|
|
.toBe(true);
|
|
await expect
|
|
.poll(() => new URL(page.url()).hostname, { timeout: 60_000 })
|
|
.toBe("ai.franksdank.cloud");
|
|
const body = await page.locator("body").innerText();
|
|
expect(body.toLowerCase()).not.toContain("powered by authentik"); // IdP flow shell
|
|
expect(body.toLowerCase()).not.toContain("password"); // no credential prompt
|
|
});
|