Skip to content

Commit 8c27110

Browse files
Update Next.js auth docs examples (#86361)
<!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change(s) that you're making: ## For Contributors ### Improving Documentation - Run `pnpm prettier-fix` to fix formatting issues before opening the PR. - Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide ### Fixing a bug - Related issues linked using `fixes #number` - Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ### Adding a feature - Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas) - Related issues/discussions are linked using `fixes #number` - e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) - Documentation added - Telemetry added. In case of a feature if it's used or not. - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ## For Maintainers - Minimal description (aim for explaining to someone not on the team to understand the PR) - When linking to a Slack thread, you might want to share details of the conclusion - Link both the Linear (Fixes NEXT-xxx) and the GitHub issues - Add review comments if necessary to explain to the reviewer the logic behind a change ### What? Updated the `Layouts and auth checks` section in the authentication documentation (`docs/01-app/02-guides/authentication.mdx`). ### Why? The previous example demonstrating authentication checks within layouts was confusing and contradicted the documentation's own advice against this pattern. This update aims to provide clearer, recommended approaches for implementing authentication checks. ### How? - Removed the misleading layout-based authentication example. - Introduced a new subsection with an example showing authentication checks in a page component. - Added another new subsection with an example demonstrating authentication checks in a leaf component. - Enhanced the "Good to know" section with a reminder about the necessity of authorization checks for Server Actions. Closes NEXT- Fixes # --> --- [Slack Thread](https://vercel.slack.com/archives/C03KAR5DCKC/p1763685748449029?thread_ts=1763685748.449029&cid=C03KAR5DCKC) <a href="https://cursor.com/background-agent?bcId=bc-f490a8eb-8f55-4a85-a31a-357adb24c09a"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-cursor-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-cursor-light.svg"><img alt="Open in Cursor" src="https://cursor.com/open-in-cursor.svg"></picture></a>&nbsp;<a href="https://cursor.com/agents?id=bc-f490a8eb-8f55-4a85-a31a-357adb24c09a"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-web-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-web-light.svg"><img alt="Open in Web" src="https://cursor.com/open-in-web.svg"></picture></a> Co-authored-by: Cursor Agent <[email protected]>
1 parent 5bbcd7d commit 8c27110

File tree

1 file changed

+67
-22
lines changed

1 file changed

+67
-22
lines changed

docs/01-app/02-guides/authentication.mdx

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,51 +1355,96 @@ For example, consider a shared layout that fetches the user data and displays th
13551355
13561356
This guarantees that wherever `getUser()` is called within your application, the auth check is performed, and prevents developers forgetting to check the user is authorized to access the data.
13571357
1358-
```tsx filename="app/layout.tsx" switcher
1359-
export default async function Layout({
1360-
children,
1361-
}: {
1362-
children: React.ReactNode;
1363-
}) {
1364-
const user = await getUser();
1358+
#### Auth checks in page components
1359+
1360+
For example, in a dashboard page, you can verify the user session and fetch the user data:
1361+
1362+
```tsx filename="app/dashboard/page.tsx" switcher
1363+
import { verifySession } from '@/app/lib/dal'
1364+
1365+
export default async function DashboardPage() {
1366+
const session = await verifySession()
1367+
1368+
// Fetch user-specific data from your database or data source
1369+
const user = await getUserData(session.userId)
13651370

13661371
return (
1367-
// ...
1372+
<div>
1373+
<h1>Welcome, {user.name}</h1>
1374+
{/* Dashboard content */}
1375+
</div>
13681376
)
13691377
}
13701378
```
13711379
1372-
```jsx filename="app/layout.js" switcher
1373-
export default async function Layout({ children }) {
1374-
const user = await getUser();
1380+
```jsx filename="app/dashboard/page.jsx" switcher
1381+
import { verifySession } from '@/app/lib/dal'
1382+
1383+
export default async function DashboardPage() {
1384+
const session = await verifySession()
1385+
1386+
// Fetch user-specific data from your database or data source
1387+
const user = await getUserData(session.userId)
13751388

13761389
return (
1377-
// ...
1390+
<div>
1391+
<h1>Welcome, {user.name}</h1>
1392+
{/* Dashboard content */}
1393+
</div>
13781394
)
13791395
}
13801396
```
13811397
1382-
```ts filename="app/lib/dal.ts" switcher
1383-
export const getUser = cache(async () => {
1398+
#### Auth checks in leaf components
1399+
1400+
You can also perform auth checks in leaf components that conditionally render UI elements based on user permissions. For example, a component that displays admin-only actions:
1401+
1402+
```tsx filename="app/ui/admin-actions.tsx" switcher
1403+
import { verifySession } from '@/app/lib/dal'
1404+
1405+
export default async function AdminActions() {
13841406
const session = await verifySession()
1385-
if (!session) return null
1407+
const userRole = session?.user?.role
13861408

1387-
// Get user ID from session and fetch data
1388-
})
1409+
if (userRole !== 'admin') {
1410+
return null
1411+
}
1412+
1413+
return (
1414+
<div>
1415+
<button>Delete User</button>
1416+
<button>Edit Settings</button>
1417+
</div>
1418+
)
1419+
}
13891420
```
13901421
1391-
```js filename="app/lib/dal.js" switcher
1392-
export const getUser = cache(async () => {
1422+
```jsx filename="app/ui/admin-actions.jsx" switcher
1423+
import { verifySession } from '@/app/lib/dal'
1424+
1425+
export default async function AdminActions() {
13931426
const session = await verifySession()
1394-
if (!session) return null
1427+
const userRole = session?.user?.role
13951428

1396-
// Get user ID from session and fetch data
1397-
})
1429+
if (userRole !== 'admin') {
1430+
return null
1431+
}
1432+
1433+
return (
1434+
<div>
1435+
<button>Delete User</button>
1436+
<button>Edit Settings</button>
1437+
</div>
1438+
)
1439+
}
13981440
```
13991441
1442+
This pattern allows you to show or hide UI elements based on user permissions while ensuring the auth check happens at render time in each component.
1443+
14001444
> **Good to know:**
14011445
>
14021446
> - A common pattern in SPAs is to `return null` in a layout or a top-level component if a user is not authorized. This pattern is **not recommended** since Next.js applications have multiple entry points, which will not prevent nested route segments and Server Actions from being accessed.
1447+
> - Ensure that any Server Actions called from these components also perform their own authorization checks, as client-side UI restrictions alone are not sufficient for security.
14031448
14041449
### Server Actions
14051450

0 commit comments

Comments
 (0)