Skip to content

Commit

Permalink
15.1 docs: forbidden, unauthorized, and authInterrupts (#73039)
Browse files Browse the repository at this point in the history
  • Loading branch information
delbaoliveira authored and wyattjoh committed Nov 28, 2024
1 parent 4efc806 commit 87cb593
Show file tree
Hide file tree
Showing 6 changed files with 606 additions and 3 deletions.
50 changes: 50 additions & 0 deletions docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: forbidden.js
description: API reference for the forbidden.js special file.
related:
links:
- app/api-reference/functions/forbidden
version: canary
---

The **forbidden** file is used to render UI when the [`forbidden`](/docs/app/api-reference/functions/forbidden) function is invoked during authentication. Along with allowing you to customize the UI, Next.js will return a `403` status code.

```tsx filename="app/forbidden.tsx" switcher
import Link from 'next/link'

export default function Forbidden() {
return (
<div>
<h2>Forbidden</h2>
<p>You are not authorized to access this resource.</p>
<Link href="/">Return Home</Link>
</div>
)
}
```

```jsx filename="app/forbidden.jsx" switcher
import Link from 'next/link'

export default function Forbidden() {
return (
<div>
<h2>Forbidden</h2>
<p>You are not authorized to access this resource.</p>
<Link href="/">Return Home</Link>
</div>
)
}
```

## Reference

### Props

`forbidden.js` components do not accept any props.

## Version History

| Version | Changes |
| --------- | -------------------------- |
| `v15.1.0` | `forbidden.js` introduced. |
10 changes: 7 additions & 3 deletions docs/01-app/03-api-reference/03-file-conventions/not-found.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@ export default function NotFound() {
}
```

> **Good to know**: In addition to catching expected `notFound()` errors, the root `app/not-found.js` file also handles any unmatched URLs for your whole application. This means users that visit a URL that is not handled by your app will be shown the UI exported by the `app/not-found.js` file.
## Reference

## Props
### Props

`not-found.js` components do not accept any props.

## Data Fetching
> **Good to know**: In addition to catching expected `notFound()` errors, the root `app/not-found.js` file also handles any unmatched URLs for your whole application. This means users that visit a URL that is not handled by your app will be shown the UI exported by the `app/not-found.js` file.
## Examples

### Data Fetching

By default, `not-found` is a Server Component. You can mark it as `async` to fetch and display data:

Expand Down
114 changes: 114 additions & 0 deletions docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: unauthorized.js
description: API reference for the unauthorized.js special file.
related:
links:
- app/api-reference/functions/unauthorized
version: canary
---

The **unauthorized** file is used to render UI when the [`unauthorized`](/docs/app/api-reference/functions/unauthorized) function is invoked during authentication. Along with allowing you to customize the UI, Next.js will return a `401` status code.

```tsx filename="app/unauthorized.tsx" switcher
import Login from '@/app/components/Login'

export default function Unauthorized() {
return (
<main>
<h1>401 - Unauthorized</h1>
<p>Please log in to access this page.</p>
<Login />
</main>
)
}
```

```jsx filename="app/unauthorized.js" switcher
import Login from '@/app/components/Login'

export default function Unauthorized() {
return (
<main>
<h1>401 - Unauthorized</h1>
<p>Please log in to access this page.</p>
<Login />
</main>
)
}
```

## Reference

### Props

`unauthorized.js` components do not accept any props.

## Examples

### Displaying login UI to unauthenticated users

You can use [`unauthorized`](/docs/app/api-reference/functions/unauthorized) function to render the `unauthorized.js` file with a login UI.

```tsx filename="app/dashboard/page.tsx" switcher
import { verifySession } from '@/app/lib/dal'
import { unauthorized } from 'next/server'

export default async function DashboardPage() {
const session = await verifySession()

if (!session) {
unauthorized()
}

return <div>Dashboard</div>
}
```

```jsx filename="app/dashboard/page.js" switcher
import { verifySession } from '@/app/lib/dal'
import { unauthorized } from 'next/server'

export default async function DashboardPage() {
const session = await verifySession()

if (!session) {
unauthorized()
}

return <div>Dashboard</div>
}
```

```tsx filename="app/unauthorized.tsx" switcher
import Login from '@/app/components/Login'

export default function UnauthorizedPage() {
return (
<main>
<h1>401 - Unauthorized</h1>
<p>Please log in to access this page.</p>
<Login />
</main>
)
}
```

```jsx filename="app/unauthorized.js" switcher
import Login from '@/app/components/Login'

export default function UnauthorizedPage() {
return (
<main>
<h1>401 - Unauthorized</h1>
<p>Please log in to access this page.</p>
<Login />
</main>
)
}
```

## Version History

| Version | Changes |
| --------- | ----------------------------- |
| `v15.1.0` | `unauthorized.js` introduced. |
172 changes: 172 additions & 0 deletions docs/01-app/03-api-reference/04-functions/forbidden.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: forbidden
description: API Reference for the forbidden function.
version: canary
related:
links:
- app/api-reference/file-conventions/forbidden
---

The `forbidden` function throws an error that renders a Next.js 403 error page. It is useful for handling authorization errors in your application. You can customize the UI using the [`forbidden.js` file](/docs/app/api-reference/file-conventions/forbidden).

To start using `forbidden`, enable the experimental [`authInterrupts`](/docs/app/api-reference/config/next-config-js/authInterrupts) configuration option in your `next.config.js` file:

```ts filename="next.config.ts" switcher
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
experimental: {
authInterrupts: true,
},
}

export default nextConfig
```

```js filename="next.config.js" switcher
module.exports = {
experimental: {
authInterrupts: true,
},
}
```

`forbidden` can be used in [Server Components](/docs/app/building-your-application/rendering/server-components), [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations), and [Route Handlers](/docs/app/building-your-application/routing/route-handlers).

```tsx filename="app/auth/route.tsx" switcher
import { verifySession } from '@/app/lib/dal'
import { forbidden } from 'next/navigation'

export default async function AdminPage() {
const session = await verifySession()

// Check if the user has the 'admin' role
if (session.role !== 'admin') {
forbidden()
}

// Render the admin page for authorized users
return <></>
}
```

```jsx filename="app/auth/route.js" switcher
import { verifySession } from '@/app/lib/dal'
import { forbidden } from 'next/navigation'

export default async function AdminPage() {
const session = await verifySession()

// Check if the user has the 'admin' role
if (session.role !== 'admin') {
forbidden()
}

// Render the admin page for authorized users
return <></>
}
```

## Good to know

- The `forbidden` function cannot be called in the [root layout](/docs/app/building-your-application/routing/layouts-and-templates#root-layout-required).

## Examples

### Role-based route protection

You can use the `forbidden` function to restrict access to certain routes based on user roles. This ensures that users who are authenticated but lack the required permissions cannot access the route.

```tsx filename="app/admin/page.tsx" switcher
import { verifySession } from '@/app/lib/dal'
import { forbidden } from 'next/navigation'

export default async function AdminPage() {
const session = await verifySession()

// Check if the user has the 'admin' role
if (session.role !== 'admin') {
forbidden()
}

// Render the admin page for authorized users
return (
<main>
<h1>Admin Dashboard</h1>
<p>Welcome, {session.user.name}!</p>
</main>
)
}
```

```jsx filename="app/admin/page.js" switcher
import { verifySession } from '@/app/lib/dal'
import { forbidden } from 'next/navigation'

export default async function AdminPage() {
const session = await verifySession()

// Check if the user has the 'admin' role
if (session.role !== 'admin') {
forbidden()
}

// Render the admin page for authorized users
return (
<main>
<h1>Admin Dashboard</h1>
<p>Welcome, {session.user.name}!</p>
</main>
)
}
```

### Mutations with Server Actions

When implementing mutations in Server Actions, you can use `forbidden` to only allow users with a specific role to update sensitive data.

```tsx filename="app/auth/route.tsx" switcher
'use server'

import { verifySession } from '@/app/lib/dal'
import { forbidden } from 'next/navigation'
import db from '@/app/lib/db'

export async function updateRole(formData: FormData) {
const session = await verifySession()

// Ensure only admins can update roles
if (session.role !== 'admin') {
forbidden()
}

// Perform the role update for authorized users
// ...
}
```

```jsx filename="app/auth/route.js" switcher
'use server'

import { verifySession } from '@/app/lib/dal'
import { forbidden } from 'next/navigation'
import db from '@/app/lib/db'

export async function updateRole(formData) {
const session = await verifySession()

// Ensure only admins can update roles
if (session.role !== 'admin') {
forbidden()
}

// Perform the role update for authorized users
// ...
}
```

## Version History

| Version | Changes |
| --------- | ----------------------- |
| `v15.1.0` | `forbidden` introduced. |
Loading

0 comments on commit 87cb593

Please sign in to comment.