From 8113d3bdef16993c27bc572122dbffd9d7571897 Mon Sep 17 00:00:00 2001 From: Jacob Fletcher Date: Fri, 12 Sep 2025 16:57:03 -0400 Subject: [PATCH] fix(next): exclude permissions from page response when unauthenticated (#13796) Similar spirit as #13714. Permissions are embedded into the page response, exposing some field names to unauthenticated users. For example, when setting `read: () => false` on a field, that field's name is now included in the response due to its presence in the permissions object. We now search the HTML source directly in the test, similar to "view source" in the browser, which will be much effective at preventing regression going forward. --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1211347942663256 --- packages/next/src/layouts/Root/index.tsx | 2 +- test/auth/config.ts | 6 ++++++ test/auth/e2e.spec.ts | 16 +++++++++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/next/src/layouts/Root/index.tsx b/packages/next/src/layouts/Root/index.tsx index 3244b4c04..7a0b58fed 100644 --- a/packages/next/src/layouts/Root/index.tsx +++ b/packages/next/src/layouts/Root/index.tsx @@ -122,7 +122,7 @@ export const RootLayout = async ({ languageCode={languageCode} languageOptions={languageOptions} locale={req.locale} - permissions={permissions} + permissions={req.user ? permissions : null} serverFunction={serverFunction} switchLanguageServerAction={switchLanguageServerAction} theme={theme} diff --git a/test/auth/config.ts b/test/auth/config.ts index 831f25f10..6a35b3615 100644 --- a/test/auth/config.ts +++ b/test/auth/config.ts @@ -190,8 +190,14 @@ export default buildConfigWithDefaults({ label: 'Auth Debug', }, { + // This is a uniquely identifiable field that we use to ensure it doesn't appear in the page source when unauthenticated + // E.g. if the user is authenticated, it will appear in the both the client config name: 'shouldNotShowInClientConfigUnlessAuthenticated', type: 'text', + access: { + // Setting this forces the field to show up in the permissions object + read: () => true, + }, }, ], }, diff --git a/test/auth/e2e.spec.ts b/test/auth/e2e.spec.ts index d44b10795..ee5ffb3fd 100644 --- a/test/auth/e2e.spec.ts +++ b/test/auth/e2e.spec.ts @@ -182,13 +182,17 @@ describe('Auth', () => { await saveDocAndAssert(page, '#action-save') }) - test('should protect the client config behind authentication', async () => { + test('should protect field schemas behind authentication', async () => { await logout(page, serverURL) - // This element is absolutely positioned and `opacity: 0` + // Inspect the page source (before authentication) + const loginPageRes = await page.goto(`${serverURL}/admin/login`) + const loginPageSource = await loginPageRes?.text() + expect(loginPageSource).not.toContain('shouldNotShowInClientConfigUnlessAuthenticated') + + // Inspect the client config (before authentication) await expect(page.locator('#unauthenticated-client-config')).toBeAttached() - // Search for our uniquely identifiable field name await expect( page.locator('#unauthenticated-client-config', { hasText: 'shouldNotShowInClientConfigUnlessAuthenticated', @@ -199,6 +203,7 @@ describe('Auth', () => { await page.goto(serverURL + '/admin') + // Inspect the client config (after authentication) await expect(page.locator('#authenticated-client-config')).toBeAttached() await expect( @@ -206,6 +211,11 @@ describe('Auth', () => { hasText: 'shouldNotShowInClientConfigUnlessAuthenticated', }), ).toHaveCount(1) + + // Inspect the page source (after authentication) + const dashboardPageRes = await page.goto(`${serverURL}/admin`) + const dashboardPageSource = await dashboardPageRes?.text() + expect(dashboardPageSource).toContain('shouldNotShowInClientConfigUnlessAuthenticated') }) test('should allow change password', async () => {