diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c6be7d0c03..b75bc54b71 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,4 @@ * @clerk/docs + +# Help keep docs quickstart content in sync with Dashboard +docs/quickstarts/* @clerk/growth \ No newline at end of file diff --git a/docs/authentication/social-connections/slack.mdx b/docs/authentication/social-connections/slack.mdx index 7ae143a044..2e301137b7 100644 --- a/docs/authentication/social-connections/slack.mdx +++ b/docs/authentication/social-connections/slack.mdx @@ -1,39 +1,76 @@ --- title: Add Slack as a social connection -description: Learn how to set up social connection with Slack. +description: Learn how to allow users to sign up and sign in to your Clerk app with their Slack account using OAuth. --- -How to set up social connection with Slack + + - Use Slack to authenticate users with OAuth + -## Overview +Enabling OAuth with [Slack](https://api.slack.com/authentication) allows your users to sign up and sign in to your Clerk app with their Slack account. -Adding social connection with Slack to your app with Clerk is done in a few steps - you only need to set the **Client ID**, **Client Secret** and **Authorized redirect URL** in your instance settings. +## Configure for your development instance -> [!NOTE] -> Please note that Sign in with Slack doesn't support any additional OAuth scopes other than **openid**, **email**, **profile**, which are requested by default +For _development instances_, Clerk uses preconfigured shared OAuth credentials and redirect URIs—no other configuration is needed. -To make the development flow as smooth as possible, Clerk uses preconfigured shared OAuth credentials and redirect URIs for development instances - no other configuration is needed. +1. In the Clerk Dashboard, navigate to the [**SSO Connections**](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) page. +1. Select **Add connection** and select **For all users**. +1. In the **Choose provider** dropdown, select **Slack**. +1. Select **Add connection**. -For production instances, you will need to generate your own Client ID and Client secret using your Slack account. +## Configure for your production instance -> [!NOTE] -> The purpose of this guide is to help you create a Slack OAuth app - if you're looking for step-by-step instructions using Clerk to add social connection (OAuth) to your application, follow the [Social connection (OAuth) guide](/docs/authentication/social-connections/oauth). +For _production instances_, you must provide custom credentials which involves generating your own **Client ID** and **Client Secret** using your Slack account. -## Before you start +To make the setup process easier, it's recommended to keep two browser tabs open: one for your [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) and one for your [Slack's API Platform](https://api.slack.com/). -- You need to create a Clerk Application in your [Clerk Dashboard](https://dashboard.clerk.com/). For more information, check out our [Set up your application guide](/docs/quickstarts/setup-clerk). -- You need to have a Slack account. To create one, [click here](https://slack.com/get-started#/createnew). + + ### Enable Slack as a social connection in Clerk -## Configuring Slack social connection + 1. In the Clerk Dashboard, navigate to the [**SSO Connections**](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) page. + 1. Select **Add connection** and select **For all users**. + 1. In the **Choose provider** dropdown, select **Slack**. + 1. Ensure that both **Enable for sign-up and sign-in** and **Use custom credentials** are toggled on. + 1. Save the **Redirect URI** somewhere secure. Keep the modal and page open. -First, you need to create a new OAuth Slack app. On the main [Slack apps page](https://api.slack.com/apps), click on **Create new app**. On the modal that pops up, choose **From scratch,** enter your application name and choose a Slack workspace to associate with it. + ### Create a Slack app -![Creating a new application](/docs/images/authentication-providers/slack/creating-new-application.jpg) + 1. In the Slack API Platform, navigate to the [**Your Apps**](https://api.slack.com/apps) page and select **Create an App**. + 1. A modal will open. Depending on your app needs, select either **From a manifest** for **From scratch**. For more information on which to choose, refer to [Slack's doc on manifests](https://api.slack.com/reference/manifests). + 1. After following the respective steps for either option, you'll be redirected to the **App Credentials** page. Save the **Client ID** and **Client Secret** somewhere secure. Keep this page open. + 1. In the sidebar, navigate to the **OAuth & Permissions** page. + 1. Scroll down to the **Redirect URLs** section and paste the **Redirect URI** you saved from the Clerk Dashboard. Select **Add**, then select **Save URLs**. -Navigate to the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections). In the top navigation, select **Configure**. Then in the sidebar, select **SSO Connections**. Select the **Add connection** button, and select **For all users**. In the **Choose provider** dropdown, select **Slack**. Toggle on **Use custom credentials** and copy **Redirect URI**. Navigate to **OAuth & Permissions > Redirect URLs** and paste the value to add a new record. + ### Set the Client ID and Client Secret in your Clerk Dashboard -![Copying values from the Slack dashboard](/docs/images/authentication-providers/slack/copying-values-from-slack-dashboard.jpg) + 1. Navigate back to your Clerk Dashboard where the modal should still be open. Paste the **Client ID** and **Client Secret** values that you saved into the respective fields. + 1. Select **Add connection**. -Copy the **Client ID** and **Client secret** as shown in the above image from the Basic Information menu of your app. Go back to the Clerk Dashboard and paste them into the respective fields. + > [!NOTE] + > If the modal or page is not still open, navigate to the [**SSO Connections**](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) page in the Clerk Dashboard. Select the **Slack** connection. Under **Use custom credentials**, you can paste the **Client ID** and **Client Secret** into their respective fields. -Finally, select **Add connection** so that the settings are applied. Congratulations! Social connection with Slack is now configured for your instance. + ### Test your OAuth + + The simplest way to test your OAuth is to visit your Clerk app's [Account Portal](/docs/customization/account-portal/overview), which is available for all Clerk apps out-of-the-box. + + 1. In the Clerk Dashboard, navigate to the [**Account Portal**](https://dashboard.clerk.com/last-active?path=account-portal) page. + 1. Next to the **Sign-in** URL, select **Visit**. The URL should resemble: + + - **For development** – `https://your-domain.accounts.dev/sign-in` + - **For production** – `https://accounts.your-domain.com/sign-in` + + 1. Sign in with your Slack account. + diff --git a/docs/backend-requests/handling/js-backend-sdks.mdx b/docs/backend-requests/handling/js-backend-sdks.mdx new file mode 100644 index 0000000000..587430f4cf --- /dev/null +++ b/docs/backend-requests/handling/js-backend-sdks.mdx @@ -0,0 +1,89 @@ +--- +title: Handling requests with a JS Backend SDK +description: Learn how to handle authenticated requests with one of Clerk's JS Backend SDKs. +--- + +To handle authenticated requests, use one of the following JS Backend SDKs. + +## Clerk Express SDK + +The `clerkMiddleware()` function checks the request's cookies and headers for a session JWT. If the user has a valid session, the `clerkMiddleware()` function attaches the [properties](/docs/references/nextjs/auth-object#auth-object-properties) of the authenticated user to the request object. + +```js +import { clerkMiddleware } from '@clerk/express' + +const app = express() + +// Pass no parameters +app.use(clerkMiddleware()) + +// Pass options +app.use(clerkMiddleware(options)) +``` + +For more information on the Middleware functions and SDK features, see the [Express SDK](/docs/references/express/overview) page. + +## Clerk Fastify SDK + +The `clerkPlugin` checks the request's cookies and headers for a session JWT. If the user has a valid session, the `clerkPlugin` attaches the [properties](/docs/references/nextjs/auth-object#auth-object-properties) of the authenticated user to the request object. + +```ts +import 'dotenv/config' +import Fastify from 'fastify' +import { clerkClient, clerkPlugin, getAuth } from '@clerk/fastify' + +const fastify = Fastify({ logger: true }) + +fastify.register(clerkPlugin) + +fastify.get('/', async (request, reply) => { + const { userId } = getAuth(request) + + // Protect the route from unauthenticated users + if (!userId) { + return reply.code(403).send({ error: 'Unauthorized request.' }) + } + + const user = userId ? await clerkClient.users.getUser(userId) : null + + return reply.send({ + message: 'User retrieved successfully.', + user, + }) +}) + +const start = async () => { + try { + await fastify.listen({ port: 8080 }) + } catch (error) { + fastify.log.error(error) + process.exit(1) + } +} + +start() +``` + +For more information on the Clerk plugin and SDK features, see the [Fastify SDK](/docs/quickstarts/fastify) page. + +## Clerk Backend SDK + +If you're not using Express or Fastify, use the `@clerk/backend` package to access `clerkClient`. + +```ts +import { createClerkClient } from '@clerk/backend' + +const clerkClient = createClerkClient({ + secretKey: process.env.CLERK_SECRET_KEY, + publishableKey: process.env.CLERK_PUBLISHABLE_KEY, +}) + +const { isSignedIn } = await clerkClient.authenticateRequest(req, { + jwtKey: process.env.CLERK_JWT_KEY, + authorizedParties: ['https://example.com'], +}) + +if (!isSignedIn) { + return Response.json({ status: 401 }) +} +``` diff --git a/docs/integrations/webhooks/debug-your-webhooks.mdx b/docs/integrations/webhooks/debug-your-webhooks.mdx index 845e48f624..ac09292051 100644 --- a/docs/integrations/webhooks/debug-your-webhooks.mdx +++ b/docs/integrations/webhooks/debug-your-webhooks.mdx @@ -21,40 +21,21 @@ Incoming webhook events will never be signed in -- they are coming from a source The following example shows the recommended Middleware configuration for your webhook routes. - - ```tsx {{ filename: 'middleware.tsx' }} - import { clerkMiddleware } from '@clerk/nextjs/server' - - // Make sure that the `/api/webhooks/(.*)` route is not protected here - export default clerkMiddleware() - - export const config = { - matcher: [ - // Skip Next.js internals and all static files, unless found in search params - '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', - // Always run for API routes - '/(api|trpc)(.*)', - ], - } - ``` - - ```tsx {{ filename: 'middleware.tsx', mark: [4] }} - import { authMiddleware } from '@clerk/nextjs/server' - - export default authMiddleware({ - ignoredRoutes: ['/api/webhooks(.*)'], - }) - - export const config = { - matcher: [ - // Skip Next.js internals and all static files, unless found in search params - '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', - // Always run for API routes - '/(api|trpc)(.*)', - ], - } - ``` - +```tsx {{ filename: 'middleware.tsx' }} +import { clerkMiddleware } from '@clerk/nextjs/server' + +// Make sure that the `/api/webhooks/(.*)` route is not protected here +export default clerkMiddleware() + +export const config = { + matcher: [ + // Skip Next.js internals and all static files, unless found in search params + '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', + // Always run for API routes + '/(api|trpc)(.*)', + ], +} +``` ## Test the Route Handler or API Route diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 812f03f4b0..1d31ab9fb2 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -74,40 +74,21 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec The following example shows the recommended Middleware configuration for webhook routes. - - ```tsx {{ filename: 'middleware.ts' }} - import { clerkMiddleware } from '@clerk/nextjs/server' - - // Make sure that the `/api/webhooks(.*)` route is not protected here - export default clerkMiddleware() - - export const config = { - matcher: [ - // Skip Next.js internals and all static files, unless found in search params - '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', - // Always run for API routes - '/(api|trpc)(.*)', - ], - } - ``` - - ```tsx {{ filename: 'middleware.ts', mark: [4] }} - import { authMiddleware } from '@clerk/nextjs/server' - - export default authMiddleware({ - ignoredRoutes: ['/api/webhooks(.*)'], - }) - - export const config = { - matcher: [ - // Skip Next.js internals and all static files, unless found in search params - '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', - // Always run for API routes - '/(api|trpc)(.*)', - ], - } - ``` - + ```ts {{ filename: 'middleware.ts' }} + import { clerkMiddleware } from '@clerk/nextjs/server' + + // Make sure that the `/api/webhooks(.*)` route is not protected here + export default clerkMiddleware() + + export const config = { + matcher: [ + // Skip Next.js internals and all static files, unless found in search params + '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', + // Always run for API routes + '/(api|trpc)(.*)', + ], + } + ``` ### Install `svix` diff --git a/docs/manifest.json b/docs/manifest.json index e3c7551d3a..8bbb9087a2 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -702,8 +702,8 @@ "items": [ [ { - "title": "Node.js & Express", - "href": "/docs/backend-requests/handling/nodejs" + "title": "JS Backend SDKs", + "href": "/docs/backend-requests/handling/js-backend-sdks" }, { "title": "Go", @@ -718,6 +718,10 @@ { "title": "Manual JWT Verification", "href": "/docs/backend-requests/handling/manual-jwt" + }, + { + "title": "Node.js (Deprecated)", + "href": "/docs/backend-requests/handling/nodejs" } ] ] @@ -1729,22 +1733,6 @@ ] ] }, - { - "title": "Deprecated", - "items": [ - [ - { - "title": "`authMiddleware()`", - "wrap": false, - "href": "/docs/references/nextjs/auth-middleware" - }, - { - "title": "Use Clerk with Next.js 12 and older", - "href": "/docs/references/nextjs/usage-with-older-versions" - } - ] - ] - }, { "title": "Demo Repositories", "items": [ diff --git a/docs/organizations/verify-user-permissions.mdx b/docs/organizations/verify-user-permissions.mdx index e0ddc60848..87de1b1c46 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) { + 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/quickstarts/astro.mdx b/docs/quickstarts/astro.mdx index 19a8444525..8b7f2de575 100644 --- a/docs/quickstarts/astro.mdx +++ b/docs/quickstarts/astro.mdx @@ -25,21 +25,19 @@ description: Add authentication and user management to your Astro app with Clerk ]} > - Install `@clerk/astro` - - Set up your environment keys to test your app locally - - Add TypeScript declarations - - Add the `clerk()` integration to your application - - Use Clerk middleware to implement route-specific authentication + - Set your Clerk API keys + - Add `clerkMiddleware()` - Create a header with Clerk components for users to sign in and out -Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of components, hooks, and stores that make it easy to build authentication and user management features in your Astro app. - ### Install `@clerk/astro` - Add Clerk's Astro SDK to your project: + Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of components, hooks, and stores that make it easy to build authentication and user management features in your Astro app. + + Add the SDK to your project by running the following command: - + ```bash {{ filename: 'terminal' }} npm install @clerk/astro ``` @@ -53,15 +51,14 @@ Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of component ``` - ### Set environment variables + ### Set your Clerk API keys - Add the following keys to your `.env.local` file. These keys can always be retrieved from the [API Keys](https://dashboard.clerk.com/last-active?path=api-keys) page of your Clerk Dashboard. + Add the following keys to your `.env.local` file. These keys can always be retrieved from the [**API Keys**](https://dashboard.clerk.com/last-active?path=api-keys) page of your Clerk Dashboard. - 1. Navigate to the Clerk Dashboard. - 1. In the navigation sidebar, select [API Keys](https://dashboard.clerk.com/last-active?path=api-keys). + 1. In the Clerk Dashboard, navigate to the [**API Keys**](https://dashboard.clerk.com/last-active?path=api-keys) page. 1. In the **Quick Copy** section, copy your Clerk publishable and secret key. 1. Paste your keys into your `.env.local` file. @@ -75,11 +72,11 @@ Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of component ### Update `astro.config.mjs` - To configure Clerk in your Astro application, you will need to update your `astro.config.mjs`. + To configure Clerk in your Astro app, you will need to update your `astro.config.mjs`. - Add the Clerk integration to the `integrations` list. - - Install an [SSR adapter](https://docs.astro.build/en/guides/server-side-rendering/#official-adapters). For this quickstart we chose the [`@astrojs/node`](https://docs.astro.build/en/guides/integrations-guide/node/) adapter. You can use any Node based adapter you wish. - - Set `output` to `server`. This is required when deploying to a host supporting SSR. + - Install an [SSR adapter](https://docs.astro.build/en/guides/server-side-rendering/#official-adapters). This quickstart uses the [`@astrojs/node`](https://docs.astro.build/en/guides/integrations-guide/node/) adapter. + - Set `output` to `server`. This is required when deploying to a host supporting SSR. ```ts {{ filename: 'astro.config.mjs', mark: [2, 3, [6, 8]] }} import { defineConfig } from 'astro/config' @@ -93,13 +90,14 @@ Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of component }) ``` - ### Add middleware to your application - - [`clerkMiddleware()`](/docs/references/astro/clerk-middleware) grants you access to user authentication state throughout your application, on any route or page. It also allows you to protect specific routes from unauthenticated users. To add `clerkMiddleware()` to your application, follow these steps: + ### Add `clerkMiddleware()` to your app - 1. Create a `middleware.ts` file inside your `src/` directory. - 1. In your `middleware.ts` file, export an `onRequest` constant and assign the result of the `clerkMiddleware` function to it. + [`clerkMiddleware()`](/docs/references/astro/clerk-middleware) grants you access to user authentication state throughout your app, on any route or page. It also allows you to protect specific routes from unauthenticated users. To add `clerkMiddleware()` to your app, follow these steps: + 1. Create a `middleware.ts` file. + - If you're using the `/src` directory, create `middleware.ts` in the `/src` directory. + - If you're not using the `/src` directory, create `middleware.ts` in the root directory alongside `.env.local`. + 1. In your `middleware.ts` file, export an `onRequest` constant and assign the result of the `clerkMiddleware()` function to it. ```tsx {{ filename: 'src/middleware.ts' }} import { clerkMiddleware } from '@clerk/astro/server' @@ -112,13 +110,22 @@ Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of component Update the `env.d.ts` file in your `src/` directory to add type definitions for the `locals` added by the middleware. ```ts {{ prettier: false, filename: 'src/env.d.ts', mark: [3] }} + // The line directly below will only be present if you've ran your app + // Don't worry about adding it manually + /// + /// /// ``` - ### Add components to your app + ### Add Clerk components to your app + + You can control which content signed-in and signed-out users can see with Clerk's [prebuilt control components](/docs/components/overview#what-are-control-components). Create a header using the following components: - Clerk offers components that allow you to protect your pages. These components are used to control the visibility of your pages based on the user's authentication state. + - [``](/docs/components/control/signed-in): Children of this component can only be seen while **signed in**. + - [``](/docs/components/control/signed-out): Children of this component can only be seen while **signed out**. + - [``](/docs/components/user/user-button): Shows the signed-in user's avatar. Selecting it opens a dropdown menu with account management options. + - [``](/docs/components/unstyled/sign-in-button): An unstyled component that links to the sign-in page. In this example, since no props or [environment variables](/docs/deployments/clerk-environment-variables) are set for the sign-in URL, this component links to the [Account Portal sign-in page.](/docs/customization/account-portal/overview#sign-in) ```astro {{ filename: 'src/layouts/SiteLayout.astro' }} --- @@ -151,6 +158,8 @@ Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of component ``` + Then, use the layout on your homepage: + ```astro {{ filename: 'src/pages/index.astro' }} --- import SiteLayout from '../layouts/SiteLayout.astro' @@ -191,7 +200,7 @@ Clerk's [Astro SDK](/docs/references/astro/overview) provides a set of component --- - [Read session and user data](/docs/references/astro/read-session-data) - - Learn how to use Clerk's stores and helpers to access the active session and user data in your Astro application. + - Learn how to use Clerk's stores and helpers to access the active session and user data in your Astro app. --- diff --git a/docs/quickstarts/expo.mdx b/docs/quickstarts/expo.mdx index 6219aedf61..a4f5e03640 100644 --- a/docs/quickstarts/expo.mdx +++ b/docs/quickstarts/expo.mdx @@ -20,20 +20,20 @@ description: Add authentication and user management to your Expo app with Clerk. } ]} > - - Create an Expo application + - Create an Expo app - Install `@clerk/expo` - - Set up your environment keys to test your app locally - - Add `` to your application + - Set your Clerk API keys + - Add `` - Protect specific pages with authentication - - Use Clerk hooks to enable users to sign in and out of your application + - Use Clerk hooks to enable users to sign in and out - ### Create an Expo application + ### Create an Expo app - To get started using Clerk with Expo, create a new Expo project and install the necessary dependencies. See the [Expo documentation](https://docs.expo.dev/tutorial/create-your-first-app/) for more information. + Create a new Expo project and install the necessary dependencies by running the following command: - + ```bash filename="terminal" npx create-expo-app application-name --template blank && cd application-name npx expo install react-dom react-native-web @expo/metro-runtime @@ -53,9 +53,11 @@ description: Add authentication and user management to your Expo app with Clerk. ### Install `@clerk/clerk-expo` - Add Clerk's [Expo SDK](/docs/references/expo/overview) to your project: + Clerk's [Expo SDK](/docs/references/expo/overview) gives you access to prebuilt components, hooks, and helpers to make user authentication easier. + + Add the SDK to your project by running the following command: - + ```bash filename="terminal" npm install @clerk/clerk-expo ``` @@ -69,17 +71,16 @@ description: Add authentication and user management to your Expo app with Clerk. ``` - ### Set your environment variables + ### Set your Clerk API keys - Add the following keys to your `.env` file. These keys can always be retrieved from your project's [API Keys](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard. + Add your Clerk publishable key to your `.env` file. It can always be retrieved from the [**API Keys**](https://dashboard.clerk.com/last-active?path=api-keys) page of your Clerk Dashboard. - 1. Navigate to the Clerk Dashboard. - 1. In the navigation sidebar, select [API Keys](https://dashboard.clerk.com/last-active?path=api-keys). - 1. In the **Quick Copy** section, copy your Clerk publishable and secret key. - 1. Paste your keys into your `.env` file. + 1. In the Clerk Dashboard, navigate to the [**API Keys**](https://dashboard.clerk.com/last-active?path=api-keys) page. + 1. In the **Quick Copy** section, copy your Clerk publishable key. + 1. Paste your key into your `.env` file. The final result should resemble the following: @@ -90,9 +91,11 @@ description: Add authentication and user management to your Expo app with Clerk. ### Add `` to your root layout - All Clerk hooks and components must be children of [``](/docs/components/clerk-provider), which provides active session and user context. Clerk also provides ``, which will not render child content unless the Clerk API has loaded. + The [``](/docs/components/clerk-provider) component wraps your app to provide active session and user context to Clerk's hooks and other components. You must pass your publishable key as a prop to the `` component. - To grant your entire app access to Clerk session data and ensure nothing renders until Clerk loads, add both components to your root layout as shown in the following example: + Clerk also provides [``](/docs/components/control/clerk-loaded), which won't render its children until the Clerk API has loaded. + + Add both components to your root layout as shown in the following example: ```tsx filename="app/_layout.tsx" import { ClerkProvider, ClerkLoaded } from '@clerk/clerk-expo' @@ -102,9 +105,7 @@ description: Add authentication and user management to your Expo app with Clerk. const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY! if (!publishableKey) { - throw new Error( - 'Missing Publishable Key. Please set EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env', - ) + throw new Error('Add EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY to your .env file') } return ( @@ -117,13 +118,13 @@ description: Add authentication and user management to your Expo app with Clerk. } ``` - ### Configure the Token Cache with Expo + ### Configure the token cache - The token cache is used to persist the active user's session token. Clerk stores this token in memory by default, however it is recommended to use a token cache for production applications. + The token cache is used to persist the active user's session token. Clerk stores this token in memory by default. However, it is recommended to use a token cache for production apps. Install `expo-secure-store`, which you'll use as your token cache: - + ```bash {{ filename: 'terminal' }} npm install expo-secure-store ``` @@ -150,7 +151,7 @@ description: Add authentication and user management to your Expo app with Clerk. The following example demonstrates an Expo layout that defines a custom token cache to securely store the user's session JWT using `expo-secure-store`: > [!IMPORTANT] - > Data stored with `expo-secure-store` may not persist between new builds of your application unless you [clear the app data of the previously installed build](https://github.com/expo/expo/issues/23426#issuecomment-1642246470). + > Data stored with `expo-secure-store` may not persist between new builds of your app unless you [clear the app data of the previously installed build](https://github.com/expo/expo/issues/23426#issuecomment-1642246470). ```tsx {{ filename: 'app/_layout.tsx' }} import * as SecureStore from 'expo-secure-store' @@ -186,9 +187,7 @@ description: Add authentication and user management to your Expo app with Clerk. const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY! if (!publishableKey) { - throw new Error( - 'Missing Publishable Key. Please set EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env', - ) + throw new Error('Add EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env') } return ( @@ -204,9 +203,9 @@ description: Add authentication and user management to your Expo app with Clerk. > [!TIP] > When you sign a user out with [`signOut()`](/docs/references/react/use-auth#use-auth-returns), Clerk will remove the user's session JWT from the token cache. - ### Conditionally render content + ### Protect your pages - You can control which content signed-in and signed-out users can see with Clerk's [control components](/docs/components/overview#what-are-control-components). For this quickstart, you'll use: + You can control which content signed-in and signed-out users can see with Clerk's [prebuilt control components](/docs/components/overview#what-are-control-components). For this quickstart, you'll use: - [``](/docs/components/control/signed-in): Children of this component can only be seen while **signed in**. - [``](/docs/components/control/signed-out): Children of this component can only be seen while **signed out**. @@ -251,8 +250,7 @@ description: Add authentication and user management to your Expo app with Clerk. ### Add `sign-up` and `sign-in` pages - Clerk currently only supports control components for Expo native. UI components are only available for Expo web. - Instead, you must build [custom flows](/docs/custom-flows/overview) using Clerk's API. The following sections demonstrate how to build custom email/password sign-up and sign-in flows. If you want to use different authentication methods, such as passwordless or OAuth, see the dedicated custom flow guides. + Clerk currently only supports control components for Expo native. UI components are only available for Expo web. Instead, you must build [custom flows](/docs/custom-flows/overview) using Clerk's API. The following sections demonstrate how to build [custom email/password sign-up and sign-in flows](/docs/custom-flows/email-password). If you want to use different authentication methods, such as passwordless or OAuth, see the dedicated custom flow guides. First, protect your `auth` routes in the `layout`. Create a new route group `(auth)` with a `_layout.tsx` file. This layout will redirect users to the home page if they're already signed in: @@ -271,7 +269,7 @@ description: Add authentication and user management to your Expo app with Clerk. } ``` - #### `Sign-up page` + #### Sign-up page The following example creates a sign-up page that allows users to sign up using email address and password, and sends an email verification code to confirm their email address. @@ -364,7 +362,7 @@ description: Add authentication and user management to your Expo app with Clerk. } ``` - #### `Sign-in page` + #### Sign-in page The following example creates a sign-in page that allows users to sign in using email address and password, or navigate to the sign-up page. @@ -456,14 +454,12 @@ description: Add authentication and user management to your Expo app with Clerk. ## Enable OTA updates -Though not required, it is recommended to implement over-the-air (OTA) updates in your Expo application. This enables you to easily roll out Clerk's feature updates and security patches as they're released without having to resubmit your application to mobile marketplaces. +Though not required, it is recommended to implement over-the-air (OTA) updates in your Expo app. This enables you to easily roll out Clerk's feature updates and security patches as they're released without having to resubmit your app to mobile marketplaces. See the [`expo-updates`](https://docs.expo.dev/versions/latest/sdk/updates) library to learn how to get started. ## Next steps -See the following guides to take the next steps toward fleshing out your Expo app. - - [OAuth with Expo](/docs/custom-flows/oauth-connections) - Learn more how to build a custom OAuth flow with Expo. diff --git a/docs/quickstarts/javascript.mdx b/docs/quickstarts/javascript.mdx index 6e4c4385b1..e38f1e3770 100644 --- a/docs/quickstarts/javascript.mdx +++ b/docs/quickstarts/javascript.mdx @@ -20,29 +20,29 @@ description: Add authentication and user management to your JavaScript app with }, ]} > - - Add the ClerkJS SDK to your JavaScript application + - Add the JavaScript SDK to your JavaScript app - Use Clerk components to allow users to sign in or out -To add the [ClerkJS SDK](/docs/references/javascript/overview) to your JavaScript application, you have two options: +To add the [JavaScript SDK](/docs/references/javascript/overview) to your JavaScript app, you have two options: -1. Install the package using a package manager, like `npm`, `yarn`, or `pnpm`. +1. Install the package using a package manager, like `npm`. 1. Use the ` ``` - In the `