From 0d17b6c006769c389d7f8d15397398b53441b8f8 Mon Sep 17 00:00:00 2001 From: panteliselef Date: Thu, 24 Oct 2024 12:42:04 -0400 Subject: [PATCH 1/3] Replace example with auth in a layout --- docs/references/nextjs/auth.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/references/nextjs/auth.mdx b/docs/references/nextjs/auth.mdx index cbb08a92f9..753b935393 100644 --- a/docs/references/nextjs/auth.mdx +++ b/docs/references/nextjs/auth.mdx @@ -133,21 +133,21 @@ export async function GET() { ## Use `auth.protect()` to check if a user is authenticated -`auth.protect()` can be used in a `layout.tsx` file to protect the entire route, including all children. +`auth.protect()` can be used in a `page.tsx` file to protect any page in your application. In the following example, -- the `auth.protect()` helper is used to check if a user visiting any `/dashboard` route is authenticated. +- the `auth.protect()` helper is used to check if a user visiting the `/dashboard` route is authenticated. - If the user is not authenticated, they will be redirected to the sign-in route. -- If the user is authenticated, they can view any `/dashboard` route and its children. +- If the user is authenticated, they can view the `/dashboard` page. -```tsx {{ filename: 'app/dashboard/layout.tsx' }} +```tsx {{ filename: 'app/dashboard/page.tsx' }} import { auth } from '@clerk/nextjs/server' -export default async function Layout({ children }: { children: React.ReactNode }) { - await auth.protect() +export default async function Page() { + const { userId } = await auth.protect() - return <>{children} + return

Welcome, {userId}

} ``` From 6fb6b0df174e6407c08fc7124b0f1fffdb7859e8 Mon Sep 17 00:00:00 2001 From: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> Date: Thu, 24 Oct 2024 18:17:15 -0400 Subject: [PATCH 2/3] update examples --- .../organizations/verify-user-permissions.mdx | 170 +++++++++++------- docs/references/nextjs/auth.mdx | 20 +-- 2 files changed, 111 insertions(+), 79 deletions(-) diff --git a/docs/organizations/verify-user-permissions.mdx b/docs/organizations/verify-user-permissions.mdx index e0ddc60848..f443efced0 100644 --- a/docs/organizations/verify-user-permissions.mdx +++ b/docs/organizations/verify-user-permissions.mdx @@ -4,7 +4,7 @@ description: A collection of utility functions and components in order to allow --- > [!IMPORTANT] -> The following authorization checks are predicated on a user having an active organization. Without this, they will likely always evaluate to false by default. Learn more about [active organizations](/docs/organizations/overview#active-organization). +> The following authorization checks are predicated on a user having an active organization. Without this, they will likely always evaluate to false by default. Learn more about [active organizations](/docs/organizations/overview#active-organization). If you would like to perform authorization checks without using Clerk's organizations feature, see [the Role Based Access Control (RBAC) guide](/docs/guides/basic-rbac). In general, you should always verify whether or not a user is authorized to access sensitive information, important content, or exclusive features. The most secure way to implement authorization is by checking the active user's [role or permissions](/docs/organizations/roles-permissions#permissions). @@ -18,7 +18,7 @@ Clerk enables two broad approaches to role and permissions-based authorization: ## Authorization in Client Components -The examples below work for both SSR and CSR. Examples are written for Next.js App Router but they are supported by any React meta framework, such as Remix. +The following examples work for both SSR and CSR. ", "has()"]}> @@ -28,7 +28,7 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A 'use client' import { Protect } from '@clerk/nextjs' - export function SettingsForm() { + export default function SettingsForm() { return ( - Use the [`useAuth()`](/docs/references/react/use-auth) hook to access the `has()` helper in Client Components. - The following example uses `has()` to inspect a user's permissions granularly. If the user doesn't have the permission, `has()` returns `false`, causing the component to return `null` instead of rendering its children. ```tsx {{ filename: '/app/dashboard/settings/form.tsx' }} 'use client' import { useAuth } from '@clerk/nextjs' - export function SettingsForm() { + export default function SettingsForm() { const { has } = useAuth() + if (!has) return null + + // Check if the user is authorized const canManageSettings = has({ permission: 'org:team_settings:manage' }) + // If has() returns false, the user does not have the correct permissions + // You can choose how your app responds. This example returns null. if (!canManageSettings) return null + // If the user is both authenticated and authorized, move forward with your logic return
{/* Add UI for managing team settings */}
} ``` @@ -67,7 +71,10 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A ", "has()", "auth.protect()"]}> - The following example uses Clerk's `` component to only render the form for users with the correct permission. If the user is not authorized, the component will not render its children. + The following example uses Clerk's `` component to only render the layout for users with the correct permission. If the user is not authorized, the component will not render its children. + + > [!WARNING] + > Be cautious when doing authorization checks in layouts, as these don't re-render on navigation, meaning the user session won't be checked on every route change. [Read more in the Next.js docs.](https://nextjs.org/docs/app/building-your-application/authentication#layouts-and-auth-checks) ```tsx {{ filename: '/app/dashboard/settings/layout.tsx' }} import type { PropsWithChildren } from 'react' @@ -82,6 +89,9 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A The following example uses `has()` to inspect a user's permissions granularly. If the user doesn't have the correct permission, `has()` returns `false`, causing the component to return `null` instead of rendering its children. + > [!WARNING] + > Be cautious when doing authorization checks in layouts, as these don't re-render on navigation, meaning the user session won't be checked on every route change. [Read more in the Next.js docs.](https://nextjs.org/docs/app/building-your-application/authentication#layouts-and-auth-checks) + ```tsx {{ filename: '/app/dashboard/settings/layout.tsx' }} import type { PropsWithChildren } from 'react' import { auth } from '@clerk/nextjs/server' @@ -89,8 +99,11 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A export default async function SettingsLayout(props: PropsWithChildren) { const { has } = await auth() + // Check if the user is authorized const canAccessSettings = has({ permission: 'org:team_settings:read' }) + // If has() returns false, the user does not have the correct permissions + // You can choose how your app responds. This example returns null. if (!canAccessSettings) return null return props.children @@ -100,7 +113,7 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A > [!WARNING] - > `auth.protect()` only works for App Router and is considered experimental. + > [`auth.protect()`](/docs/references/nextjs/auth#protect) is only available for App Router, and only works on the server-side. The following example uses [`auth.protect()`](/docs/references/nextjs/auth#protect) to protect a RSC from unauthenticated and unauthorized access. @@ -108,14 +121,13 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A - If the user is authenticated but is not authorized (as in, does not have the `org:team_settings:read` permission), `auth.protect()` will throw a `404` error. - If the user is both authenticated and authorized, `auth.protect()` will return the user's `userId`. - ```tsx {{ filename: '/app/dashboard/settings/layout.tsx' }} - import type { PropsWithChildren } from 'react' + ```tsx {{ filename: '/app/dashboard/settings/page.tsx' }} import { auth } from '@clerk/nextjs/server' - export default async function SettingsLayout(props: PropsWithChildren) { + export default async function Page() { const { userId } = await auth.protect({ permission: 'org:team_settings:read' }) - return props.children + return

{userId} is authorized to access this page.

} ```
@@ -131,21 +143,24 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A import { auth } from '@clerk/nextjs/server' export default async function ExampleServerComponent() { - async function myAction(formData: FormData) { + async function myServerAction(formData: FormData) { 'use server' const { has } = await auth() + // Check if the user is authorized const canManage = has({ permission: 'org:team_settings:manage' }) // If has() returns false, the user does not have the correct permissions + // You can choose how your app responds. This example returns a 403 error. if (!canManage) return Response.json({ error: 'User does not have the correct permissions' }, { status: 403 }) - // Add logic for managing team settings + // If the user is both authenticated and authorized, move forward with your logic + return users.getTeams(userId) } return ( -
+ {/* Add UI for managing team settings */}
@@ -161,24 +176,29 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A The example: - - uses the `userId` returned from [`auth()`](/docs/references/nextjs/auth) to check if the user is signed in. If the user is not authenticated, the Route Handler will return a `401` error. - - uses `has()` to check if the user has the correct permission. If the user is not authorized, `has()` will return false, causing the Route Handler to return a `403` error. + - uses the `userId` returned from [`auth()`](/docs/references/nextjs/auth) to check if the user is signed in. If the user is not **authenticated**, the Route Handler will return a `401` error. + - uses `has()` to check if the user has the correct permission. If the user is not **authorized**, `has()` will return false, causing the Route Handler to return a `403` error. ```tsx {{ filename: 'app/api/get-teams/route.tsx' }} import { auth } from '@clerk/nextjs/server' - export const GET = () => { + export const GET = async () => { const { userId, has } = await auth() + // Check if the user is authenticated if (!userId) { return Response.json({ error: 'User is not signed in' }, { status: 401 }) } + // Check if the user is authorized const canRead = has({ permission: 'org:team_settings:read' }) + // If has() returns false, the user does not have the correct permissions + // You can choose how your app responds. This example returns a 403 error. if (!canRead) return Response.json({ error: 'User does not have the correct permissions' }, { status: 403 }) + // If the user is both authenticated and authorized, move forward with your logic return users.getTeams(userId) } ``` @@ -186,7 +206,7 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A > [!WARNING] - > `auth.protect()` only works for App Router and is considered experimental. + > [`auth.protect()`](/docs/references/nextjs/auth#protect) is only available for App Router, and only works on the server-side. The following example uses [`auth.protect()`](/docs/references/nextjs/auth#protect) to protect a Next.js Route Handler from unauthenticated and unauthorized access. @@ -196,12 +216,12 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A ```tsx {{ filename: 'app/api/create-team/route.tsx' }} import { auth } from '@clerk/nextjs/server' - export const POST = async () => { + export const GET = async () => { const { userId } = await auth.protect({ permission: 'org:team_settings:manage', }) - return users.createTeam(userId) + return Response.json({ userId }) } ``` @@ -213,8 +233,8 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A The following example: - - uses the `userId` returned from `getAuth()` to check if the user is signed in. If the user is not authenticated, the route will return a `401` error. - - uses `has()` to check if the user has the correct permission. If the user is not authorized, `has()` will return false, causing the route to return a `403` error. + - uses the `userId` returned from `getAuth()` to check if the user is signed in. If the user is not **authenticated**, the route will return a `401` error. + - uses `has()` to check if the user has the correct permission. If the user is not **authorized**, `has()` will return false, causing the route to return a `403` error. ```tsx {{ filename: 'src/pages/api/get-teams.ts' }} import { getAuth } from '@clerk/nextjs/server' @@ -222,12 +242,17 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A export default async function handler(req: NextApiRequest) { const { userId, has } = await getAuth(req) + // Check if the user is authenticated if (!userId) return res.status(401) + // Check if the user is authorized const canRead = has({ permission: 'org:team_settings:read' }) + // If has() returns false, the user does not have the correct permissions + // You can choose how your app responds. This example returns a 403 error. if (!canRead) return res.status(403) + // If the user is both authenticated and authorized, move forward with your logic return users.getTeams(userId) } ``` @@ -236,53 +261,60 @@ The examples below work for both SSR and CSR. Examples are written for Next.js A ## Authorization in Remix Loaders - - ```tsx - export const loader: LoaderFunction = async (args) => { - const { has } = await getAuth(args) +The following example uses the [`has()`](/docs/references/nextjs/auth-object#has) helper to check if the user has the correct permission. If the user is not authorized, `has()` will return false, causing the loader to redirect the user to the `/request-access` route. - if (has({ permission: 'org:team_settings:manage' })) { - return redirect('/request-access') + + + ```tsx + export const loader: LoaderFunction = async (args) => { + const { has } = await getAuth(args) + + if (has({ permission: 'org:team_settings:manage' }) === false) { + return redirect('/request-access') + } + + return {} } - return {} - } - export default function Settings() { - return ( -
-

Settings Page

-
- ) - } - ``` -
+ export default function Settings() { + return ( +
+

Settings Page

+
+ ) + } + ``` +
+
## Authorization in JavaScript -If you are not using React or any of the meta-frameworks we support, you can use the Clerk JavaScript SDK. The following example demonstrates how to use the [`checkAuthorization()`](/docs/references/javascript/session#check-authorization) method to check if a user is authorized. +If you are not using React or any of the meta-frameworks we support, you can use the [Clerk JavaScript SDK](/docs/references/javascript/overview). The following example demonstrates how to use the [`checkAuthorization()`](/docs/references/javascript/session#check-authorization) method to check if a user is authorized. - ```tsx {{ filename: 'main.js' }} - import { Clerk } from '@clerk/clerk-js' - - // Initialize Clerk with your Clerk publishable key - const clerk = new Clerk('{{pub_key}}') - await clerk.load() - - // Check if the user is authenticated - if (clerk.user) { - // Check if the user is authorized - const canManageSettings = clerk.session.checkAuthorization({ - permission: 'org:team_settings:manage', - }) - } - ``` + + ```tsx {{ filename: 'main.js' }} + import { Clerk } from '@clerk/clerk-js' + + // Initialize Clerk with your Clerk publishable key + const clerk = new Clerk('{{pub_key}}') + await clerk.load() + + // Check if the user is authenticated + if (clerk.user) { + // Check if the user is authorized + const canManageSettings = clerk.session.checkAuthorization({ + permission: 'org:team_settings:manage', + }) + } + ``` + ## Authorize with roles > [!WARNING] -> We suggest permission-based authorization over role-based authorization, as it reduces complexity and increases security. Usually, complex role checks can be refactored with a single permission check. +> It's best practice to use permission-based authorization over role-based authorization, as it reduces complexity and increases security. Usually, complex role checks can be refactored with a single permission check. You can pass a `role` the same way you can pass a `permission` in all the examples above. @@ -290,16 +322,15 @@ You can pass a `role` the same way you can pass a `permission` in all the exampl The following example uses ``'s `condition` prop to conditionally render its children if the user has the correct role. - ```tsx {{ filename: '/app/dashboard/settings/layout.tsx' }} - import type { PropsWithChildren } from 'react' + ```tsx {{ filename: '/app/dashboard/settings/Page.tsx' }} import { Protect } from '@clerk/nextjs' - export default function SettingsLayout(props: PropsWithChildren) { + export default function Page() { return ( has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })} > - {props.children} +

Admin settings

) } @@ -308,7 +339,7 @@ You can pass a `role` the same way you can pass a `permission` in all the exampl > [!WARNING] - > `auth.protect()` only works for App Router and is considered experimental. + > [`auth.protect()`](/docs/references/nextjs/auth#protect) is only available for App Router, and only works on the server-side. The following example uses [`auth.protect()`](/docs/references/nextjs/auth#protect) to protect a RSC from unauthenticated and unauthorized access. @@ -316,23 +347,20 @@ You can pass a `role` the same way you can pass a `permission` in all the exampl - If the user is authenticated but is not authorized (as in, does not have the `org:admin` or `org:billing_manager` role), `auth.protect()` will throw a `404` error. - If the user is both authenticated and authorized, `auth.protect()` will return the user's `userId`. - ```tsx {{ filename: '/app/dashboard/settings/layout.tsx' }} - import type { PropsWithChildren } from 'react' + ```tsx {{ filename: '/app/dashboard/settings/page.tsx' }} import { auth } from '@clerk/nextjs/server' - export default async function SettingsLayout(props: PropsWithChildren) { - const { userId } = await auth.protect( + export default async function Page() { + const { userId } = await auth().protect( (has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' }), ) - return props.children + return

{userId} is authorized to access this page.

} ```
- Use the [`useAuth()`](/docs/references/react/use-auth) hook to access the `has()` helper in Client Components. - The following example uses `has()` to inspect a user's roles granularly. If the user doesn't have the correct role, `has()` returns `false`, causing the component to return `null` instead of rendering its children. ```tsx {{ filename: '/app/dashboard/settings/form.tsx' }} @@ -342,10 +370,14 @@ You can pass a `role` the same way you can pass a `permission` in all the exampl export function SettingsForm() { const { has } = useAuth() + // Check if the user is authorized const canAccessSettings = has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' }) + // If has() returns false, the user does not have the correct permissions + // You can choose how your app responds. This example returns null. if (!canAccessSettings) return null + // If the user is both authenticated and authorized, move forward with your logic return
{/* Add UI for team settings */}
} ``` diff --git a/docs/references/nextjs/auth.mdx b/docs/references/nextjs/auth.mdx index 753b935393..f0df33daeb 100644 --- a/docs/references/nextjs/auth.mdx +++ b/docs/references/nextjs/auth.mdx @@ -5,7 +5,7 @@ description: Access minimal authentication data for managing sessions and data f The `auth()` helper returns the [`Auth`](/docs/references/nextjs/auth-object) object of the currently active user. This is the same `Auth` object that is returned by the [`getAuth()`](/docs/references/nextjs/get-auth) hook. However, it can be used in Server Components, Route Handlers, and Server Actions. -The `auth()` helper does require [Middleware](/docs/references/nextjs/clerk-middleware). +The `auth()` helper requires [Middleware](/docs/references/nextjs/clerk-middleware). It is only available for App Router, and only works on the server-side. ## Returns @@ -15,9 +15,6 @@ The `auth()` helper does require [Middleware](/docs/references/nextjs/clerk-midd ### `auth.protect()` -> [!WARNING] -> `auth.protect()` only works for App Router and is considered experimental. - You can use the `auth.protect()` helper in two ways: - to check if a user is authenticated (signed in) @@ -54,7 +51,7 @@ The following table describes how the `auth.protect()` helper behaves based on u - `has?` - `(isAuthorizedParams: CheckAuthorizationParamsWithCustomPermissions) => boolean` - A function that returns a boolean based on the permission or role provided as parameter. Can be used for authorization. See the dedicated [`has()`](/docs/references/nextjs/auth-object#has) section for more information. + A function that returns a boolean based on the permission or role provided as parameter. Can be used for authorization. See [the dedicated `has()` section](/docs/references/nextjs/auth-object#has) for more information. --- @@ -139,7 +136,7 @@ In the following example, - the `auth.protect()` helper is used to check if a user visiting the `/dashboard` route is authenticated. - If the user is not authenticated, they will be redirected to the sign-in route. -- If the user is authenticated, they can view the `/dashboard` page. +- If the user is authenticated, `auth.protect()` returns the user's `userId`, and they can view the `/dashboard` page. ```tsx {{ filename: 'app/dashboard/page.tsx' }} import { auth } from '@clerk/nextjs/server' @@ -155,7 +152,7 @@ export default async function Page() { `auth()` returns the [`Auth`](/docs/references/nextjs/auth-object#auth-object) object, which includes the [`has()`](/docs/references/nextjs/auth-object#has) helper. -You can protect certain parts of your application or even entire routes based on user authorization status by checking if the user has the required roles or permissions. +You can protect certain parts of your application or even entire routes based on a user's authorization status by checking if the user has the required permissions or roles. Learn more about authorization checks in [the dedicated guide](/docs/organizations/verify-user-permissions). - Use `auth.protect()` if you want Clerk to return a `404` if the user does not have the role or permission. - Use `has()` if you want more control over what your app does based on the authorization status instead of immediately returning a `404`. @@ -173,19 +170,20 @@ You can protect certain parts of your application or even entire routes based on export default async function Page() { const { has } = await auth() + // Check if the user is authorized const canManage = has({ permission: 'org:team_settings:manage' }) + // If has() returns false, the user does not have the correct permissions + // You can choose how your app responds. This example returns null. if (!canManage) return null + // If the user is both authenticated and authorized, move forward with your logic return

Team Settings

} ```
- > [!WARNING] - > `auth.protect()` only works for App Router and is considered experimental. - The following example uses `auth.protect()` to protect a Next.js Route Handler from unauthenticated and unauthorized access. - If the user is not authenticated, `auth.protect()` will redirect the user to the sign-in route. @@ -196,8 +194,10 @@ You can protect certain parts of your application or even entire routes based on import { auth } from '@clerk/nextjs/server' export const POST = async () => { + // Check if the user is authorized const { userId } = await auth.protect({ permission: 'org:team_settings:manage' }) + // If the user is both authenticated and authorized, move forward with your logic return users.createTeam(userId) } ``` From 167806ba6a57ec661b7de43bf2a28942184ab5d3 Mon Sep 17 00:00:00 2001 From: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:21:15 -0400 Subject: [PATCH 3/3] updates --- .../organizations/verify-user-permissions.mdx | 2 +- docs/references/nextjs/auth.mdx | 140 ++++-------------- 2 files changed, 33 insertions(+), 109 deletions(-) diff --git a/docs/organizations/verify-user-permissions.mdx b/docs/organizations/verify-user-permissions.mdx index f443efced0..87de1b1c46 100644 --- a/docs/organizations/verify-user-permissions.mdx +++ b/docs/organizations/verify-user-permissions.mdx @@ -351,7 +351,7 @@ You can pass a `role` the same way you can pass a `permission` in all the exampl import { auth } from '@clerk/nextjs/server' export default async function Page() { - const { userId } = await auth().protect( + const { userId } = await auth.protect( (has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' }), ) diff --git a/docs/references/nextjs/auth.mdx b/docs/references/nextjs/auth.mdx index f0df33daeb..9cf89c08bd 100644 --- a/docs/references/nextjs/auth.mdx +++ b/docs/references/nextjs/auth.mdx @@ -3,24 +3,20 @@ title: '`auth()`' description: Access minimal authentication data for managing sessions and data fetching. --- -The `auth()` helper returns the [`Auth`](/docs/references/nextjs/auth-object) object of the currently active user. This is the same `Auth` object that is returned by the [`getAuth()`](/docs/references/nextjs/get-auth) hook. However, it can be used in Server Components, Route Handlers, and Server Actions. +The `auth()` helper returns the [`Auth`](/docs/references/nextjs/auth-object) object of the currently active user, as well as the [`redirectToSignIn()`](#redirect-to-sign-in) method. -The `auth()` helper requires [Middleware](/docs/references/nextjs/clerk-middleware). It is only available for App Router, and only works on the server-side. +- Only available for App Router. +- Only works on the server-side, such as in Server Components, Route Handlers, and Server Actions. +- Requires [`clerkMiddleware()`](/docs/references/nextjs/clerk-middleware) to be configured. -## Returns +## `auth.protect()` -`auth()` returns the [`Auth`](/docs/references/nextjs/auth-object) object with a few extra properties: - -- [`redirectToSignIn()`](#redirect-to-sign-in) - -### `auth.protect()` - -You can use the `auth.protect()` helper in two ways: +`auth` includes a single property, the `protect()` method, which you can use in two ways: - to check if a user is authenticated (signed in) - to check if a user is authorized (has the correct roles or permissions) to access something, such as a component or a route handler -The following table describes how the `auth.protect()` helper behaves based on user authentication or authorization status: +The following table describes how `auth.protect()` behaves based on user authentication or authorization status: | Authenticated | Authorized | `auth.protect()` will | | - | - | - | @@ -68,11 +64,15 @@ The following table describes how the `auth.protect()` helper behaves based on u The URL to redirect the user to if they are not authenticated. -For more information on how to use `auth.protect()`, see the [examples](#use-auth-to-check-if-a-user-is-authenticated) in this guide. There are also examples in the [Verify user permissions](/docs/organizations/verify-user-permissions) guide. +### Examples + +`auth.protect()` can be used to check if a user is authenticated or authorized to access certain parts of your application or even entire routes. See detailed examples in [the dedicated guide.](/docs/organizations/verify-user-permissions) -### `redirectToSignIn()` +## `redirectToSignIn()` -`redirectToSignIn()` is a method that redirects the user to the sign-in page. It accepts the following parameters: +The `auth()` helper returns the `redirectToSignIn()` method, which you can use to redirect the user to the sign-in page. + +`redirectToSignIn()` accepts the following parameters: - `returnBackUrl?` @@ -84,6 +84,22 @@ For more information on how to use `auth.protect()`, see the [examples](#use-aut > [!NOTE] > `auth()` on the server-side can only access redirect URLs defined via [environment variables](/docs/deployments/clerk-environment-variables#sign-in-and-sign-up-redirects) or [`clerkMiddleware` dynamic keys](/docs/references/nextjs/clerk-middleware#dynamic-keys). +### Example + +The following example shows how to use `redirectToSignIn()` to redirect the user to the sign-in page if they are not authenticated. It's also common to use `redirectToSignIn()` in `clerkMiddleware()` to protect entire routes; see [the `clerkMiddleware()` docs](/docs/references/nextjs/clerk-middleware) for more information. + +```tsx {{ filename: 'app/page.tsx' }} +import { auth } from '@clerk/nextjs/server' + +export default async function Page() { + const { userId, redirectToSignIn } = await auth() + + if (!userId) return redirectToSignIn() + + return

Hello, {userId}

+} +``` + ## Use `auth()` to retrieve `userId` You can use `auth()` to check if a `userId` exists. If it does not, that means there is no user signed in. You can use this information to protect pages, as shown in the following example: @@ -128,98 +144,6 @@ export async function GET() { } ``` -## Use `auth.protect()` to check if a user is authenticated - -`auth.protect()` can be used in a `page.tsx` file to protect any page in your application. - -In the following example, - -- the `auth.protect()` helper is used to check if a user visiting the `/dashboard` route is authenticated. -- If the user is not authenticated, they will be redirected to the sign-in route. -- If the user is authenticated, `auth.protect()` returns the user's `userId`, and they can view the `/dashboard` page. - -```tsx {{ filename: 'app/dashboard/page.tsx' }} -import { auth } from '@clerk/nextjs/server' - -export default async function Page() { - const { userId } = await auth.protect() - - return

Welcome, {userId}

-} -``` +## Use `auth()` to protect your app -## Use `auth()` to check if a user is authorized - -`auth()` returns the [`Auth`](/docs/references/nextjs/auth-object#auth-object) object, which includes the [`has()`](/docs/references/nextjs/auth-object#has) helper. - -You can protect certain parts of your application or even entire routes based on a user's authorization status by checking if the user has the required permissions or roles. Learn more about authorization checks in [the dedicated guide](/docs/organizations/verify-user-permissions). - -- Use `auth.protect()` if you want Clerk to return a `404` if the user does not have the role or permission. -- Use `has()` if you want more control over what your app does based on the authorization status instead of immediately returning a `404`. - - - - The following example uses `has()` to protect a pages content from unauthorized access. - - - If the user does not have the permission, `has()` will return `false`, causing the component to return `null`. - - If the user has the permission, `has()` will return `true`, allowing the component to render its children. - - ```tsx {{ filename: 'app/team-settings/page.tsx' }} - import { auth } from '@clerk/nextjs/server' - - export default async function Page() { - const { has } = await auth() - - // Check if the user is authorized - const canManage = has({ permission: 'org:team_settings:manage' }) - - // If has() returns false, the user does not have the correct permissions - // You can choose how your app responds. This example returns null. - if (!canManage) return null - - // If the user is both authenticated and authorized, move forward with your logic - return

Team Settings

- } - ``` -
- - - The following example uses `auth.protect()` to protect a Next.js Route Handler from unauthenticated and unauthorized access. - - - If the user is not authenticated, `auth.protect()` will redirect the user to the sign-in route. - - If the user is authenticated but is not authorized (as in, does not have the `org:team_settings:manage` permission), `auth.protect()` will throw a `404` error. - - If the user is both authenticated and authorized, `auth.protect()` will return the user's `userId`. - - ```tsx {{ filename: 'app/api/create-team/route.ts' }} - import { auth } from '@clerk/nextjs/server' - - export const POST = async () => { - // Check if the user is authorized - const { userId } = await auth.protect({ permission: 'org:team_settings:manage' }) - - // If the user is both authenticated and authorized, move forward with your logic - return users.createTeam(userId) - } - ``` - -
- -## Use `auth()` to check your current user's role - -In some cases, you need to check your user's current organization role before displaying data or allowing certain actions to be performed. - -Check the current user's role with the `orgRole` property of the `Auth` object returned by `auth()`, as shown in the following example: - -```tsx {{ filename: 'app/page.tsx' }} -import { auth } from '@clerk/nextjs/server' - -export default async function Page() { - const { orgRole } = await auth() - - return ( - <> -
Your current role is {orgRole}
- - ) -} -``` +You can protect certain parts of your application or even entire routes based on a user's authentication and/or authorization status. See detailed examples in [the dedicated guide.](/docs/organizations/verify-user-permissions)