test(e2e): accept IdP redirect as a valid gate in the direct-nav guard spec
Live run against the fleet showed the outpost redirects direct navigation to auth.franksdank.cloud with the guarded host preserved as redirect_uri, rather than rendering the flow UI in place. The security property under test is that an unauthenticated visitor never sees app content; assert that shape (uidField visible + no leak markers + gate is either in-place or a redirect carrying the return path) instead of hostname preservation.
This commit is contained in:
@@ -56,8 +56,8 @@ for (const sub of GUARDED) {
|
||||
await page.goto(`https://${host}/`);
|
||||
|
||||
// The guard resolves (Anubis PoW solves automatically in a real browser)
|
||||
// and presents authentik's flow UI in place — the user never reaches the
|
||||
// app without a session.
|
||||
// and presents authentik's flow UI — either in place or after a redirect
|
||||
// to the IdP host. Either way, the user never reaches the app content.
|
||||
const uid = page.locator('input[name="uidField"]');
|
||||
await expect(uid).toBeVisible({ timeout: 90_000 });
|
||||
|
||||
@@ -66,9 +66,16 @@ for (const sub of GUARDED) {
|
||||
for (const marker of LEAK_MARKERS[host] ?? []) {
|
||||
expect(body, `${host} leaked app content to an unauthenticated user`).not.toContain(marker);
|
||||
}
|
||||
// The response is the IdP's flow UI, not a passthrough: it must be served
|
||||
// by authentik (the flow shell renders "Sign in" / uidField), never the app.
|
||||
expect(new URL(page.url()).hostname).toBe(host);
|
||||
// The guard is present: either the flow UI renders in place on the guarded
|
||||
// vhost, or the browser was redirected to the IdP host (auth.) with the
|
||||
// guarded host preserved as redirect_uri. Both prove a gate; neither leaks.
|
||||
const landed = new URL(page.url()).hostname;
|
||||
expect([host, "auth.franksdank.cloud"], `${host} must gate, not pass through`).toContain(landed);
|
||||
if (landed === "auth.franksdank.cloud") {
|
||||
const params = new URL(page.url()).searchParams;
|
||||
const redirect = params.get("redirect_path") ?? params.get("redirect_uri") ?? "";
|
||||
expect(redirect, `${host} must return to the guarded host after auth`).toContain(sub);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user