diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7b1f6158d2..398002e105 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -439,18 +439,18 @@ console.log('ignored')
### ``
-The `` component is used to number a set of instructions with an outcome. It uses the highest heading available in the component to denote each step. Can be used with `h3` headings.
+The `` component is used to number a set of instructions with an outcome. It uses the highest heading available in the component to denote each step. Can be used with `h2` and `h3` headings.
```mdx
-### Step 1
+## Step 1
Do these actions to complete Step 1.
-### Another step
+## Another step
-#### A heading inside a step
+### A heading inside a step
Do these actions to complete Step 2.
@@ -575,7 +575,7 @@ The `` component is used at the beginning of a tutorial-type con
- Install `@clerk/nextjs`
- Set up your environment keys to test your app locally
-- Add `` to your application
+- Add `` to your application
- Use Clerk middleware to implement route-specific authentication
- Create a header with Clerk components for users to sign in and out
diff --git a/docs/_partials/clerk-provider.mdx b/docs/_partials/clerk-provider.mdx
new file mode 100644
index 0000000000..d64638d8f5
--- /dev/null
+++ b/docs/_partials/clerk-provider.mdx
@@ -0,0 +1 @@
+The [``](/docs/components/clerk-provider) component provides session and user context to Clerk's hooks and components. It's recommended to wrap your entire app at the entry point with `` to make authentication globally accessible. See the [reference docs](/docs/components/clerk-provider) for other configuration options.
diff --git a/docs/_partials/expo/oauth-custom-flow.mdx b/docs/_partials/expo/oauth-custom-flow.mdx
new file mode 100644
index 0000000000..81f09bee6c
--- /dev/null
+++ b/docs/_partials/expo/oauth-custom-flow.mdx
@@ -0,0 +1,58 @@
+The following example demonstrates how to create a custom OAuth sign-in flow for [Google accounts](/docs/authentication/social-connections/google).
+
+```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
+import React from 'react'
+import * as WebBrowser from 'expo-web-browser'
+import { Text, View, Button } from 'react-native'
+import { Link } from 'expo-router'
+import { useOAuth } from '@clerk/clerk-expo'
+import * as Linking from 'expo-linking'
+
+export const useWarmUpBrowser = () => {
+ React.useEffect(() => {
+ // Warm up the android browser to improve UX
+ // https://docs.expo.dev/guides/authentication/#improving-user-experience
+ void WebBrowser.warmUpAsync()
+ return () => {
+ void WebBrowser.coolDownAsync()
+ }
+ }, [])
+}
+
+WebBrowser.maybeCompleteAuthSession()
+
+export default function Page() {
+ useWarmUpBrowser()
+
+ const { startOAuthFlow } = useOAuth({ strategy: 'oauth_google' })
+
+ const onPress = React.useCallback(async () => {
+ try {
+ const { createdSessionId, signIn, signUp, setActive } = await startOAuthFlow({
+ redirectUrl: Linking.createURL('/dashboard', { scheme: 'myapp' }),
+ })
+
+ // If sign in was successful, set the active session
+ if (createdSessionId) {
+ setActive!({ session: createdSessionId })
+ } else {
+ // Use signIn or signUp returned from startOAuthFlow
+ // for next steps, such as MFA
+ }
+ } catch (err) {
+ // See https://clerk.com/docs/custom-flows/error-handling
+ // for more info on error handling
+ console.error(JSON.stringify(err, null, 2))
+ }
+ }, [])
+
+ return (
+
+
+ Home
+
+
+
+ )
+}
+```
diff --git a/docs/_partials/react-hooks.mdx b/docs/_partials/react-hooks.mdx
new file mode 100644
index 0000000000..594ffdf1e8
--- /dev/null
+++ b/docs/_partials/react-hooks.mdx
@@ -0,0 +1,9 @@
+- [`useUser()`](/docs/references/react/use-user){{ target: '_blank' }}
+- [`useClerk()`](/docs/references/react/use-clerk){{ target: '_blank' }}
+- [`useAuth()`](/docs/references/react/use-auth){{ target: '_blank' }}
+- [`useSignIn()`](/docs/references/react/use-sign-in){{ target: '_blank' }}
+- [`useSignUp()`](/docs/references/react/use-sign-up){{ target: '_blank' }}
+- [`useSession()`](/docs/references/react/use-session){{ target: '_blank' }}
+- [`useSessionList()`](/docs/references/react/use-session-list){{ target: '_blank' }}
+- [`useOrganization()`](/docs/references/react/use-organization){{ target: '_blank' }}
+- [`useOrganizationList()`](/docs/references/react/use-organization-list){{ target: '_blank' }}
diff --git a/docs/advanced-usage/satellite-domains.mdx b/docs/advanced-usage/satellite-domains.mdx
index 9a22e430bf..5ffb193f48 100644
--- a/docs/advanced-usage/satellite-domains.mdx
+++ b/docs/advanced-usage/satellite-domains.mdx
@@ -115,7 +115,7 @@ To access authentication state from a satellite domain, users will be transparen
# CLERK_SIGN_UP_URL=http://localhost:3000/sign-up
```
- - You will also need to add the `allowedRedirectOrigins` property to `` on your _primary domain app_ to ensure that the redirect back from primary to satellite domain works correctly. For example:
+ - You will also need to add the `allowedRedirectOrigins` property to `` on your _primary domain app_ to ensure that the redirect back from primary to satellite domain works correctly. For example:
```tsx {{ filename: 'app/layout.tsx' }}
diff --git a/docs/authentication/configuration/sign-up-sign-in-options.mdx b/docs/authentication/configuration/sign-up-sign-in-options.mdx
index 6e4865727a..4184b85cfe 100644
--- a/docs/authentication/configuration/sign-up-sign-in-options.mdx
+++ b/docs/authentication/configuration/sign-up-sign-in-options.mdx
@@ -17,7 +17,7 @@ Identifiers are how your application recognizes an individual user. There are th
In the application configuration screen, you can select multiple identifiers, but at least one is required.
-**Email address** is the most common primary identifier. During the sign-up process, a user must supply and verify their email address. They must keep an email address on their account at all times. However, the email address that was used for registration can be later changed from the user's profile page.
+**Email address** is the most common primary identifier. When it is the only enabled identifier, users are required to supply an email address during sign-up and keep one on their account at all times. The email address that was supplied during sign-up can be later changed from the user's profile page.
When **phone number** is selected as the identifier, a user can sign up with their phone number and receive a code via SMS to verify it. SMS functionality is restricted to phone numbers from countries enabled on your [SMS allowlist](#sms-allowlist).
@@ -162,12 +162,12 @@ To enable social connections:
## Web3 authentication
-Clerk provides [Web3 authentication](/docs/users/web3) with either MetaMask or Coinbase Wallet. As part of validating the accuracy of the returned Web3 account address, Clerk handles the signing of a message and verifying the signature. Because sign-in with Web3 uses the same abstraction as our other authentication factors, like passwords or email links, other Clerk features like multi-factor authentication and profile enrichment work for Web3 users out-of-the-box.
+Clerk provides [Web3 authentication](/docs/users/web3) with either MetaMask, Coinbase Wallet or OKX Wallet. As part of validating the accuracy of the returned Web3 account address, Clerk handles the signing of a message and verifying the signature. Because sign-in with Web3 uses the same abstraction as our other authentication factors, like passwords or email links, other Clerk features like multi-factor authentication and profile enrichment work for Web3 users out-of-the-box.
To enable Web3 authentication:
1. In the Clerk Dashboard, navigate to the [**Web3**](https://dashboard.clerk.com/last-active?path=user-authentication/web3) page.
-1. Toggle on the Web3 provider. Currently, Clerk supports MetaMask and Coinbase Wallet.
+1. Enable your preferred Web3 provider.
## Multi-factor authentication
diff --git a/docs/authentication/enterprise-connections/easie/microsoft.mdx b/docs/authentication/enterprise-connections/easie/microsoft.mdx
index 026abb0cf8..f0ac052697 100644
--- a/docs/authentication/enterprise-connections/easie/microsoft.mdx
+++ b/docs/authentication/enterprise-connections/easie/microsoft.mdx
@@ -74,7 +74,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
[nOAuth](https://www.descope.com/blog/post/noauth) is an exploit in Microsoft Entra ID OAuth apps that can lead to account takeovers via email address spoofing. Clerk mitigates this risk by enforcing stricter checks on verified email addresses.
- For further security, Microsoft offers an optional `xms_edov` claim, which provides additional context to determine whether the returned email is verified.
+ For further security, Microsoft offers an optional `xms_edov` [claim](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference), which provides additional context to determine whether the returned email is verified.
This claim is mandatory for applications backing EASIE connections. To enable it, you must:
@@ -83,8 +83,6 @@ To make the setup process easier, it's recommended to keep two browser tabs open
1. Select **Add optional claim**.
1. For the **Token type**, select **ID**. Then, in the table that opens, enable the `email` and `xms_pdl` claims.
1. At the bottom of the modal, select **Add**. A new modal will prompt you to turn on the Microsoft Graph email permission. Enable it, then select **Add** to complete the form.
- > [!NOTE]
- > At the time of writing, the `xms_edov` claim is still in preview and may not be available for all apps. We'll choose another claim and rename it in the manifest later.
1. Repeat the previous steps for **Token type**, but select **Access** instead of **ID**. The **Optional claims** list should now show two claims for `email` and two for `xms_pdl`: one each for **ID** and **Access**.
1. In the sidebar, go to **Manifest**.
1. In the text editor, search for `"acceptMappedClaims"` and set its value from `null` to `true`.
diff --git a/docs/authentication/enterprise-connections/oidc/custom-provider.mdx b/docs/authentication/enterprise-connections/oidc/custom-provider.mdx
new file mode 100644
index 0000000000..ffe342ec81
--- /dev/null
+++ b/docs/authentication/enterprise-connections/oidc/custom-provider.mdx
@@ -0,0 +1,88 @@
+---
+title: Add a custom OpenID Connect (OIDC) Provider as an enterprise connection
+description: Learn how to integrate a custom OIDC provider with Clerk for Enterprise SSO.
+---
+
+
+ - Add a custom OIDC provider to authenticate users with Enterprise SSO
+
+
+This guide explains how to use a custom [OpenID Connect (OIDC)](https://openid.net/developers/how-connect-works) provider to authenticate users via Enterprise SSO.
+
+To make the setup process easier, it's recommended to keep two browser tabs open: one for the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) and one for your Identity Provider (IdP).
+
+
+ ## Set up an enterprise connection in Clerk
+
+ 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 specific domains**.
+ 1. Under **Third party**, select **OpenID Connect (OIDC)**.
+ 1. Add the **Name** of the connection.
+ 1. Add the **Key** of the provider. This is the provider's unique identifier (cannot be changed after creation).
+ 1. Add the **Specific Domain** that you want to allow this connection for. This is the domain of the users you want to allow to sign in to your app.
+ 1. Select **Add connection**. You will be redirected to the connection's configuration page. Keep this page open.
+
+ ## Configure your IdP
+
+ 1. If necessary, create a new application in your IdP.
+ 1. In the connection's configuration page of the Clerk Dashboard, copy the **Authorized redirect URI**.
+ 1. Add the value to your IdP's whitelisted URLs.
+ 1. Find your application's **Discovery Endpoint**, **Client ID**, and **Client Secret** and copy them.
+
+ ## Set the Discovery Endpoint, Client ID, and Client Secret in Clerk
+
+ 1. In your IdP settings, copy your application's **Discovery Endpoint**, **Client ID**, and **Client Secret**.
+ 1. In the connection's configuration page in the Clerk Dashboard, paste these values in their respective fields.
+ 1. Under **Scopes**, add the minimum required scopes based on the IdP's documentation if needed. Common OIDC scopes include `openid`, `email`, and `profile`.
+ 1. Select **Save**.
+
+ > [!NOTE]
+ > Most IdPs provide a **Discovery Endpoint** to retrieve metadata about an OIDC provider. If your IdP doesn't offer this endpoint or if you need greater control over the setup process, in the connection's configuration page in the Clerk Dashboard, find the **Identity Provider Configuration** section and select **Use Manual Configuration** to manually configure the connection.
+
+ ## Configure attribute mapping (optional)
+
+ Clerk expects the claims returned by your IdP to follow the [OIDC Standard](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). If your provider returns claims in a non-standard format, use the **Attribute Mapping** section on the connection's configuration page to adjust the mapping of Clerk's user properties to match the IdP's claim attributes.
+
+ > [!WARNING]
+ > OIDC Enterprise connections require the [`email_verified`](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims:~:text=Section%C2%A05.7.-,email_verified,-boolean) claim to verify email ownership. However, some IdPs, such as Microsoft Azure Active Directory, might not return this claim or use a non-standard format.
+ >
+ > If the IdP doesn't return this claim, you can leave the **Email address verified** field blank and set the **Default value** to **True**. This should only be done if you fully trust the IdP, as it can expose your app to [OAuth attacks](https://www.descope.com/blog/post/noauth).
+
+ ## Allow additional identifiers (optional)
+
+ User profile information is sourced from the IdP. To allow users to add new identifiers (e.g., email address or phone number) to their profiles:
+
+ 1. In the connection's configuration page of the Clerk Dashboard, navigate to the **Advanced** tab.
+ 1. Enable **Allow additional identifiers**.
+ 1. Select **Save**.
+
+ ## Enable the connection for Clerk
+
+ To make the connection available for your users to authenticate with:
+
+ 1. Navigate back to the Clerk Dashboard where you should still have the connection's configuration page open. If not, navigate to the [**SSO connections**](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) page and select the connection.
+ 1. At the top of the page, toggle on **Enable connection** and select **Save**.
+
+ ## Test your connection
+
+ The simplest way to test your enterprise connection 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 IdP account.
+
diff --git a/docs/authentication/enterprise-connections/overview.mdx b/docs/authentication/enterprise-connections/overview.mdx
index a46326a5ab..db77f71d6a 100644
--- a/docs/authentication/enterprise-connections/overview.mdx
+++ b/docs/authentication/enterprise-connections/overview.mdx
@@ -1,15 +1,15 @@
---
-title: Enterprise SSO
+title: Enterprise Single Sign-On (SSO)
description: Clerk provides Enterprise SSO to authenticate users via federated Identity Providers such such as Azure AD, Okta, Google Workspace and more.
---
-With Enterprise SSO, users can sign in seamlessly using their Identity Provider's (IdP) credentials and have their user data synchronized with Clerk. You can learn more about the process in the guides on [authentication flows](/docs/authentication/enterprise-connections/authentication-flows) and [account linking](/docs/authentication/enterprise-connections/account-linking).
+Enterprise Single Sign-On (SSO) allows users to sign in seamlessly using their Identity Provider (IdP) credentials (e.g.,Azure AD, Okta, or Google Workspace) and have their user data synchronized with Clerk. Clerk supports multiple protocols for implementing Enterprise SSO, including SAML and OIDC. Learn more about the process in the guides on [authentication flows](/docs/authentication/enterprise-connections/authentication-flows) and [account linking](/docs/authentication/enterprise-connections/account-linking).
## SAML
Clerk supports Enterprise SSO via the SAML protocol, enabling you to create authentication strategies for an IdP. The following IdPs are supported: [Microsoft Azure AD](/docs/authentication/enterprise-connections/saml/azure), [Google Workspace](/docs/authentication/enterprise-connections/saml/google), and [Okta Workforce](/docs/authentication/enterprise-connections/saml/okta). However, you can also [integrate with any other IdP](/docs/authentication/enterprise-connections/saml/custom-provider) that supports the SAML protocol.
-### Allow subdomains
+#### Allow subdomains
Authenticating via SAML SSO requires the user's email address domain to match the exact domain the SAML connection has been configured with. By default, subdomains are not supported. For example, a user with the email address `john@sales.example.com` wouldn't be able to use a SAML connection with the `example.com` domain to authenticate.
@@ -24,26 +24,30 @@ To configure subdomains for a SAML connection:
> [!NOTE]
> To enable the **Allow subdomains** option, your SAML connection domain must be an [eTLD+1](https://developer.mozilla.org/en-US/docs/Glossary/eTLD).
-## EASIE
+## OIDC
+
+Clerk supports Enterprise SSO via the OpenID Connect (OIDC) protocol, either through [EASIE](#easie) or by [integrating with any OIDC-compatible provider](/docs/authentication/enterprise-connections/oidc/custom-provider).
+
+### EASIE
[EASIE](https://easie.dev) SSO is a way for applications to provide enterprise-grade SSO through a multi-tenant OpenID provider. It is designed to be an easier alternative to SAML SSO.
The following IdPs are supported: Google Workspace and Microsoft Entra ID. For _development instances_, Clerk uses preconfigured shared credentials and redirect URIs—no other configuration is needed. For _production instances_, you must provide custom credentials. Follow the steps outlined in the guides to complete the setup:
-- [Google](docs/authentication/social-connections/google)
-- [Microsoft](docs/authentication/social-connections/azure)
+- [Google](/docs/authentication/social-connections/google)
+- [Microsoft](/docs/authentication/social-connections/microsoft)
-### Automatic deprovisioning
+#### Automatic deprovisioning
Clerk prevents users linked to deprovisioned accounts in the OpenID provider from accessing the app.
Within 10 minutes of a user being removed from the OpenID provider (e.g. [suspendeded](https://support.google.com/a/answer/33312?hl=en) or [deleted](https://support.google.com/a/answer/33314?hl=en) via Google Workspace, or [deleted](https://learn.microsoft.com/en-us/entra/fundamentals/how-to-create-delete-users#delete-a-user) via Microsoft Entra), Clerk will recognize that the user has been deprovisioned and will revoke that user's existing sessions.
-It is ultimately the app's responsibility to handle this unauthenticated state and display something appropriate to the user. For example, Next.js apps using [`auth.protect()`](docs/references/nextjs/auth#auth-protect) will automatically redirect the user to the sign-in page.
+It is ultimately the app's responsibility to handle this unauthenticated state and display something appropriate to the user. For example, Next.js apps using [`auth.protect()`](/docs/references/nextjs/auth#auth-protect) will automatically redirect the user to the sign-in page.
-## SAML vs. EASIE
+### SAML vs. EASIE
-The primary security difference between EASIE SSO and SAML SSO is that EASIE depends on a multi-tenant identity provider, while SAML depends on a single-tenant identity provider. Relying on a multi-tenant provider **increases** the risk that a user from one tenant will mistakenly be granted access to the resources of another tenant. While Clerk implements [measures to address this risk](https://easie.dev/#mitigating-tenant-crossover-vulnerabilities), apps that require single-tenant IdPs should opt for SAML.
+The primary security difference between EASIE SSO and SAML SSO is that EASIE depends on a multi-tenant identity provider, while SAML depends on a single-tenant identity provider. Relying on a multi-tenant provider **increases** the risk that a user from one tenant will mistakenly be granted access to the resources of another tenant. While Clerk implements [measures to address this risk](https://easie.dev/#mitigating-tenant-crossover-vulnerabilities:~:text=4.%20Mitigating%20tenant%20crossover%20vulnerabilities), apps that require single-tenant IdPs should opt for SAML.
For more information, see the [EASIE docs](https://easie.dev#security).
@@ -74,7 +78,3 @@ Yes, for SAML only. Clerk supports both Service Provider-initiated (SP-initiated
For development instances, Enterprise connections are always free but limited to a maximum of 25.
Production instances require the Pro plan and the Enhanced Authentication Add-on. Please see [pricing](/pricing){{ target: '_blank' }} for more information.
-
-### Can I get a bulk discount?
-
-Yes, [contact support](/contact/support){{ target: '_blank' }} to work out a custom plan.
diff --git a/docs/authentication/enterprise-connections/saml/azure.mdx b/docs/authentication/enterprise-connections/saml/azure.mdx
index 87a7039fc4..67a08b2cbd 100644
--- a/docs/authentication/enterprise-connections/saml/azure.mdx
+++ b/docs/authentication/enterprise-connections/saml/azure.mdx
@@ -25,7 +25,7 @@ Enabling single sign-on (SSO) with **Microsoft Azure Entra ID** (formerly [Activ
To make the setup process easier, it's recommended to keep two browser tabs open: one for the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) and one for your [Microsoft Azure portal](https://portal.azure.com).
- ### Set up an enterprise connection in Clerk
+ ## Set up an enterprise connection in Clerk
To create a SAML connection in Clerk:
@@ -38,7 +38,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
1. Find the **Service Provider Configuration** section.
1. Save the **Identifier (Entity ID)** and **Reply URL (Assertion Consumer Service URL)** values somewhere secure. You'll need these in the [Configure your service provider](#configure-your-service-provider) step. Leave this page open.
- ### Create a new enterprise app in Microsoft
+ ## Create a new enterprise app in Microsoft
To create a new enterprise app in Microsoft:
@@ -52,7 +52,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
- Ensure the option **Integrate any other application you don't find in the gallery (Non-gallery)** is selected.
- Select **Create**.
- ### Assign selected user or group in Microsoft
+ ## Assign selected user or group in Microsoft
Now that you have created the enterprise app, you need to assign users or groups to the app. For example, if you were part of the Clerk organization, you would have access to users and groups within the Clerk organization. In this case, you could assign individual users or entire groups to the enterprise app you just created.
@@ -63,14 +63,14 @@ To make the setup process easier, it's recommended to keep two browser tabs open
1. Select **Select** at the bottom of the page. You'll be redirected to the **Add Assignment** page.
1. Select **Assign** at the bottom of the page.
- ### Configure SSO in Microsoft
+ ## Configure SSO in Microsoft
After assigning the user or group to the enterprise app, you need to configure the SSO settings to enable SAML SSO.
1. In the navigation sidebar, open the **Manage** dropdown and select **Single sign-on**.
1. In the **Select a single sign-on method** section, select **SAML**.
- ### Configure your service provider
+ ## Configure your service provider
To configure Clerk as your service provider, add these two fields to your IdP's application:
@@ -84,7 +84,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
1. Paste the **Identifier (Entity ID)** and **Reply URL (Assertion Consumer Service URL)** values you saved earlier into their respective fields. These values will be saved automatically.
1. Select **Save** at the top of the panel. Close the panel.
- ### Configure your identity provider
+ ## Configure your identity provider
To configure Microsoft Entra ID as your identity provider, add the following fields to your app:
@@ -93,7 +93,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
1. Navigate back to the **Clerk Dashboard**. In the **Identity Provider Configuration** section, under **App Federation Metadata Url**, paste the **App Federation Metadata URL**.
1. Select **Fetch & save**.
- ### Map Microsoft claims to Clerk attributes
+ ## Map Microsoft claims to Clerk attributes
Mapping the claims in your IdP to the attributes in Clerk ensures that the data from your IdP is correctly mapped to the data in Clerk.
@@ -112,7 +112,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
1. Next to **Source attribute**, search for and select `user.userprincipalname` in the dropdown.
1. Select **Save** at the top of the page.
- ### Enable the connection for Clerk
+ ## Enable the connection for Clerk
To make the connection available for your users to authenticate with:
diff --git a/docs/authentication/enterprise-connections/saml/custom-provider.mdx b/docs/authentication/enterprise-connections/saml/custom-provider.mdx
index b717cfa88e..e0dbd4a0d6 100644
--- a/docs/authentication/enterprise-connections/saml/custom-provider.mdx
+++ b/docs/authentication/enterprise-connections/saml/custom-provider.mdx
@@ -22,10 +22,8 @@ description: Learn how to integrate an Identity Provider with Clerk using SAML S
Clerk supports Enterprise SSO via the SAML protocol, enabling you to create authentication strategies for an Identity Provider (IdP). Currently, Clerk offers direct integrations with [Microsoft Azure AD](/docs/authentication/enterprise-connections/saml/azure), [Google Workspace](/docs/authentication/enterprise-connections/saml/google), and [Okta Workforce](/docs/authentication/enterprise-connections/saml/okta) as IdPs. However, you can also integrate with any other IdP that supports the SAML protocol. This guide will show you how to set up a SAML connection with a custom IdP in Clerk.
-## Tutorial
-
- ### Set up an enterprise connection in Clerk
+ ## Set up an enterprise connection in Clerk
To create a SAML connection in Clerk:
@@ -36,23 +34,23 @@ Clerk supports Enterprise SSO via the SAML protocol, enabling you to create auth
1. Add the **Specific Domain** that you want to allow this connection for. This is the domain of the users you want to allow to sign in to your application.
1. Select **Add connection**. You will be redirected to the connection's configuration page.
- ### Create a new enterprise application in your IdP
+ ## Create a new enterprise application in your IdP
Create a new application in your IdP. In the next steps, you'll configure your IdP with the settings provided by your Service Provider (Clerk), and configure Clerk with the settings provided by your IdP. Keep both the IdP and Clerk Dashboard open.
- ### Configure your Identity Provider
+ ## Configure your Identity Provider
There are two options for configuring your IdP:
- [**Metadata configuration**](#metadata-configuration) - This is where you can download your IdP's metadata file or input the metadata URL that you got from your IdP. This is the recommended way to configure your IdP, but not all IdPs support this method.
- [**Custom configuration**](#custom-configuration) - This is where you can manually input the configuration settings for your IdP.
- #### Metadata configuration
+ ### Metadata configuration
1. In your IdP dashboard, find where you can download the metadata file or copy the metadata URL.
1. In the Clerk Dashboard on the connection's configuration page, under **Identity Provider Configuration**,select **Add via metadata**. Input the metadata URL or upload the metadata file that you got from your IdP.
- #### Custom configuration
+ ### Custom configuration
If you choose to manually input the configuration settings for your IdP, you will need to fill these three fields in the Clerk Dashboard:
diff --git a/docs/authentication/enterprise-connections/saml/google.mdx b/docs/authentication/enterprise-connections/saml/google.mdx
index 010d286a92..4ec7423f1c 100644
--- a/docs/authentication/enterprise-connections/saml/google.mdx
+++ b/docs/authentication/enterprise-connections/saml/google.mdx
@@ -20,10 +20,8 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
- Use Google Workspace to enable single sign-on (SSO) via SAML for your Clerk application.
-## Tutorial
-
- ### Set up an enterprise connection in Clerk
+ ## Set up an enterprise connection in Clerk
To create a SAML connection in Clerk:
@@ -34,7 +32,7 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
1. Add the **Specific Domain** that you want to allow this connection for. This is the domain of the users you want to allow to sign in to your application.
1. Select **Add connection**. You'll be redirected to the connection's configuration page.
- ### Create a new enterprise application in Google
+ ## Create a new enterprise application in Google
To create a new enterprise application in Google:
@@ -45,20 +43,20 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
1. In the **App details** section, an **App name** is required.
1. Select the **Continue** button.
- ### Configure your identity provider
+ ## Configure your identity provider
There are two options for configuring your IdP:
- [**Metadata configuration**](#metadata-configuration) - This is where you can input the URL to your IdP's metadata file. This is the recommended way to configure your IdP.
- [**Custom configuration**](#custom-configuration) - This is where you can manually input the configuration settings for your IdP.
- #### Metadata configuration
+ ### Metadata configuration
1. In the Google Admin Console, under **Option 1: Download IdP Metadata**, select the **Download Metadata** button.
1. Navigate back to the Clerk Dashboard and in the **Identity Provider Configuration** section, select the **Upload file** button.
1. Upload the metadata file you downloaded from Google.
- #### Custom configuration
+ ### Custom configuration
If you choose to manually input the configuration settings for your IdP, you must add these three fields to your Clerk settings:
@@ -71,7 +69,7 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
1. Fill in the **SSO URL**, **Entity ID**, and upload the **Certificate**. Don't forget to select **Save**.
1. In the Google Admin Console, select the **Continue** button.
- ### Configure your service provider
+ ## Configure your service provider
To configure your service provider (Clerk), you will need to add these two fields to your IdP's application:
@@ -85,7 +83,7 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
1. In the Google Admin Console, paste these values into their respective fields.
1. Under the **Name ID** section, select the dropdown for **Name ID format** and select **Email**.
- ### Map Google claims to Clerk attributes
+ ## Map Google claims to Clerk attributes
Mapping the claims in your IdP to the attributes in Clerk ensures that the data from your IdP is correctly mapped to the data in Clerk.
@@ -103,7 +101,7 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
1. Enter `mail` in the field.
1. If you have additional claims that you would like to map to Clerk, you can do so by following the steps in the [Map other claims](#map-other-claims-optional) section. Otherwise, select the **Finish** button.
- #### Map other claims (optional)
+ ### Map other claims (optional)
In Clerk, the [`User`](/docs/users/overview#user-object) object has a `publicMetadata` property that you can use to store additional information about your users.
@@ -121,7 +119,7 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
Learn more about [how to access the metadata from our APIs](/docs/users/metadata).
- ### Enable the connection on Google
+ ## Enable the connection on Google
Once the configuration is complete, you will be redirected to the app details page.
@@ -129,7 +127,7 @@ description: Learn how to integrate Google Workspace with Clerk using SAML SSO.
1. In the **Service status** section, select **ON for everyone**.
1. Select the **Save** button.
- ### Enable the connection for Clerk
+ ## Enable the connection for Clerk
To make the connection available for your users to authenticate with:
diff --git a/docs/authentication/enterprise-connections/saml/okta.mdx b/docs/authentication/enterprise-connections/saml/okta.mdx
index f530a92eae..2ba9589b4c 100644
--- a/docs/authentication/enterprise-connections/saml/okta.mdx
+++ b/docs/authentication/enterprise-connections/saml/okta.mdx
@@ -20,10 +20,8 @@ description: Learn how to integrate Okta Workforce with Clerk using SAML SSO.
- Use Okta Workforce to enable single sign-on (SSO) via SAML for your Clerk application.
-## Tutorial
-
- ### Set up an enterprise connection in Clerk
+ ## Set up an enterprise connection in Clerk
To create a SAML connection in Clerk:
@@ -37,7 +35,7 @@ description: Learn how to integrate Okta Workforce with Clerk using SAML SSO.
1. Save the **Single sign-on URL** and the **Audience URI (SP Entity ID)** values somewhere secure. You'll need these in the [Configure your service provider](#configure-your-service-provider) step.
1. Leave this page open.
- ### Create a new enterprise application in Okta
+ ## Create a new enterprise application in Okta
To create a new enterprise application in Okta:
@@ -49,7 +47,7 @@ description: Learn how to integrate Okta Workforce with Clerk using SAML SSO.
1. Once redirected to the **Create SAML Integration** page, fill in the **General Settings** fields. An **App name** is required.
1. Select the **Next** button to continue.
- ### Configure your service provider
+ ## Configure your service provider
Once you have moved forward from the **General Settings** instructions, you will be presented with the **Configure SAML** page.
@@ -62,7 +60,7 @@ description: Learn how to integrate Okta Workforce with Clerk using SAML SSO.
1. Paste the **Single sign-on URL** and the **Audience URI (SP Entity ID)** values that you saved earlier into their respective fields.
- ### Map Okta claims to Clerk attributes
+ ## Map Okta claims to Clerk attributes
Mapping the claims in your IdP to the attributes in Clerk ensures that the data from your IdP is correctly mapped to the data in Clerk.
@@ -84,7 +82,7 @@ description: Learn how to integrate Okta Workforce with Clerk using SAML SSO.
1. Scroll to the bottom of the page and select the **Next** button to continue.
1. You will be redirected to the **Feedback** page. Fill out the feedback however you would like and select the **Finish** button to complete the setup.
- ### Assign selected user or group in Okta
+ ## Assign selected user or group in Okta
You need to assign your users/user groups to your enterprise application. For example, if you were part of the Clerk organization, you would have access to users and groups in the Clerk organization. In this case, you could assign one or more users or entire groups to the enterprise application you just created.
@@ -94,7 +92,7 @@ description: Learn how to integrate Okta Workforce with Clerk using SAML SSO.
1. Select the **Assign** button next to the user or group that you want to assign.
1. Select the **Done** button to complete the assignment.
- ### Configure your identity provider
+ ## Configure your identity provider
Once you have completed the setup in Okta, you will be redirected to the application instances page with the **Sign On** tab selected.
@@ -103,7 +101,7 @@ description: Learn how to integrate Okta Workforce with Clerk using SAML SSO.
1. Under the **Metadata configuration** option, paste the **Metadata URL**.
1. Select the **Fetch & save** button to complete the setup.
- ### Enable the connection for Clerk
+ ## Enable the connection for Clerk
To make the connection available for your users to authenticate with:
diff --git a/docs/authentication/social-connections/spotify.mdx b/docs/authentication/social-connections/spotify.mdx
index 14bf02bde1..93023f25ab 100644
--- a/docs/authentication/social-connections/spotify.mdx
+++ b/docs/authentication/social-connections/spotify.mdx
@@ -28,7 +28,7 @@ Enabling OAuth with [Spotify](https://developer.spotify.com/documentation/web-ap
To make the setup process easier, it's recommended to keep two browser tabs open: one for the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) and one for your [Spotify Developer Dashboard](https://developer.spotify.com/).
- ### Enable Spotify as a social connection in Clerk
+ ## Enable Spotify as a social connection in Clerk
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**.
@@ -36,7 +36,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
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.
- ### Create your app in Spotify
+ ## Create your app in Spotify
1. On a separate page, go to the [Spotify Developer Dashboard](https://developer.spotify.com/) and sign in.
1. In the top-right, select your profile button and select [**Dashboard**](https://developer.spotify.com/dashboard).
@@ -45,7 +45,7 @@ To make the setup process easier, it's recommended to keep two browser tabs open
1. Select **Save**.
1. On your app page, select **Settings**. Keep this page open.
- ### Set the Client ID and Client Secret in the Clerk Dashboard
+ ## Set the Client ID and Client Secret in the Clerk Dashboard
1. In the Spotify app's settings page, save the **Client ID** and **Client secret** somewhere secure. To reveal the **Client secret**, you must select **View client secret**.
1. Navigate back to the Clerk Dashboard where the modal should still be open and paste these values into the respective fields.
diff --git a/docs/authentication/social-connections/x-twitter.mdx b/docs/authentication/social-connections/x-twitter.mdx
index 296986e1c3..4610f5a6d9 100644
--- a/docs/authentication/social-connections/x-twitter.mdx
+++ b/docs/authentication/social-connections/x-twitter.mdx
@@ -23,15 +23,13 @@ description: Learn how to set up a social connection with X/Twitter v2 in your C
- Set X/Twitter's **Client ID** and **Client Secret** in the Clerk Dashboard
-## Overview
-
Clerk does not currently support preconfigured shared OAuth credentials for X/Twitter on development instances. This means you will have to provide custom credentials for both development _and_ production instances, which involves generating your own **Client ID** and **Client Secret** using your X/Twitter Developer account. This tutorial will walk you through that process in just a few simple steps.
> [!WARNING]
> X/Twitter v2 is currently not providing email addresses of users. The user will have to fill in their email address manually when they return to your application after authenticating with X/Twitter.
- ### Create an X/Twitter application
+ ## Create an X/Twitter application
If you don't have an existing X/Twitter application you've set up for social connection, you need to register a new one at the [X/Twitter Developer Portal](https://developer.twitter.com/en/portal/dashboard). Note that the process requires approval from X/Twitter before your new application can be used.
@@ -40,7 +38,7 @@ Clerk does not currently support preconfigured shared OAuth credentials for X/Tw
1. Navigate to the X/Twitter Developer Portal and go to [**Projects & Apps**](https://developer.twitter.com/en/portal/projects-and-apps).
1. Select **+ Add App**. After entering a name, you will be presented with your app's credentials. However, for setting up the X/Twitter v2 social connection with Clerk, **you won't need these credentials**. This is because you will be utilizing the OAuth 2.0 flow, which relies on different authentication details.
- ### Enable X/Twitter as a social connection
+ ## Enable X/Twitter as a social connection
To enable X/Twitter as a social connection for your Clerk application:
@@ -49,7 +47,7 @@ Clerk does not currently support preconfigured shared OAuth credentials for X/Tw
1. In the **Choose provider** dropdown, select **X/Twitter**.
1. Toggle on **Use custom credentials** and copy **Redirect URI**. Keep this modal and page open.
- ### Set the Redirect URI in your X/Twitter application
+ ## Set the Redirect URI in your X/Twitter application
1. Navigate back to the X/Twitter Developer portal.
1. On the application settings screen, scroll down to the **User authentication settings** section and select **Set up**. You'll be presented with the **User authentication settings** page.
@@ -58,7 +56,7 @@ Clerk does not currently support preconfigured shared OAuth credentials for X/Tw
1. Under **App info**, in the **Callback URI / Redirect URL** input, paste the **Redirect URI** value you copied from the Clerk Dashboard.
1. Fill any other required fields, such as the **Website URL**, and select **Save**.
- ### Set the Client ID and Client Secret in the Clerk Dashboard
+ ## Set the Client ID and Client Secret in the Clerk Dashboard
After setting up your X/Twitter application, you should be able to copy your **Client ID** and **Client Secret**.
@@ -67,7 +65,7 @@ Clerk does not currently support preconfigured shared OAuth credentials for X/Tw
> [!NOTE]
> If the modal or page is not still open, in the Clerk Dashboard, navigate to the [**SSO connections**](https://dashboard.clerk.com/last-active?path=user-authentication/sso-connections) page. Next to **X/Twitter**, select the settings icon. Under **Use custom credentials**, you can paste the **Client ID** and **Client Secret** into their respective fields.
- ### Test your OAuth
+ ## Test your OAuth
The simplest way to test your OAuth is to visit your Clerk application's [Account Portal](/docs/customization/account-portal/overview), which is available for all Clerk applications out-of-the-box.
diff --git a/docs/backend-requests/making/custom-session-token.mdx b/docs/backend-requests/making/custom-session-token.mdx
index 6a15fed211..4b4973f87e 100644
--- a/docs/backend-requests/making/custom-session-token.mdx
+++ b/docs/backend-requests/making/custom-session-token.mdx
@@ -11,10 +11,8 @@ This guide will show you how to customize a session token to include additional
-{/* TODO: Update the H3 to an H2 when the Steps component can accept headings other than H3. */}
-
- ### Add custom claims to your session token
+ ## Add custom claims to your session token
1. In the Clerk Dashboard, navigate to the [**Sessions**](https://dashboard.clerk.com/last-active?path=sessions) page.
1. In the **Customize your session token** section, click the **Edit** button.
@@ -24,7 +22,7 @@ This guide will show you how to customize a session token to include additional
![Clerk Dashboard showing the custom claim modal](/docs/images/advance/session-tokens/custom-session-example.png)
- ### Use the custom claims in your application
+ ## Use the custom claims in your application
The [`Auth`](/docs/references/nextjs/auth-object) object in the `@clerk/nextjs` package includes a `sessionClaims` property that contains the custom claims you added to your session token.
@@ -40,11 +38,11 @@ This guide will show you how to customize a session token to include additional
export default async function Page() {
const { sessionClaims } = await auth()
- const firstName = sessionClaims?.fullName
+ const fullName = sessionClaims?.fullName
const primaryEmail = sessionClaims?.primaryEmail
- return NextResponse.json({ firstName, primaryEmail })
+ return NextResponse.json({ fullName, primaryEmail })
}
```
@@ -55,16 +53,16 @@ This guide will show you how to customize a session token to include additional
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { sessionClaims } = getAuth(req)
- const firstName = sessionClaims.fullName
+ const fullName = sessionClaims.fullName
const primaryEmail = sessionClaims.primaryEmail
- return res.status(200).json({ firstName, primaryEmail })
+ return res.status(200).json({ fullName, primaryEmail })
}
```
- ### Add global TypeScript type for custom session claims
+ ## Add global TypeScript type for custom session claims
To get auto-complete and prevent TypeScript errors when working with custom session claims, you can define a global type.
@@ -73,14 +71,14 @@ This guide will show you how to customize a session token to include additional
1. Create the `CustomJwtSessionClaims` interface and declare it globally.
1. Add the custom claims to the `CustomJwtSessionClaims` interface.
- The following example demonstrates how to add the `firstName` and `primaryEmail` claims to the `CustomJwtSessionClaims` interface.
+ The following example demonstrates how to add the `fullName` and `primaryEmail` claims to the `CustomJwtSessionClaims` interface.
```tsx {{ filename: 'types/globals.d.ts' }}
export {}
declare global {
interface CustomJwtSessionClaims {
- firstName?: string
+ fullName?: string
primaryEmail?: string
}
}
diff --git a/docs/backend-requests/making/jwt-templates.mdx b/docs/backend-requests/making/jwt-templates.mdx
index 4dce58e567..96d42f6339 100644
--- a/docs/backend-requests/making/jwt-templates.mdx
+++ b/docs/backend-requests/making/jwt-templates.mdx
@@ -10,8 +10,6 @@ Clerk offers the ability to generate [JSON Web Tokens](https://en.wikipedia.org/
You can control the claims that will go into these tokens by creating custom **JWT templates** that fit your needs. This enables you to integrate with any third-party services that support authentication with JWTs. An example use case is integrating with a third-party service that is able to consume JWTs, but requires them to be in a particular format.
-
-
## What is a JWT template?
**JWT templates** are essentially JSON objects that specify claims to be included in the generated tokens, along with their respective values.
@@ -123,7 +121,7 @@ The result of a conditional expression is that of the first operand that does no
```json
{
- "has_verified_contact_info": "{{user.has_verified_email || user.has_verified_phone}}",
+ "has_verified_contact_info": "{{user.email_verified || user.phone_number_verified}}",
// fallback to a string value
"full_name": "{{user.full_name || 'Awesome User'}}",
diff --git a/docs/backend-requests/resources/session-tokens.mdx b/docs/backend-requests/resources/session-tokens.mdx
index 468659a991..ca19a995cb 100644
--- a/docs/backend-requests/resources/session-tokens.mdx
+++ b/docs/backend-requests/resources/session-tokens.mdx
@@ -38,7 +38,7 @@ You can also create custom tokens using a [JWT template](/docs/backend-requests/
The Clerk session token is stored in a cookie. All modern browsers [limit the maximum size of a cookie to 4kb](https://datatracker.ietf.org/doc/html/rfc2109#section-6.3). Exceeding this limit can have adverse effects, including a possible infinite redirect loop for users who exceed this size in Next.js applications.
-A session token with the [default session claims](#default-session-claims) won't run into this issue, as this configuration produces a cookie significantly smaller than 4kb. However, this limitation becomes relevant when implementing a [custom session token](/docs/backend-requests/making/custom-session-token) or creating a [custom JWT template](/docs/backend-requests/making/jwt-templates). In these cases, it's recommended to move particularly large claims out of the token and fetch these using a separate API call from your backend.
+A session token with the [default session claims](#default-session-claims) won't run into this issue, as this configuration produces a cookie significantly smaller than 4kb. However, this limitation becomes relevant when implementing a [custom session token](/docs/backend-requests/making/custom-session-token). In this case, it's recommended to move particularly large claims out of the token and fetch these using a separate API call from your backend.
Claims to monitor for size limits:
@@ -50,6 +50,9 @@ Claims to monitor for size limits:
If you include any of these claims in your token, use caution to ensure the stored data doesn't exceed the size limit.
+> [!NOTE]
+> If your application encounters this issue, the Clerk Dashboard will display a warning: **"Some users are exceeding cookie size limits"**. To resolve this, update your [custom session token](/docs/backend-requests/making/custom-session-token).
+
## Validate session tokens
If you're using the middleware provided by our Clerk SDKs, this is all handled automatically in every request. If you're not using the middleware, you can still use the respective helpers provided by the SDKs to validate the tokens.
diff --git a/docs/components/authentication/sign-up.mdx b/docs/components/authentication/sign-up.mdx
index 950fe34e60..4f80641e35 100644
--- a/docs/components/authentication/sign-up.mdx
+++ b/docs/components/authentication/sign-up.mdx
@@ -79,9 +79,9 @@ All props are optional.
---
- `unsafeMetadata`
- - `{[string]: any} | null`
+ - [`SignUpUnsafeMetadata`](/docs/references/javascript/types/metadata#sign-up-unsafe-metadata)
- An object containing key-value pairs for `unsafeMetadata` that will be saved after the user signs up. For example: `{ "company": "companyID1234" }`.
+ Metadata that can be read and set from the frontend and the backend. Once the sign-up is complete, the value of this field will be automatically copied to the created user's unsafe metadata (`User.unsafeMetadata`). One common use case is to collect custom information about the user during the sign-up process and store it in this property. Read more about [unsafe metadata](/docs/users/metadata#unsafe-metadata).
## Usage with frameworks
diff --git a/docs/components/clerk-provider.mdx b/docs/components/clerk-provider.mdx
index abe1e84ba0..bcda26af27 100644
--- a/docs/components/clerk-provider.mdx
+++ b/docs/components/clerk-provider.mdx
@@ -1,13 +1,13 @@
---
title: '``'
-description: The component wraps your React application to provide active session and user context to Clerk's hooks and other components.
+description: The component provides session and user context to Clerk's hooks and components.
---
-The `` component wraps your React application to provide active session and user context to Clerk's hooks and other components.
+The `` component is required to integrate Clerk into your React application, providing session and user context to Clerk's hooks and components.
-## Usage
+The recommended approach is to wrap your entire app with `` at the entry point to make authentication globally accessible. If you only need authentication for specific routes or pieces of your application, render `` deeper in the component tree. This allows you to implement Clerk's functionality precisely where required without impacting the rest of your app.
-The `` component must be added to your React entrypoint.
+## Usage
@@ -90,7 +90,14 @@ The `` component must be added to your React entrypoint.
- `allowedRedirectOrigins?`
- `Array`
- Optional array of domains used to validate against the query param of an auth redirect. If no match is made, the redirect is considered unsafe and the default redirect will be used with a warning passed to the console.
+ An optional array of domains to validate user-provided redirect URLs against. If no match is made, the redirect is considered unsafe and the default redirect will be used with a warning logged in the console.
+
+ ---
+
+ - `allowedRedirectProtocols?`
+ - `Array`
+
+ An optional array of protocols to validate user-provided redirect URLs against. If no match is made, the redirect is considered unsafe and the default redirect will be used with a warning logged in the console.
---
@@ -202,7 +209,7 @@ The `` component must be added to your React entrypoint.
- `signUpUrl`
- `string`
- This URL will be used for any redirects that might happen and needs to point to your primary application on the client-side. This option is optional for production instances and required for development instances. It's recommended to use [the environment variable](/docs/deployments/clerk-environment-variables#sign-in-and-sign-up-redirects) instead.
+ This URL will be used for any redirects that might happen and needs to point to your primary application on the client-side. This option is optional for production instances but **must be set for a satellite application in a development instance.** It's recommended to use [the environment variable](/docs/deployments/clerk-environment-variables#sign-in-and-sign-up-redirects) instead.
---
diff --git a/docs/components/organization/create-organization.mdx b/docs/components/organization/create-organization.mdx
index b083ec1043..c32e40a38f 100644
--- a/docs/components/organization/create-organization.mdx
+++ b/docs/components/organization/create-organization.mdx
@@ -59,7 +59,7 @@ The following example includes a basic implementation of the `
- ```jsx {{ filename: '/app/create-organization/[[...create-organization]]/page.tsx' }}
+ ```jsx {{ filename: 'app/create-organization/[[...create-organization]]/page.tsx' }}
import { CreateOrganization } from '@clerk/nextjs'
export default function CreateOrganizationPage() {
diff --git a/docs/components/organization/organization-list.mdx b/docs/components/organization/organization-list.mdx
index c11dcfaf9b..d97d8cf159 100644
--- a/docs/components/organization/organization-list.mdx
+++ b/docs/components/organization/organization-list.mdx
@@ -64,7 +64,7 @@ All props are optional.
- ```jsx {{ filename: '/app/discover/page.tsx' }}
+ ```jsx {{ filename: 'app/discover/page.tsx' }}
import { OrganizationList } from '@clerk/nextjs'
export default function OrganizationListPage() {
diff --git a/docs/components/organization/organization-profile.mdx b/docs/components/organization/organization-profile.mdx
index 54f9c09a80..9dc549275b 100644
--- a/docs/components/organization/organization-profile.mdx
+++ b/docs/components/organization/organization-profile.mdx
@@ -56,7 +56,7 @@ All props are optional.
You can embed the `` component using the [Next.js optional catch-all route](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-routes). This allows you to redirect the user inside your application.
- ```jsx {{ filename: '/app/organization-profile/[[...organization-profile]]/page.tsx' }}
+ ```jsx {{ filename: 'app/organization-profile/[[...organization-profile]]/page.tsx' }}
import { OrganizationProfile } from '@clerk/nextjs'
export default function OrganizationProfilePage() {
diff --git a/docs/components/organization/organization-switcher.mdx b/docs/components/organization/organization-switcher.mdx
index 734ae48d85..0edcfc5b1c 100644
--- a/docs/components/organization/organization-switcher.mdx
+++ b/docs/components/organization/organization-switcher.mdx
@@ -103,7 +103,7 @@ All props below are optional.
- ```jsx {{ filename: '/app/organization-switcher/[[...organization-switcher]]/page.tsx' }}
+ ```jsx {{ filename: 'app/organization-switcher/[[...organization-switcher]]/page.tsx' }}
import { OrganizationSwitcher } from '@clerk/nextjs'
export default function OrganizationSwitcherPage() {
diff --git a/docs/components/overview.mdx b/docs/components/overview.mdx
index 30ef4f78aa..fbc6b591d8 100644
--- a/docs/components/overview.mdx
+++ b/docs/components/overview.mdx
@@ -5,15 +5,48 @@ description: A list of Clerk's comprehensive suite of components designed to sea
Clerk offers a comprehensive suite of components designed to seamlessly integrate authentication and multi-tenancy into your application. With Clerk components, you can easily customize the appearance of authentication components and pages, manage the entire authentication flow to suit your specific needs, and even build robust SaaS applications.
-To get started, select a component from the navigation on the left.
+## UI components
-## What are control components?
+- [``](/docs/components/authentication/sign-in)
+- [``](/docs/components/authentication/sign-up)
+- [``](/docs/components/authentication/google-one-tap)
+- [``](/docs/components/user/user-button)
+- [``](/docs/components/user/user-profile)
+- [``](/docs/components/organization/create-organization)
+- [``](/docs/components/organization/organization-profile)
+- [``](/docs/components/organization/organization-switcher)
+- [``](/docs/components/organization/organization-list)
+- [``](/docs/components/waitlist)
+
+## Control components
+
+{/* TODO(Alexis): update with new callout */}
Control components manage authentication-related behaviors in your application. They handle tasks such as controlling content visibility based on user authentication status, managing loading states during authentication processes, and redirecting users to appropriate pages. Control components render at `` and `` states for assertions on the [`Clerk` object](/docs/references/javascript/clerk/clerk). A common example is the [``](/docs/components/control/signed-in) component, which allows you to conditionally render content only when a user is authenticated.
+- [``](/docs/components/control/authenticate-with-callback)
+- [``](/docs/components/control/clerk-loaded)
+- [``](/docs/components/control/clerk-loading)
+- [``](/docs/components/protect)
+- [``](/docs/components/control/multi-session)
+- [``](/docs/components/control/redirect-to-signin)
+- [``](/docs/components/control/redirect-to-signup)
+- [``](/docs/components/control/redirect-to-userprofile)
+- [``](/docs/components/control/redirect-to-organizationprofile)
+- [``](/docs/components/control/redirect-to-createorganization)
+- [``](/docs/components/control/signed-in)
+- [``](/docs/components/control/signed-out)
+
+## Unstyled components
+
+- [``](/docs/components/unstyled/sign-in-button)
+- [``](/docs/components/unstyled/sign-in-with-metamask)
+- [``](/docs/components/unstyled/sign-up-button)
+- [``](/docs/components/unstyled/sign-out-button)
+
## Customization Guides
-- [Theme components with the appearance prop](/docs/customization/overview)
+- [Customize components with the `appearance` prop](/docs/customization/overview)
- [Localize components with the `localization` prop (experimental)](/docs/customization/localization)
- [Add pages to the `` component](/docs/customization/user-profile)
- [Add pages to the `` component](/docs/customization/organization-profile)
diff --git a/docs/components/protect.mdx b/docs/components/protect.mdx
index 44a9a497af..e9f90fe55e 100644
--- a/docs/components/protect.mdx
+++ b/docs/components/protect.mdx
@@ -158,7 +158,7 @@ The following example uses ``'s `condition` prop to conditionally rende
- ```tsx {{ filename: '/app/dashboard/settings/layout.tsx' }}
+ ```tsx {{ filename: 'app/dashboard/settings/layout.tsx' }}
import type { PropsWithChildren } from 'react'
import { Protect } from '@clerk/nextjs'
diff --git a/docs/components/user/user-profile.mdx b/docs/components/user/user-profile.mdx
index e303ba5be1..6c9f17b42d 100644
--- a/docs/components/user/user-profile.mdx
+++ b/docs/components/user/user-profile.mdx
@@ -53,7 +53,7 @@ All props are optional.
You can embed the `` component using the [Next.js optional catch-all route](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-routes). This allows you to redirect the user inside your application.
- ```jsx {{ filename: '/app/user-profile/[[...user-profile]]/page.tsx' }}
+ ```jsx {{ filename: 'app/user-profile/[[...user-profile]]/page.tsx' }}
import { UserProfile } from '@clerk/nextjs'
const UserProfilePage = () =>
diff --git a/docs/components/waitlist.mdx b/docs/components/waitlist.mdx
index ee5e0dafd2..e558b24b8e 100644
--- a/docs/components/waitlist.mdx
+++ b/docs/components/waitlist.mdx
@@ -53,7 +53,7 @@ The following example includes a basic implementation of the `` comp
- ```jsx {{ filename: '/app/waitlist/[[...waitlist]]/page.tsx' }}
+ ```jsx {{ filename: 'app/waitlist/[[...waitlist]]/page.tsx' }}
import { Waitlist } from '@clerk/nextjs'
export default function WaitlistPage() {
diff --git a/docs/custom-flows/bot-sign-up-protection.mdx b/docs/custom-flows/bot-sign-up-protection.mdx
index 20bf49b4cc..e6c63a18b5 100644
--- a/docs/custom-flows/bot-sign-up-protection.mdx
+++ b/docs/custom-flows/bot-sign-up-protection.mdx
@@ -8,12 +8,12 @@ description: Learn how to add Clerk's bot protection to your custom sign-up flow
Clerk provides the ability to add a CAPTCHA widget to your sign-up flows to protect against bot sign-ups. The [``](/docs/components/authentication/sign-up) component handles this flow out-of-the-box. However, if you're building a custom user interface, this guide will show you how to add the CAPTCHA widget to your custom sign-up flow.
- ### Enable bot sign-up protection
+ ## Enable bot sign-up protection
1. In the Clerk Dashboard, navigate to the [**Attack protection**](https://dashboard.clerk.com/last-active?path=user-authentication/attack-protection) page.
1. In the **Bot sign-up protection** section, enable the feature and choose the **CAPTCHA type** you want to use.
- ### Add the CAPTCHA widget to your custom sign-up form
+ ## Add the CAPTCHA widget to your custom sign-up form
To render the CAPTCHA widget in your custom sign-up form, you need to include a specific element in your DOM. Specifically, there should be a `` element by the time you call `signUp.create()`. This element acts as a placeholder onto which the widget will be rendered.
diff --git a/docs/custom-flows/email-password-mfa.mdx b/docs/custom-flows/email-password-mfa.mdx
index 35635ef407..2296237854 100644
--- a/docs/custom-flows/email-password-mfa.mdx
+++ b/docs/custom-flows/email-password-mfa.mdx
@@ -11,10 +11,8 @@ Clerk supports second factor verification through **SMS verification code**, **A
This guide will walk you through how to build a custom email/password sign-in flow that supports **Authenticator application** and **Backup codes** as the second factor.
-{/* TODO: Update these Steps when the Steps component can accept other headings. As of right now, Steps can only accept H3s. */}
-
- ### Enable email and password authentication
+ ## Enable email and password authentication
This example uses email and password authentication, however, you can modify this approach according to the needs of your application. To use email and password authentication, you first need to enable these authentication strategies in the Clerk Dashboard.
@@ -22,14 +20,15 @@ This guide will walk you through how to build a custom email/password sign-in fl
1. Ensure that _only_ **Email address** is required. If **Phone number** and **Username** are enabled, ensure they are not required. Use the settings icon next to each user attribute to check if a setting is required or optional. If you want to require **Username**, you must collect the username and pass the data to the `create()` method in your custom flow.
1. In the **Authentication strategies** section of this page, ensure **Password** is enabled.
- ### Enable multi-factor authentication
+ ## Enable multi-factor authentication
For your users to be able to enable MFA for their account, you need to enable MFA as an authentication strategy in your Clerk application.
1. In the Clerk Dashboard, navigate to the [**Multi-factor**](https://dashboard.clerk.com/last-active?path=user-authentication/multi-factor) page.
1. For the purpose of this guide, toggle on both the **Authenticator application** and **Backup codes** strategies.
+ 1. Select **Save**.
- ### Sign-in flow
+ ## Sign-in flow
Signing in to an MFA-enabled account is identical to the regular sign-in process. However, in the case of an MFA-enabled account, a sign-in won't convert until both first factor and second factor verifications are completed.
@@ -309,19 +308,34 @@ This guide will walk you through how to build a custom email/password sign-in fl
### Build the flow
- Create a component that handles the sign-in with multi-factor authentication flow.
+ 1. Create the `(auth)` route group. This groups your sign-up and sign-in pages.
+ 1. In the `(auth)` group, create a `_layout.tsx` file with the following code. The [`useAuth()`](/docs/references/react/use-auth) hook is used to access the user's authentication state. If the user's already signed in, they'll be redirected to the home page.
+
+ ```tsx {{ filename: 'app/(auth)/_layout.tsx' }}
+ import { Redirect, Stack } from 'expo-router'
+ import { useAuth } from '@clerk/clerk-expo'
+
+ export default function AuthenticatedLayout() {
+ const { isSignedIn } = useAuth()
+
+ if (isSignedIn) {
+ return
+ }
+
+ return
+ }
+ ```
- > [!NOTE]
- > You can render this component in a custom sign-in or sign-up flow, which you can find examples of in [the Expo quickstart](/docs/quickstarts/expo).
+ In the `(auth)` group, create a `sign-in.tsx` file with the following code. The [`useSignIn()`](/docs/references/react/use-sign-in) hook is used to create a sign-in flow. The user can sign in using their email and password and will be prompted to verify their account with a code from their authenticator app or with a backup code.
- ```tsx {{ filename: 'SignInMFAForm.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
import React from 'react'
import { useSignIn } from '@clerk/clerk-expo'
import { useRouter } from 'expo-router'
- import { Text, TextInput, TouchableOpacity, View } from 'react-native'
+ import { Text, TextInput, Button, View } from 'react-native'
import Checkbox from 'expo-checkbox'
- export default function SignInMFAForm() {
+ export default function Page() {
const { signIn, setActive, isLoaded } = useSignIn()
const [email, setEmail] = React.useState('')
@@ -335,18 +349,24 @@ This guide will walk you through how to build a custom email/password sign-in fl
const handleFirstStage = async () => {
if (!isLoaded) return
+ // Attempt to sign in using the email and password provided
try {
const attemptFirstFactor = await signIn.create({
identifier: email,
password,
})
+ // If the sign-in was successful, set the session to active
+ // and redirect the user
if (attemptFirstFactor.status === 'complete') {
await setActive({ session: attemptFirstFactor.createdSessionId })
- router.replace('/dashboard')
+ router.replace('/')
} else if (attemptFirstFactor.status === 'needs_second_factor') {
+ // If the sign-in requires a second factor, display the TOTP form
setDisplayTOTP(true)
} else {
+ // If the sign-in failed, check why. User might need to
+ // complete further steps.
console.error(JSON.stringify(attemptFirstFactor, null, 2))
}
} catch (err) {
@@ -356,6 +376,7 @@ This guide will walk you through how to build a custom email/password sign-in fl
}
}
+ // Handle the submission of the TOTP or backup code
const onPressTOTP = React.useCallback(async () => {
if (!isLoaded) return
@@ -371,13 +392,13 @@ This guide will walk you through how to build a custom email/password sign-in fl
if (attemptSecondFactor.status === 'complete') {
await setActive({ session: attemptSecondFactor.createdSessionId })
- router.replace('/dashboard')
+ router.replace('/')
} else {
// If the status is not complete, check why. User may need to
// complete further steps.
console.error(JSON.stringify(attemptSecondFactor, null, 2))
}
- } catch (err: any) {
+ } catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
@@ -390,32 +411,30 @@ This guide will walk you through how to build a custom email/password sign-in fl
Verify your account
- Code setCode(c)}
/>
-
- This code is a backup code
+
+ Check if this code is a backup code setUseBackupCode((prev) => !prev)} />
-
- Verify
-
+
)
}
return (
- Sign In
+ Sign in setEmail(email)}
/>
@@ -423,15 +442,14 @@ This guide will walk you through how to build a custom email/password sign-in fl
setPassword(password)}
/>
-
- Sign In
-
+
)
}
diff --git a/docs/custom-flows/email-password.mdx b/docs/custom-flows/email-password.mdx
index 8c916e2dd7..d22ac988ff 100644
--- a/docs/custom-flows/email-password.mdx
+++ b/docs/custom-flows/email-password.mdx
@@ -10,7 +10,7 @@ This guide will walk you through how to build a custom email/password sign-up an
{/* TODO: Update these Steps when the Steps component can accept other headings. As of right now, Steps can only accept H3s. */}
- ### Enable email and password authentication
+ ## Enable email and password authentication
To use email and password authentication, you first need to enable these [authentication strategies](/docs/authentication/configuration/sign-up-sign-in-options#authentication-strategies) in the Clerk Dashboard.
@@ -21,7 +21,7 @@ This guide will walk you through how to build a custom email/password sign-up an
> [!NOTE]
> By default, the [verification method](/docs/authentication/configuration/sign-up-sign-in-options#verification-methods) for the **Email address** strategy is set to **Email verification code**. This means that when a user signs up using their email address and password, Clerk sends a one-time code to their email address. The user must then enter this code to verify their email and complete the sign-up process.
- ### Sign-up flow
+ ## Sign-up flow
To sign up a user using their email, password, and email verification code, you must:
@@ -34,7 +34,7 @@ This guide will walk you through how to build a custom email/password sign-up an
This example is written for Next.js App Router but it can be adapted for any React meta framework, such as Remix.
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
'use client'
import * as React from 'react'
@@ -257,9 +257,10 @@ This guide will walk you through how to build a custom email/password sign-up an
- Create a route group with a layout that redirects users if they're already signed in, as shown in the following example:
+ 1. Create the `(auth)` route group. This groups your sign-up and sign-in pages.
+ 1. In the `(auth)` group, create a `_layout.tsx` file with the following code. The [`useAuth()`](/docs/references/react/use-auth) hook is used to access the user's authentication state. If the user's already signed in, they'll be redirected to the home page.
- ```tsx {{ filename: '/app/(auth)/_layout.tsx' }}
+ ```tsx {{ filename: 'app/(auth)/_layout.tsx' }}
import { Redirect, Stack } from 'expo-router'
import { useAuth } from '@clerk/clerk-expo'
@@ -274,57 +275,53 @@ This guide will walk you through how to build a custom email/password sign-up an
}
```
- Then create a sign-up page that sends users an email verification code to create an account.
+ In the `(auth)` group, create a `sign-up.tsx` file with the following code. The [`useSignUp()`](/docs/references/react/use-sign-up) hook is used to create a sign-up flow. The user can sign up using their email and password and will receive an email verification code to confirm their email.
- ```tsx {{ filename: '/app/(auth)/sign-up.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/(auth)/sign-up.tsx', collapsible: true }}
import * as React from 'react'
- import { Text, TextInput, TouchableOpacity, View } from 'react-native'
+ import { Text, TextInput, Button, View } from 'react-native'
import { useSignUp } from '@clerk/clerk-expo'
+ import { Link, useRouter } from 'expo-router'
- export default function SignUpScreen() {
+ export default function Page() {
const { isLoaded, signUp, setActive } = useSignUp()
+ const router = useRouter()
- const [firstName, setFirstName] = React.useState('')
- const [lastName, setLastName] = React.useState('')
const [emailAddress, setEmailAddress] = React.useState('')
const [password, setPassword] = React.useState('')
const [pendingVerification, setPendingVerification] = React.useState(false)
const [code, setCode] = React.useState('')
+ // Handle submission of sign-up form
const onSignUpPress = async () => {
- if (!isLoaded) {
- return
- }
+ if (!isLoaded) return
- // Start the sign-up process using the info the user provided
+ // Start sign-up process using email and password provided
try {
await signUp.create({
- firstName,
- lastName,
emailAddress,
password,
})
- // Send the user an email with the verification code
+ // Send user an email with verification code
await signUp.prepareEmailAddressVerification({ strategy: 'email_code' })
- // Display the second form to collect the verification code
+ // Set 'pendingVerification' to true to display second form
+ // and capture OTP code
setPendingVerification(true)
- } catch (err: any) {
+ } catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}
- // Handle the submission of the verification form
- const onPressVerify = async () => {
- if (!isLoaded) {
- return
- }
+ // Handle submission of verification form
+ const onVerifyPress = async () => {
+ if (!isLoaded) return
- // Use the code the user provided to attempt verification
try {
+ // Use the code the user provided to attempt verification
const signUpAttempt = await signUp.attemptEmailAddressVerification({
code,
})
@@ -333,71 +330,60 @@ This guide will walk you through how to build a custom email/password sign-up an
// and redirect the user
if (signUpAttempt.status === 'complete') {
await setActive({ session: signUpAttempt.createdSessionId })
- router.replace('/dashboard')
+ router.replace('/')
} else {
// If the status is not complete, check why. User may need to
// complete further steps.
console.error(JSON.stringify(signUpAttempt, null, 2))
}
- } catch (err: any) {
+ } catch (err) {
+ // See https://clerk.com/docs/custom-flows/error-handling
+ // for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}
+ if (pendingVerification) {
+ return (
+ <>
+ Verify your email
+ setCode(code)}
+ />
+
+ >
+ )
+ }
+
return (
- {!pendingVerification && (
-
-
- setFirstName(firstName)}
- />
-
-
- setLastName(lastName)}
- />
-
-
- setEmailAddress(email)}
- />
-
-
-
- setPassword(password)}
- />
-
-
-
- Sign up
-
-
- )}
- {pendingVerification && (
-
-
- setCode(code)} />
-
-
- Verify Email
-
+ <>
+ Sign up
+ setEmailAddress(email)}
+ />
+ setPassword(password)}
+ />
+
+
+ Have an account?
+
+ Sign in
+
- )}
+ >
)
}
@@ -481,7 +467,7 @@ This guide will walk you through how to build a custom email/password sign-up an
- ### Sign-in flow
+ ## Sign-in flow
To authenticate a user using their email and password, you must:
@@ -492,7 +478,7 @@ This guide will walk you through how to build a custom email/password sign-up an
This example is written for Next.js App Router but it can be adapted for any React meta framework, such as Remix.
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
'use client'
import * as React from 'react'
@@ -509,9 +495,7 @@ This guide will walk you through how to build a custom email/password sign-up an
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
- if (!isLoaded) {
- return
- }
+ if (!isLoaded) return
// Start the sign-in process using the email and password provided
try {
@@ -654,42 +638,24 @@ This guide will walk you through how to build a custom email/password sign-up an
- Create a route group with a layout that redirects users if they're already signed in, as shown in the following example:
+ In the `(auth)` group, create a `sign-in.tsx` file with the following code. The [`useSignIn()`](/docs/references/react/use-sign-in) hook is used to create a sign-in flow. The user can sign in using email address and password, or navigate to the sign-up page.
- ```tsx {{ filename: '/app/(auth)/_layout.tsx' }}
- import { Redirect, Stack } from 'expo-router'
- import { useAuth } from '@clerk/clerk-expo'
-
- export default function GuestLayout() {
- const { isSignedIn } = useAuth()
-
- if (isSignedIn) {
- return
- }
-
- return
- }
- ```
-
- Then, create a sign-in page that allows users to sign in or navigate to the sign-up page that you created earlier.
-
- ```tsx {{ filename: '/app/(auth)/sign-in.tsx', collapsible: true }}
- import { useClerk, useSignIn } from '@clerk/clerk-expo'
- import { Link, Stack } from 'expo-router'
- import { Text, TextInput, TouchableOpacity, View } from 'react-native'
+ ```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
+ import { useSignIn } from '@clerk/clerk-expo'
+ import { Link, useRouter } from 'expo-router'
+ import { Text, TextInput, Button, View } from 'react-native'
import React from 'react'
export default function Page() {
const { signIn, setActive, isLoaded } = useSignIn()
+ const router = useRouter()
const [emailAddress, setEmailAddress] = React.useState('')
const [password, setPassword] = React.useState('')
// Handle the submission of the sign-in form
const onSignInPress = React.useCallback(async () => {
- if (!isLoaded) {
- return
- }
+ if (!isLoaded) return
// Start the sign-in process using the email and password provided
try {
@@ -702,13 +668,13 @@ This guide will walk you through how to build a custom email/password sign-up an
// and redirect the user
if (signInAttempt.status === 'complete') {
await setActive({ session: signInAttempt.createdSessionId })
- router.replace('/dashboard')
+ router.replace('/')
} else {
// If the status is not complete, check why. User may need to
// complete further steps.
console.error(JSON.stringify(signInAttempt, null, 2))
}
- } catch (err: any) {
+ } catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
@@ -717,42 +683,26 @@ This guide will walk you through how to build a custom email/password sign-up an
return (
- Sign in
+ setEmailAddress(emailAddress)}
/>
-
- setEmailAddress(emailAddress)}
- />
-
-
-
- setPassword(password)}
- />
-
-
-
- Sign in
-
-
-
+ setPassword(password)}
+ />
+
+ Don't have an account?
-
-
-
- Sign up
-
+
+ Sign up
diff --git a/docs/custom-flows/email-sms-otp.mdx b/docs/custom-flows/email-sms-otp.mdx
index 363d863d34..9eaec44650 100644
--- a/docs/custom-flows/email-sms-otp.mdx
+++ b/docs/custom-flows/email-sms-otp.mdx
@@ -9,10 +9,8 @@ Clerk supports passwordless authentication, which lets users sign in and sign up
This guide will walk you through how to build a custom SMS OTP sign-up and sign-in flow. The process for using email OTP is similar, and the differences will be highlighted throughout.
-{/* TODO: Update these Steps when the Steps component can accept other headings. As of right now, Steps can only accept H3s. */}
-
- ### Enable SMS OTP
+ ## Enable SMS OTP
To use SMS OTP as an authentication strategy, you first need to enable it in the Clerk Dashboard.
@@ -20,7 +18,7 @@ This guide will walk you through how to build a custom SMS OTP sign-up and sign-
1. Ensure that _only_ **Phone number** is required. If **Email address** or **Username** are enabled, ensure they are not required. Use the settings icon to check if a setting is required or optional. If you would like to require **Username**, you must collect the username and pass it to the `create()` method in your custom flow. For this guide, if you would like to use email OTP instead, require the **Email address** option instead of the **Phone number** option.
1. In the **Authentication strategies** section of this page, ensure **SMS verification code** is enabled. Ensure **Password** is toggled off, as you are prioritizing passwordless, SMS OTP-only authentication in this guide. If you would like to use email OTP instead, enable the **Email verification code** strategy instead of the **SMS verification code** strategy.
- ### Sign-up flow
+ ## Sign-up flow
To sign up a user using an OTP, you must:
@@ -306,7 +304,7 @@ This guide will walk you through how to build a custom SMS OTP sign-up and sign-
To create a sign-up flow for email OTP, use the [`prepareEmailAddressVerification`](/docs/references/javascript/sign-up/email-verification#prepare-email-address-verification) and [`attemptEmailAddressVerification`](/docs/references/javascript/sign-up/email-verification#attempt-email-address-verification). These helpers work the same way as their phone number counterparts do in the previous example. You can find all available methods in the [`SignUp`](/docs/references/javascript/sign-in/sign-in) object documentation.
- ### Sign-in flow
+ ## Sign-in flow
To authenticate a user with an OTP, you must:
diff --git a/docs/custom-flows/embedded-email-links.mdx b/docs/custom-flows/embedded-email-links.mdx
index a7c6a6a6e9..2af4535257 100644
--- a/docs/custom-flows/embedded-email-links.mdx
+++ b/docs/custom-flows/embedded-email-links.mdx
@@ -15,7 +15,7 @@ Common use cases include:
This guide will demonstrate how to generate a sign-in token and use it to sign in a user.
- ### Generate a sign-in token
+ ## Generate a sign-in token
[Sign-in tokens](/docs/reference/backend-api/tag/Sign-in-Tokens#operation/CreateSignInToken){{ target: '_blank' }} are JWTs that can be used to sign in to an application without specifying any credentials. A sign-in token can be used **once**, and can be consumed from the Frontend API using the [`ticket`](/docs/references/javascript/sign-in/sign-in#sign-in-create-params) strategy, which is demonstrated in the following example.
@@ -40,7 +40,7 @@ This guide will demonstrate how to generate a sign-in token and use it to sign i
Then, you can embed this link anywhere, such as an email.
- ### Build a custom flow for signing in with a sign-in token
+ ## Build a custom flow for signing in with a sign-in token
To handle email links with sign-in tokens, you must set up a page in your frontend that detects the token, signs the user in, and performs any additional actions you need.
diff --git a/docs/custom-flows/saml-connections.mdx b/docs/custom-flows/enterprise-connections.mdx
similarity index 64%
rename from docs/custom-flows/saml-connections.mdx
rename to docs/custom-flows/enterprise-connections.mdx
index e062065c88..dd0135cdb6 100644
--- a/docs/custom-flows/saml-connections.mdx
+++ b/docs/custom-flows/enterprise-connections.mdx
@@ -1,25 +1,25 @@
---
-title: Build a custom flow for authenticating with SAML connections
-description: Learn how to use the Clerk API to build a custom sign-up and sign-in flow that supports OAuth connections.
+title: Build a custom flow for authenticating with enterprise connections
+description: Learn how to use the Clerk API to build a custom sign-up and sign-in flow that supports enterprise connections.
---
## Before you start
-You must configure your application instance through the Clerk Dashboard for the SAML connection(s) that you want to use. Visit [the appropriate SAML guide for your platform](/docs/authentication/enterprise-connections/overview) to learn how to configure your instance.
+You must configure your application instance through the Clerk Dashboard for the enterprise connection(s) that you want to use. Visit [the appropriate guide for your platform](/docs/authentication/enterprise-connections/overview) to learn how to configure your instance.
## Create the sign-up and sign-in flow
-When using SAML, the sign-in and sign-up flows are equivalent. A successful SAML flow consists of the following steps:
+When using Enterprise SSO, the sign-in and sign-up flows are equivalent. A successful Enterprise SSO flow consists of the following steps:
-1. Start the SAML flow by calling [`SignIn.authenticateWithRedirect(params)`](/docs/references/javascript/sign-in/authenticate-with#authenticate-with-redirect) or [`SignUp.authenticateWithRedirect(params)`](/docs/references/javascript/sign-up/authenticate-with#authenticate-with-redirect). Both of these methods require a `redirectUrl` param, which is the URL that the browser will be redirected to once the user authenticates with the identity provider.
+1. Start the Enterprise SSO flow by calling [`SignIn.authenticateWithRedirect(params)`][sign-in-redirect] or [`SignUp.authenticateWithRedirect(params)`][sign-up-redirect]. Both of these methods require a `redirectUrl` param, which is the URL that the browser will be redirected to once the user authenticates with the identity provider.
1. Create a route at the URL that the `redirectUrl` param points to. The following example names this route `/sso-callback`. This route should either call the [`Clerk.handleRedirectCallback()`](/docs/references/javascript/clerk/handle-navigation#handle-redirect-callback) method or render the prebuilt [``](/docs/components/control/authenticate-with-callback) component.
The following example shows two files:
-1. The sign-in page where the user can start the SAML flow.
-1. The SSO callback page where the SAML flow is completed.
+1. The sign-in page where the user can start the Enterprise SSO flow.
+1. The SSO callback page where the flow is completed.
@@ -30,13 +30,13 @@ The following example shows two files:
import * as React from 'react'
import { useSignIn, useSignUp } from '@clerk/nextjs'
- export default function SAMLSignIn() {
+ export default function Page() {
const { signIn } = useSignIn()
const { signUp } = useSignUp()
if (!signIn || !signUp) return null
- const signInWithSAML = (e: React.FormEvent) => {
+ const signInWithEnterpriseSSO = (e: React.FormEvent) => {
e.preventDefault()
const email = (e.target as HTMLFormElement).email.value
@@ -44,7 +44,7 @@ The following example shows two files:
signIn
.authenticateWithRedirect({
identifier: email,
- strategy: 'saml',
+ strategy: 'enterprise_sso',
redirectUrl: '/sso-callback',
redirectUrlComplete: '/',
})
@@ -58,9 +58,9 @@ The following example shows two files:
}
return (
-
)
}
@@ -69,10 +69,10 @@ The following example shows two files:
```jsx {{ filename: 'app/sign-up/sso-callback/page.tsx' }}
import { AuthenticateWithRedirectCallback } from '@clerk/nextjs'
- export default function SSOCallback() {
+ export default function Page() {
// Handle the redirect flow by rendering the
// prebuilt AuthenticateWithRedirectCallback component.
- // This is the final step in the custom SAML flow.
+ // This is the final step in the custom Enterprise SSO flow.
return
}
```
@@ -80,13 +80,13 @@ The following example shows two files:
-## SAML account transfer flows
+## Enterprise account transfer flows
-It is common for users who are authenticating with SAML to use a sign-in button when they mean to sign-up, and vice versa. For those cases, the `SignIn` and `SignUp` objects have a `transferable` status that indicates whether the user can be transferred to the other flow.
+It is common for users who are authenticating with an enterprise account to use a sign-in button when they mean to sign-up, and vice versa. For those cases, the `SignIn` and `SignUp` objects have a `transferable` status that indicates whether the user can be transferred to the other flow.
**If you would like to keep your sign-in and sign-up flows completely separate, then you can skip this section.**
-The following example demonstrates how to handle these cases in your sign-in flow. To apply the same logic to the sign-up flow, simply replace `signIn.authenticateWithRedirect()` with `signUp.authenticateWithRedirect()` in your code.
+The following example demonstrates how to handle these cases in your sign-in flow. To apply the same logic to the sign-up flow, simply replace [`signIn.authenticateWithRedirect()`][sign-in-redirect] with [`signUp.authenticateWithRedirect()`][sign-up-redirect] in your code.
@@ -96,13 +96,13 @@ The following example demonstrates how to handle these cases in your sign-in flo
import * as React from 'react'
import { useSignIn, useSignUp } from '@clerk/nextjs'
- export default function SAMLSignIn() {
+ export default function Page() {
const { signIn } = useSignIn()
const { signUp, setActive } = useSignUp()
if (!signIn || !signUp) return null
- const signInWithSAML = (e: React.FormEvent) => {
+ const signInWithEnterpriseSSO = (e: React.FormEvent) => {
e.preventDefault()
const email = (e.target as HTMLFormElement).email.value
@@ -110,7 +110,7 @@ The following example demonstrates how to handle these cases in your sign-in flo
signIn
.authenticateWithRedirect({
identifier: email,
- strategy: 'saml',
+ strategy: 'enterprise_sso',
redirectUrl: '/sso-callback',
redirectUrlComplete: '/',
})
@@ -127,7 +127,7 @@ The following example demonstrates how to handle these cases in your sign-in flo
if (!signIn || !signUp) return null
// If the user has an account in your application, but does not yet
- // have a SAML account connected to it, you can transfer the SAML
+ // have a enterprise account connected to it, you can transfer the enterprise
// account to the existing user account.
const userExistsButNeedsToSignIn =
signUp.verifications.externalAccount.status === 'transferable' &&
@@ -143,9 +143,9 @@ The following example demonstrates how to handle these cases in your sign-in flo
}
}
- // If the user has a SAML account but does not yet
+ // If the user has a enterprise account but does not yet
// have an account in your app, you can create an account
- // for them using the SAML information.
+ // for them using the enterprise account's information.
const userNeedsToBeCreated = signIn.firstFactorVerification.status === 'transferable'
if (userNeedsToBeCreated) {
@@ -160,18 +160,22 @@ The following example demonstrates how to handle these cases in your sign-in flo
}
} else {
// If the user has an account in your application
- // and has an SAML account connected to it, you can sign them in.
- signInWithSAML(e)
+ // and has an enterprise account connected to it, you can sign them in.
+ signInWithEnterpriseSSO(e)
}
}
return (
)
}
```
+
+[sign-in-redirect]: /docs/references/javascript/sign-in/authenticate-with#authenticate-with-redirect
+
+[sign-up-redirect]: /docs/references/javascript/sign-up/authenticate-with#authenticate-with-redirect
diff --git a/docs/custom-flows/google-one-tap.mdx b/docs/custom-flows/google-one-tap.mdx
index 0023351877..d072ead81d 100644
--- a/docs/custom-flows/google-one-tap.mdx
+++ b/docs/custom-flows/google-one-tap.mdx
@@ -10,11 +10,11 @@ description: Learn how to build a custom Google One Tap authentication flow usin
This guide will walk you through how to build a custom Google One Tap authentication flow.
- ### Enable Google as a social connection
+ ## Enable Google as a social connection
To use Google One Tap with Clerk, follow the steps in the [dedicated guide](/docs/authentication/social-connections/google#configuring-google-social-connection) to configure Google as a social connection in the Clerk Dashboard using custom credentials.
- ### Create the Google One Tap authentication flow
+ ## Create the Google One Tap authentication flow
To authenticate users with Google One Tap, you must:
diff --git a/docs/custom-flows/manage-sms-based-mfa.mdx b/docs/custom-flows/manage-sms-based-mfa.mdx
index a3f45b5d15..34d75f7092 100644
--- a/docs/custom-flows/manage-sms-based-mfa.mdx
+++ b/docs/custom-flows/manage-sms-based-mfa.mdx
@@ -13,14 +13,14 @@ One of the options that Clerk supports for MFA is **SMS verification codes**. Th
> To learn how to build a custom flow for managing authenticator app (TOTP) MFA, see the [dedicated guide](/docs/custom-flows/manage-totp-based-mfa).
- ### Enable multi-factor authentication
+ ## Enable multi-factor authentication
For your users to be able to enable MFA for their account, you need to enable MFA as an MFA authentication strategy in your Clerk application.
1. In the Clerk Dashboard, navigate to the [**Multi-factor**](https://dashboard.clerk.com/last-active?path=user-authentication/multi-factor) page.
1. Enable **SMS verification code** and **Backup codes** and select **Save**.
- ### Create the multi-factor management flow
+ ## Create the multi-factor management flow
This example is written for Next.js App Router but it can be adapted for any React meta framework, such as Remix.
@@ -33,7 +33,7 @@ One of the options that Clerk supports for MFA is **SMS verification codes**. Th
- ```tsx {{ filename: '/app/account/manage-mfa/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/account/manage-mfa/page.tsx', collapsible: true }}
'use client'
import * as React from 'react'
@@ -222,7 +222,7 @@ One of the options that Clerk supports for MFA is **SMS verification codes**. Th
- ```tsx {{ filename: '/app/account/add-phone/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/account/add-phone/page.tsx', collapsible: true }}
'use client'
import * as React from 'react'
diff --git a/docs/custom-flows/manage-totp-based-mfa.mdx b/docs/custom-flows/manage-totp-based-mfa.mdx
index 5a08c5d936..9710cfe585 100644
--- a/docs/custom-flows/manage-totp-based-mfa.mdx
+++ b/docs/custom-flows/manage-totp-based-mfa.mdx
@@ -13,14 +13,15 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
> To learn how to build a custom flow for managing SMS MFA, see the [dedicated guide](/docs/custom-flows/manage-sms-based-mfa).
- ### Enable multi-factor authentication
+ ## Enable multi-factor authentication
For your users to be able to enable MFA for their account, you need to enable MFA as an MFA authentication strategy in your Clerk application.
1. In the Clerk Dashboard, navigate to the [**Multi-factor**](https://dashboard.clerk.com/last-active?path=user-authentication/multi-factor) page.
- 1. Enable **Authenticator application** and **Backup codes** and select **Save**.
+ 1. Enable **Authenticator application** and **Backup codes**.
+ 1. Select **Save**.
- ### Create the multi-factor management flow
+ ## Create the multi-factor management flow
@@ -35,7 +36,7 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
- ```tsx {{ filename: '/app/account/manage-mfa/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/account/manage-mfa/page.tsx', collapsible: true }}
'use client'
import * as React from 'react'
@@ -157,7 +158,7 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
- ```tsx {{ filename: '/app/account/manage-mfa/add/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/account/manage-mfa/add/page.tsx', collapsible: true }}
'use client'
import { useUser } from '@clerk/nextjs'
@@ -259,7 +260,7 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
}) {
return (
<>
-
Backup codes
+
Verification was a success!
Save this list of backup codes somewhere safe in case you need to access your account in
@@ -304,32 +305,80 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
```
+
+ ### Force MFA (optional)
+
+ While Clerk does not natively enforce MFA for all users, you can implement this functionality by using `clerkMiddleware()` to check whether a user has MFA enabled.
+
+ The following example demonstrates how to force MFA for all users. It uses `clerkMiddleware()` to intercept all requests and check whether a user has MFA enabled. If the user does not have MFA enabled, `clerkMiddleware()` redirects them to the `/mfa` page where they can set up MFA.
+
+ ```tsx {{ filename: 'middleware.ts', collapsible: true }}
+ import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
+ import { NextResponse } from 'next/server'
+
+ const isMFARoute = createRouteMatcher(['/account/manage-mfa/add(.*)'])
+ const isSignInRoute = createRouteMatcher(['/sign-in(.*)'])
+
+ export default clerkMiddleware(async (auth, req) => {
+ const { userId } = await auth()
+
+ // Redirect to homepage if the user is signed in and on the sign-in page
+ if (userId !== null && isSignInRoute(req) && !isMFARoute(req)) {
+ return NextResponse.redirect(new URL('/', req.url))
+ }
+
+ // Check if the user is signed in and not on the MFA page
+ if (userId !== null && !isMFARoute(req)) {
+ const res = await fetch(`https://api.clerk.com/v1/users/${userId}`, {
+ headers: {
+ Authorization: `Bearer ${process.env.CLERK_SECRET_KEY}`,
+ },
+ })
+
+ const userData = await res.json()
+
+ // Redirect to MFA setup page if MFA is not enabled
+ if (userData.two_factor_enabled === false) {
+ return NextResponse.redirect(new URL('/account/manage-mfa/add', req.url))
+ }
+ }
+ })
+
+ 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)(.*)',
+ ],
+ }
+ ```
### Before you start
- Install `expo-checkbox` for the UI and `@clerk/types` for type definitions.
+ Install `expo-checkbox` for the UI and `react-native-qr-svg` for the QR code.
```bash {{ filename: 'terminal' }}
- npm install expo-checkbox @clerk/types
+ npm install expo-checkbox react-native-qr-svg
```
```bash {{ filename: 'terminal' }}
- yarn add expo-checkbox @clerk/types
+ yarn add expo-checkbox react-native-qr-svg
```
```bash {{ filename: 'terminal' }}
- pnpm add expo-checkbox @clerk/types
+ pnpm add expo-checkbox react-native-qr-svg
```
### Build the flow
- To allow users to configure MFA, you will create a basic dashboard.
+ To allow users to configure their MFA settings, you'll create a basic dashboard.
- This example consists of three pages:
+ The following example consists of three pages:
- The layout page that checks if the user is signed in
- The page where users can manage their account, including their MFA settings
@@ -339,7 +388,8 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
- Start by creating the `(dashboard)` route group and adding the following code to the layout:
+ 1. Create the `(dashboard)` route group. This groups your account page and the "Add TOTP MFA" page.
+ 1. Create a `_layout.tsx` file with the following code. The [`useAuth()`](/docs/references/react/use-auth) hook is used to check if the user is signed in. If the user isn't signed in, they'll be redirected to the sign-in page.
```tsx {{ filename: 'app/(dashboard)/_layout.tsx' }}
import { Redirect, Stack } from 'expo-router'
@@ -358,16 +408,17 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
- Add a basic account page to the `(dashboard)` route group that shows users whether or not MFA is enabled, and allows them to add MFA with an authenticator app.
+ In the `(dashboard)` group, create an `account.tsx` file with the following code. This page shows users whether or not MFA is enabled, and allows them to add MFA with an authenticator app.
```tsx {{ filename: 'app/(dashboard)/account.tsx', collapsible: true }}
import React from 'react'
import { useUser } from '@clerk/clerk-expo'
- import { Link } from 'expo-router'
- import { View, Text, Button, TouchableOpacity, FlatList } from 'react-native'
+ import { useRouter } from 'expo-router'
+ import { View, Text, Button, FlatList } from 'react-native'
import { BackupCodeResource } from '@clerk/types'
export default function ManageTOTPMfa() {
+ const router = useRouter()
const [backupCodes, setBackupCodes] = React.useState(undefined)
const [loading, setLoading] = React.useState(false)
@@ -395,7 +446,7 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
const MFAEnabled = () => {
return (
-
+ TOTP via authentication app enabled -
@@ -404,13 +455,9 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
const MFADisabled = () => {
return (
-
+ Add TOTP via authentication app -
-
-
- Add
-
-
+
)
}
@@ -444,7 +491,7 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
- Create a page that adds the functionality for generating the QR code and backup codes.
+ In the `(dashboard)` group, create an `add-mfa.tsx` file with the following code. This page adds the functionality for generating the QR code and backup codes.
```tsx {{ filename: 'app/(dashboard)/add-mfa.tsx', collapsible: true }}
import React from 'react'
@@ -467,7 +514,7 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
void user
?.createTOTP()
.then((totp: TOTPResource) => setTotp(totp))
- .catch((error) => console.log('error', error))
+ .catch((err) => console.error(JSON.stringify(err, null, 2)))
}, [])
return (
@@ -507,13 +554,18 @@ One of the options that Clerk supports for MFA is **Authenticator applications (
await user
?.verifyTOTP({ code })
.then(() => setStep('backupcodes'))
- .catch((error) => console.log('Error', error))
+ .catch((err) => console.error(JSON.stringify(err, null, 2)))
}
return (
<>
Verify MFA
- setCode(c)} />
+ setCode(c)}
+ />
diff --git a/docs/custom-flows/sign-out.mdx b/docs/custom-flows/sign-out.mdx
index 0d8d4db267..732a57ebf8 100644
--- a/docs/custom-flows/sign-out.mdx
+++ b/docs/custom-flows/sign-out.mdx
@@ -12,7 +12,7 @@ The `signOut()` function signs a user out of all sessions in a [multi-session ap
> [!NOTE]
> The sign-out flow deactivates only the current session. Other valid sessions associated with the same user (e.g., if the user is signed in on another device) will remain active.
-
+
The [`useClerk()`](/docs/references/react/use-clerk) hook is used to access the `signOut()` function, which is called when the user clicks the sign-out button.
@@ -20,7 +20,7 @@ The `signOut()` function signs a user out of all sessions in a [multi-session ap
This example is written for Next.js App Router but can be adapted for any React meta framework, such as Remix.
- ```jsx {{ filename: '/app/components/SignOutButton.tsx' }}
+ ```jsx {{ filename: 'app/components/SignOutButton.tsx' }}
'use client'
import { useClerk } from '@clerk/nextjs'
@@ -77,6 +77,32 @@ The `signOut()` function signs a user out of all sessions in a [multi-session ap
+
+ ```jsx {{ filename: 'SignOutButton.tsx', collapsible: true }}
+ import { useClerk } from '@clerk/clerk-react'
+ import * as Linking from 'expo-linking'
+ import { Button } from 'react-native'
+
+ export const SignOutButton = () => {
+ const { signOut } = useClerk()
+
+ const handleSignOut = async () => {
+ try {
+ await signOut()
+ // Redirect to your desired page
+ Linking.openURL(Linking.createURL('/'))
+ } catch (err) {
+ // See https://clerk.com/docs/custom-flows/error-handling
+ // for more info on error handling
+ console.error(JSON.stringify(err, null, 2))
+ }
+ }
+
+ return
+ }
+ ```
+
+
```swift {{ filename: 'SignOutView.swift', collapsible: true }}
import SwiftUI
diff --git a/docs/custom-flows/user-impersonation.mdx b/docs/custom-flows/user-impersonation.mdx
index f314b944b7..2a159c172d 100644
--- a/docs/custom-flows/user-impersonation.mdx
+++ b/docs/custom-flows/user-impersonation.mdx
@@ -5,7 +5,7 @@ description: Learn how to build a custom flow using the Clerk API that handles u
-User impersonation is a way to offer customer support by logging into your application from their accounts. Doing so enables you to directly reproduce and remedy any issues they're experiencing.
+[Clerk's user impersonation feature](/docs/users/user-impersonation) allows you to sign in to your application as one of your users, enabling you to directly reproduce and remedy any issues they're experiencing. It's a helpful feature for customer support and debugging.
This guide will walk you through how to build a custom flow that handles user impersonation.
@@ -187,463 +187,261 @@ This guide will walk you through how to build a custom flow that handles user im
- ### Before you start
-
- > [!WARNING]
- > This example uses [`expo-router`](https://docs.expo.dev/router/installation/)'s **experimental** API routes for simplicity. However, you can use your own backend server to handle the API routes.
- >
- > To use Expo's experimental API routes, you must follow the [Expo deployment docs](https://docs.expo.dev/router/reference/api-routes/#deployment). Doing so allows your impersonation endpoints to access to your `CLERK_SECRET_KEY`.
-
- Install the following dependencies:
-
-
- ```bash {{ filename: 'terminal' }}
- npm i expo-linking @clerk/types
- ```
-
- ```bash {{ filename: 'terminal' }}
- yarn add expo-linking @clerk/types
- ```
-
- ```bash {{ filename: 'terminal' }}
- pnpm add expo-linking @clerk/types
- ```
-
-
- ### Build the flow
-
The following example creates a basic dashboard for impersonating users.
### Protect the dashboard route
> [!WARNING]
- > It is **recommended** that you should build impersonation into an admin-only dashboard that **only authorized users** can access.
+ > It is **recommended** that you build impersonation into a dashboard that **only authorized users** can access.
- The person visiting this dashboard should not be able to see it unless signed in. To protect the dashboard, create the `dashboard` route group with a layout that redirects users if they're already signed in, as shown in the following example:
+ 1. Create the `dashboard/` directory.
+ 1. In the `dashboard/` directory, create a `_layout.tsx` file with the following code. The [`useAuth()`](/docs/references/react/use-auth) hook is used to access the user's authentication state. If the user is already signed in, they'll be redirected to the home page. The [``](/docs/components/protect) component is used to ensure that only users with the `org:dashboard:access` permission can access it. You can modify the `permission` attribute to fit your use case.
- ```tsx {{ filename: 'app/(dashboard)/_layout.tsx' }}
+ ```tsx {{ filename: 'app/dashboard/_layout.tsx' }}
import { Redirect, Stack } from 'expo-router'
- import { useAuth } from '@clerk/clerk-expo'
+ import { Protect, useAuth } from '@clerk/clerk-expo'
+ import { Text } from 'react-native'
export default function GuestLayout() {
const { isSignedIn } = useAuth()
if (!isSignedIn) {
- return
+ return
}
- return
+ return (
+ You don't have the permissions to access the dashboard.}
+ >
+
+
+ )
}
```
- ### Create the dashboard UI
-
- Create the main page of the dashboard, which will hold most of your impersonation code. This example contains the skeleton of the final result, which will be fleshed out with each step in this guide. To skip the step-by-step process, see [the full example](#full-example) at the end of this guide.
-
- ```tsx {{ filename: 'app/(dashboard)/index.tsx' }}
- import React from 'react'
- import { Button, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
- import { Link, useRouter } from 'expo-router'
- import { useAuth, useUser, useSignIn, useSessionList } from '@clerk/clerk-expo'
- import { UserDataJSON } from '@clerk/types'
- import * as Linking from 'expo-linking'
- import useImpersonatedUser from '@/hooks/useImpersonatedUser'
- import useImpersonation from '@/hooks/useImpersonation'
+ ### Create an API route to generate actor tokens
- export default function Dashboard() {
- // This state will allow us to display some information about the current impersonator
- const [impersonator, setImpersonator] = React.useState('')
- // Our Clerk hooks provide us with variables and functions to handle our authentication flows
- const { signOut, actor } = useAuth()
- const { isLoaded, signIn, setActive } = useSignIn()
- const { user } = useUser()
- const { sessions } = useSessionList()
+ To sign in as a different user, you must supply an actor token when creating a session.
- // Using expo's router will allow us to navigate properly once we've newly authenticated
- const router = useRouter()
+ Create the `generateActorToken+api.tsx` file with the following code. This creates an API route that will call Clerk's Backend API [`/actor_tokens`](/docs/reference/backend-api/tag/Actor-Tokens#operation/CreateActorToken) endpoint to create an actor token.
- const actorRes = useImpersonation(actor?.sub || undefined, user?.id)
- const actorUserData = useImpersonatedUser(actor?.sub || '', setImpersonator)
+ ```tsx {{ filename: 'app/generateActorToken+api.tsx', collapsible: true }}
+ export async function POST(request: Request) {
+ const { actorId, userId } = await request.json()
- // Our actor endpoint will return a URL containing the ticket value we need to pass to our signIn method
- // This function will get fleshed out later in the doc
- function extractTicketValue() {}
+ try {
+ // Create an actor token using Clerk's Backend API
+ const res = await fetch('https://api.clerk.com/v1/actor_tokens', {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${process.env.CLERK_SECRET_KEY}`,
+ 'Content-type': 'application/json',
+ },
+ body: JSON.stringify({
+ user_id: userId,
+ actor: {
+ sub: actorId,
+ },
+ }),
+ })
- // `onSignoutPress` will determine which session we are attempting to sign out of and clear the session
- // This function will get fleshed out later in the doc
- async function onSignoutPress() {}
+ const data = await res.json()
- return (
-
-
- Account
-
- Hello {user?.firstName}
-
- {sessions?.map((sesh) => (
- onSignOutPress(sesh.id)} key={sesh.id}>
- Sign out of {sesh?.user?.primaryEmailAddress?.emailAddress}
-
- ))}
-
- {actorRes && await impersonateUser()} />}
-
- )
+ return Response.json(data)
+ } catch (err) {
+ return Response.json({ error: 'Failed to generate actor token' }, { status: 500 })
+ }
}
```
- ### Create a hook to generate an actor token
+ ### Create a hook to get users
- Create a custom hook called `useImpersonation()` that will call an API route to generate and return an actor token from Clerk.
+ To impersonate a user, you need a list of your application's users to be able to select one for impersonation.
- ```tsx {{ filename: 'hooks/useImpersonation.tsx' }}
- import { useState, useEffect } from 'react'
+ 1. Create the `hooks/` directory.
+ 1. In the `hooks/` directory, create the `useUsers.tsx` file with the following code. This creates a hook that will fetch the list of your application's users.
- // This is the entire return type for actor token generation,
- // Though we are only using a couple of the properties in the example
- export type Actor = {
- object: string
- id: string
- status: 'pending' | 'accepted' | 'revoked'
- user_id: string
- actor: object
- token: string | null
- url: string | null
- created_at: Number
- updated_at: Number
+ ```tsx {{ filename: 'app/hooks/useUsers.tsx', collapsible: true }}
+ import { UserJSON } from '@clerk/types'
+ import { useEffect, useState } from 'react'
+
+ type UseUsersReturn = {
+ users: UserJSON[] | null
+ isLoading: boolean
+ error: Error | null
}
- export default function useImpersonation(actorId: string | undefined, userId: string | undefined) {
- const [actor, setActor] = useState()
+ /**
+ * Returns a list of users for the application.
+ *
+ * Until the users are fetched, `isLoading` will be set to `true`.
+ *
+ * @example
+ *
+ * import { useUsers } from '@/app/hooks/useUsers';
+ *
+ * function Hello() {
+ * const { users, isLoading, error } = useUsers();
+ * if(isLoading) {
+ * return
+ * }
+ */
+ export default function useUsers(): UseUsersReturn {
+ const [users, setUsers] = useState(null)
+ const [isLoading, setIsLoading] = useState(true)
+ const [error, setError] = useState(null)
useEffect(() => {
- async function generateAndSetToken() {
- if (typeof actorId !== 'string') {
- const res = await fetch('/generateActorToken', {
- method: 'POST',
- body: JSON.stringify({
- // This is the user ID of the use you're going to impersonate
- user_id: userId,
- actor: {
- // This is the ID of the impersonator
- sub: actorId,
- },
- }),
- })
-
+ const getUsers = async () => {
+ try {
+ const res = await fetch('/getUsers')
+ if (!res.ok) {
+ throw new Error('Failed to fetch users')
+ }
const data = await res.json()
-
- setActor(data)
+ setUsers(data)
+ } catch (err) {
+ setError(err instanceof Error ? err : new Error('Unknown error'))
+ } finally {
+ setIsLoading(false)
}
}
- generateAndSetToken()
- }, [])
+ getUsers()
+ }, []) // Remove users from dependency array to prevent infinite loop
- return actor
+ return { users, isLoading, error }
}
```
- ### Create an API route to generate actor tokens
-
- Now create an endpoint that will call the [create actor token](/docs/reference/backend-api/tag/Actor-Tokens#operation/CreateActorToken) endpoint at `/actor_tokens` and pass in the Clerk Secret Key for authorization. In your API, you should build in permission checks to make sure this is only being accessed from a trusted source.
-
- ```tsx {{ filename: 'app/generateActorToken+api.tsx' }}
- export async function POST(request: Request) {
- const body: { user_id: string; actor: { sub: string } } = await request.json()
+ ### Create the dashboard UI
- const { user_id, actor } = body
+ 1. In the `dashboard/` directory, create the `index.tsx` file with the following code. This creates the UI for the dashboard, which displays a list of users and allows you to impersonate one.
- const res = await fetch('https://api.clerk.com/v1/actor_tokens', {
- method: 'POST',
- headers: {
- Authorization: `Bearer ${process.env.CLERK_SECRET_KEY}`,
- 'Content-type': 'application/json',
- },
- body: JSON.stringify({
- user_id,
- actor: {
- sub: actor.sub,
- },
- }),
- })
+ ```tsx {{ filename: 'app/dashboard/index.tsx', collapsible: true }}
+ import React, { useState } from 'react'
+ import { Button, Text, View } from 'react-native'
+ import { useRouter } from 'expo-router'
+ import { useUser, useSignIn } from '@clerk/clerk-expo'
+ import useUsers from '../hooks/useUsers'
- const data = await res.json()
+ export default function Dashboard() {
+ const [error, setError] = useState(null)
- return Response.json(data)
- }
- ```
+ const { isLoaded, signIn, setActive } = useSignIn()
+ const { user } = useUser()
+ const router = useRouter()
+ const { users, isLoading } = useUsers()
- ### Create a hook to get impersonated user data
+ if (!user?.id) return null
- Create a second custom hook called `useImpersonatedUser()` that will fetch data about the impersonator. You can use this to display UI only the impersonator will see for specific actions, like showing who is currently impersonating and matching the session to the right user for logout.
+ // Create an actor token for the impersonation
+ async function createActorToken(actorId: string, userId: string) {
+ setError(null)
- ```tsx {{ filename: 'hooks/useImpersonatedUser.tsx' }}
- function useImpersonatedUser(
- actorSub: string,
- setImpersonator: React.Dispatch>,
- ) {
- React.useEffect(() => {
- const getImpersonatedUser = async () => {
- const res = await fetch(`/getImpersonatedUser`, {
+ try {
+ const res = await fetch('/generateActorToken', {
method: 'POST',
body: JSON.stringify({
- impersonator_id: actorSub,
+ actorId,
+ userId,
}),
})
const data = await res.json()
- setImpersonator(data)
+ if (data.errors) {
+ setError(data.errors[0].long_message)
+ return null
+ }
- getImpersonatedUser()
+ return data.token
+ } catch (err) {
+ setError('Failed to generate actor token')
+ return null
}
- }, [actorSub])
- }
- ```
-
- ### Create an API route to retrieve user data
-
- With your hook setup you can now create an API route that will call the [retrieve user endpoint](/docs/reference/backend-api/tag/Users#operation/GetUserList){{ target: '_blank' }} at `/users` and get back the Impersonated user's full [`User` object](/docs/references/javascript/user/user#user-object).
-
- ```tsx {{ filename: 'app/getImpersonatedUser+api.tsx' }}
- export async function POST(request: Request) {
- const body: { impersonator_id: string } = await request.json()
-
- const { impersonator_id } = body
- const res = await fetch(`https://api.clerk.com/v1/users/${impersonator_id}`, {
- headers: {
- Authorization: `Bearer ${process.env.CLERK_SECRET_KEY}`,
- },
- })
- const data = await res.json()
-
- return Response.json(data)
- }
- ```
-
- ### Create functions to generate an impersonated session
-
- Now that you have the functionality for generating an impersonated session & getting the impersonated user's data, there are a few more functions to complete that will:
-
- 1. Get the `ticket` from the URL generated by your `useImpersonation()` hook.
- 1. Pass the `ticket` to the `signIn()` function to create a new impersonated session, allowing you to sign in the impersonated user or impersonator.
-
- The following code should be placed in the `Page` component of your `app/(dashboard)/index.tsx` file:
-
- ```tsx {{ filename: 'app/(dashboard)/index.tsx' }}
- // Use this function to get the ticket ID from the response of our generateActorToken API
- function extractTicketValue(input: string): string | undefined {
- const index = input.indexOf('ticket=')
- if (index !== -1) {
- return input.slice(index + 7)
}
- return undefined
- }
- // Passing the ticket ID to our `signIn.create` function will create a new impersonated session that we can set to the active session
- async function impersonateUser() {
- if (!isLoaded) return
+ // Handle "Impersonate" button click
+ async function impersonateUser(actorId: string, userId: string) {
+ setError(null)
+ if (!isLoaded) return
- if (typeof actorRes?.url === 'string') {
- const ticket = extractTicketValue(actorRes.url)
+ // Calls your /generateActorToken API route
+ const actorToken = await createActorToken(actorId, userId)
- if (ticket) {
+ // Sign in as the impersonated user
+ if (actorToken) {
try {
const { createdSessionId } = await signIn.create({
strategy: 'ticket',
- ticket,
+ ticket: actorToken,
})
await setActive({ session: createdSessionId })
- await user?.reload()
- router.replace('/dashboard')
+ router.push('/')
} catch (err) {
+ setError('Failed to impersonate user')
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}
}
- }
- ```
-
- ### Create a hook for signing out
-
- Finally, create a helper function for signing out. Usually this can be as simple as calling the [`signOut()`](/docs/references/javascript/clerk/clerk#sign-out) function, but since you're handling multiple sessions, you must add some checks to ensure you're signing out of the right session.
-
- ```tsx {{ filename: 'app/(dashboard)/index.tsx' }}
- const onSignOutPress = async (sessionId: string) => {
- try {
- if (isLoaded && sessions && sessions?.length > 0) {
- const noActiveSessions = sessions.filter((session) => session.user?.id !== user?.id)
- await setActive({ session: noActiveSessions[0].id })
- }
- const redirectUrl = Linking.createURL('/dashboard', { scheme: 'myapp' })
- await signOut({
- sessionId,
- })
- router.replace(redirectUrl)
- } catch (err: any) {
- // See https://clerk.com/docs/custom-flows/error-handling
- // for more info on error handling
- console.error(JSON.stringify(err, null, 2))
- }
- }
- ```
-
- ### Full example
-
- The full code for the dashboard page will resemble the following, excluding the API routes:
-
- ```tsx {{ filename: 'app/(dashboard)/index.tsx' }}
- import React from 'react'
- import { Button, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
- import { Link, useRouter } from 'expo-router'
- import { useAuth, useUser, useSignIn, useSessionList } from '@clerk/clerk-expo'
- import { UserDataJSON } from '@clerk/types'
- import * as Linking from 'expo-linking'
-
- export type Actor = {
- object: string
- id: string
- status: 'pending' | 'accepted' | 'revoked'
- user_id: string
- actor: object
- token: string | null
- url: string | null
- created_at: Number
- updated_at: Number
- }
-
- function useImpersonation(actorId: string | undefined, userId: string | undefined) {
- const [actor, setActor] = React.useState()
- React.useEffect(() => {
- async function generateAndSetToken() {
- if (typeof actorId !== 'string') {
- const res = await fetch('/generateActorToken', {
- method: 'POST',
- body: JSON.stringify({
- user_id: userId, // This is the user ID of the use you're going to impersonate,
- actor: {
- sub: actorId, // This is the ID of the impersonator,
- },
- }),
- })
-
- const data = await res.json()
-
- setActor(data)
- }
- }
-
- generateAndSetToken()
- }, [])
-
- return actor
- }
-
- function useImpersonatedUser(
- actorSub: string,
- setImpersonator: React.Dispatch>,
- ) {
- React.useEffect(() => {
- const getImpersonatedUser = async () => {
- const res = await fetch(`/getImpersonatedUser`, {
- method: 'POST',
- body: JSON.stringify({
- impersonator_id: actorSub,
- }),
- })
-
- const data = await res.json()
-
- setImpersonator(data)
-
- getImpersonatedUser()
- }
- }, [actorSub])
- }
-
- export default function Page() {
- const [impersonator, setImpersonator] = React.useState('')
- const { signOut, actor } = useAuth()
- const { isLoaded, signIn, setActive } = useSignIn()
- const { user } = useUser()
- const router = useRouter()
- const { sessions } = useSessionList()
-
- const actorRes = useImpersonation(actor?.sub || undefined, user?.id)
- const actorUserData = useImpersonatedUser(actor?.sub || '', setImpersonator)
-
- function extractTicketValue(input: string): string | undefined {
- const index = input.indexOf('ticket=')
- if (index !== -1) {
- return input.slice(index + 7)
- }
- return undefined
- }
-
- async function impersonateUser() {
- if (!isLoaded) return
-
- if (typeof actorRes?.url === 'string') {
- const ticket = extractTicketValue(actorRes.url)
-
- if (ticket) {
- try {
- const { createdSessionId } = await signIn.create({
- strategy: 'ticket',
- ticket,
- })
-
- await setActive({ session: createdSessionId })
- await user?.reload()
-
- router.replace('/dashboard')
- } catch (err) {
- // See https://clerk.com/docs/custom-flows/error-handling
- // for more info on error handling
- console.error(JSON.stringify(err, null, 2))
- }
- }
- }
- }
-
- const onSignOutPress = async (sessionId: string) => {
- try {
- if (isLoaded && sessions && sessions?.length > 0) {
- const noActiveSessions = sessions.filter((session) => session.user?.id !== user?.id)
- await setActive({ session: noActiveSessions[0].id })
- }
- const redirectUrl = Linking.createURL('/dashboard', { scheme: 'myapp' })
- await signOut({
- sessionId,
- })
- router.replace(redirectUrl)
- } catch (err: any) {
- // See https://clerk.com/docs/custom-flows/error-handling
- // for more info on error handling
- console.error(JSON.stringify(err, null, 2))
- }
- }
return (
-
- Account
-
- Hello {user?.firstName}
-
- {sessions?.map((sesh) => (
- onSignOutPress(sesh.id)} key={sesh.id}>
- Sign out of {sesh?.user?.primaryEmailAddress?.emailAddress}
-
- ))}
-
- {actorRes && await impersonateUser()} />}
+
+ Welcome to the dashboard, {user?.firstName}!
+
+ Your user ID is {user?.id}
+
+ {isLoading && Loading your users...}
+
+ {!isLoading && users && (
+
+
+ User ID
+ Email ID
+ First Name
+ Actions
+
+ {users.map((userFromList) => {
+ const primaryEmail = userFromList.email_addresses?.find(
+ (email) => email.id === userFromList.primary_email_address_id,
+ )
+ return (
+
+ {userFromList.id}
+ {primaryEmail?.id || 'N/A'}
+ {userFromList.first_name || 'N/A'}
+
+ {/* Don't allow impersonation of yourself */}
+ {userFromList.id !== user.id ? (
+ await impersonateUser(user.id, userFromList.id)}
+ />
+ ) : (
+ You cannot impersonate yourself
+ )}
+
+
+ )
+ })}
+
+ )}
+
+ {error && (
+
+ {error}
+
+ )}
)
}
diff --git a/docs/customization/account-portal/getting-started.mdx b/docs/customization/account-portal/getting-started.mdx
index 7a657908ec..b695c7cb86 100644
--- a/docs/customization/account-portal/getting-started.mdx
+++ b/docs/customization/account-portal/getting-started.mdx
@@ -20,6 +20,7 @@ For development environments, Clerk will issue you a randomly generated domain o
https://accounts..com/sign-in
https://accounts..com/sign-up
https://accounts..com/user
+https://accounts..com/unauthorized-sign-in
https://accounts..com/organization
https://accounts..com/create-organization
```
diff --git a/docs/customization/account-portal/overview.mdx b/docs/customization/account-portal/overview.mdx
index 79fee3b8d6..f5287b11f9 100644
--- a/docs/customization/account-portal/overview.mdx
+++ b/docs/customization/account-portal/overview.mdx
@@ -52,6 +52,14 @@ The user profile page hosts the prebuilt [``](/docs/components/us
Redirect your authenticated users to their user profile page using the [``](/docs/components/control/redirect-to-userprofile) control component.
+### Unauthorized sign-in
+
+The unauthorized sign-in page doesn't host any prebuilt Clerk component. It displays a UI confirming that a session from an unrecognized device was successfully revoked. For more information, see the [Unauthorized sign-in](/docs/security/unauthorized-sign-in) feature.
+
+The unauthorized sign-in page displays a UI confirming that a session from an unrecognized device was successfully revoked. For more information, refer to [the reference.](/docs/security/unauthorized-sign-in)
+
+![Clerk's Account Portal unauthorized sign-in page](/docs/images/account-portal/unauthorized-sign-in.png)
+
### Create organization
The create organization page hosts the prebuilt [``](/docs/components/organization/create-organization) component, which provides a streamlined interface for users to create new organizations within your application.
diff --git a/docs/customization/elements/examples/shadcn-ui.mdx b/docs/customization/elements/examples/shadcn-ui.mdx
index 33b2a88753..94a33ba20c 100644
--- a/docs/customization/elements/examples/shadcn-ui.mdx
+++ b/docs/customization/elements/examples/shadcn-ui.mdx
@@ -55,7 +55,7 @@ You must also configure the appropriate settings in Clerk:
},
]}
>
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
import * as SignUp from '@clerk/elements/sign-up'
@@ -321,7 +321,7 @@ You must also configure the appropriate settings in Clerk:
},
]}
>
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
import * as SignIn from '@clerk/elements/sign-in'
diff --git a/docs/customization/elements/examples/sign-in.mdx b/docs/customization/elements/examples/sign-in.mdx
index 0180ae75a2..e82ef39ba6 100644
--- a/docs/customization/elements/examples/sign-in.mdx
+++ b/docs/customization/elements/examples/sign-in.mdx
@@ -26,7 +26,7 @@ Before you build your sign-in flow, you need to configure the appropriate settin
}
]}
>
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -127,7 +127,7 @@ Before you build your sign-in flow, you need to configure the appropriate settin
}
]}
>
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -222,7 +222,7 @@ Before you build your sign-in flow, you need to configure the appropriate settin
}
]}
>
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -382,7 +382,7 @@ Before you build your sign-in flow, you need to configure the appropriate settin
}
]}
>
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
diff --git a/docs/customization/elements/examples/sign-up.mdx b/docs/customization/elements/examples/sign-up.mdx
index 8ade4df375..6f2ee7add0 100644
--- a/docs/customization/elements/examples/sign-up.mdx
+++ b/docs/customization/elements/examples/sign-up.mdx
@@ -25,7 +25,7 @@ Before you build your sign-up flow, you need to configure the appropriate settin
}
]}
>
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -175,7 +175,7 @@ Before you build your sign-up flow, you need to configure the appropriate settin
}
]}
>
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', collapsible: true }}
'use client'
import * as Clerk from '@clerk/elements/common'
diff --git a/docs/customization/elements/guides/sign-in.mdx b/docs/customization/elements/guides/sign-in.mdx
index 89c63d39af..003a318b7d 100644
--- a/docs/customization/elements/guides/sign-in.mdx
+++ b/docs/customization/elements/guides/sign-in.mdx
@@ -34,11 +34,11 @@ description: Learn how to build a complete sign-in form with Clerk Elements.
> - Clerk Elements currently only works with Next.js App Router and [Clerk Core 2](/changelog/2024-04-19){{ target: '_blank' }}. As it gets closer to a stable release, support for additional frameworks will be added.
- ### Add a sign-in route
+ ## Add a sign-in route
Create a new route in your Next.js application. The route needs to be an [optional catch-all route](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) so the sign-in flow can handled nested paths, as shown in the following example:
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx' }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx' }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -54,11 +54,11 @@ description: Learn how to build a complete sign-in form with Clerk Elements.
> [!TIP]
> If you're getting TypeScript errors on the `@clerk/elements` imports you probably have forgotten to set your [`moduleResolution`](https://www.typescriptlang.org/tsconfig/#moduleResolution) in `tsconfig.json` to `bundler`.
- ### Add the start step
+ ## Add the start step
The Clerk authentication flows are made up of **steps**. Steps handle rendering the UI for each part of the flow. To allow users to create a sign-in attempt, the `start` step needs to be rendered. The following example does so with the `` component:
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', mark: [[9, 11]] }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', mark: [[9, 11]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -75,11 +75,11 @@ description: Learn how to build a complete sign-in form with Clerk Elements.
}
```
- ### Add form fields
+ ## Add form fields
Make it functional by adding input fields. The following example uses the `` component to render an `identifier` field, as well as the `` component to allow users to sign in with a social connection, like Google:
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', mark: [[12, 20]] }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', mark: [[12, 20]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -111,13 +111,13 @@ description: Learn how to build a complete sign-in form with Clerk Elements.
> [!NOTE]
> If your Clerk instance supports signing in with Google and doesn't require multi-factor authentication (MFA), you should be able to complete a sign-in with the components rendered so far.
- ### Add verification
+ ## Add verification
As users progress through a sign-in attempt, they may be asked to **verify** a number of authentication factors in the `verifications` step. You can render a form for the user to complete verification, but each [verification strategy](/docs/customization/elements/reference/sign-in#strategy) requires different fields. You must render the form fields conditionally for each authentication strategy your instance supports using the `` component.
The following example demonstrates how to conditionally render a form for the `email_code` strategy:
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', mark: [[23, 38]] }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', mark: [[23, 38]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -163,11 +163,11 @@ description: Learn how to build a complete sign-in form with Clerk Elements.
Verification is the final step in the sign-in flow. When a user has verified all required factors, the sign-in attempt will be complete and they will be signed in.
- ### Add password support
+ ## Add password support
If your instance is configured to support authenticating with passwords, you must add a few additional steps and verification strategies. You can choose if you want to support providing a password in the `start` step with an additional field, or as an additional verification strategy. For this guide, add it as a standalone verification strategy.
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', mark: [[39, 65], [68, 94]] }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', mark: [[39, 65], [68, 94]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -276,7 +276,7 @@ description: Learn how to build a complete sign-in form with Clerk Elements.
> [!NOTE]
> If your instance isn't configured to use passwords, or any of the strategies outlined here, Clerk Elements will log a warning to the console during development.
- ### Customize and add styling
+ ## Customize and add styling
Learn how to style your Clerk Elements components with the [styling guide](/docs/customization/elements/guides/styling).
diff --git a/docs/customization/elements/guides/sign-up.mdx b/docs/customization/elements/guides/sign-up.mdx
index 5aed014cf7..85e41b892d 100644
--- a/docs/customization/elements/guides/sign-up.mdx
+++ b/docs/customization/elements/guides/sign-up.mdx
@@ -34,11 +34,11 @@ description: Learn how to build a complete sign-up form with Clerk Elements.
> - Clerk Elements currently only works with Next.js App Router and [Clerk Core 2](/changelog/2024-04-19){{ target: '_blank' }}. As it gets closer to a stable release, support for additional frameworks will be added.
- ### Add a sign-up route
+ ## Add a sign-up route
Create a new route in your Next.js application. The route needs to be an [optional catch-all route](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) so the sign-up flow can handled nested paths, as shown in the following example:
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx' }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx' }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -54,11 +54,11 @@ description: Learn how to build a complete sign-up form with Clerk Elements.
> [!TIP]
> If you're getting TypeScript errors on the `@clerk/elements` imports you probably have forgotten to set your [`moduleResolution`](https://www.typescriptlang.org/tsconfig/#moduleResolution) in `tsconfig.json` to `bundler`.
- ### Add the start step
+ ## Add the start step
The Clerk authentication flows are made up of **steps**. Steps handle rendering the UI for each part of the flow. To allow users to create a sign-up attempt, the `start` step needs to be rendered. The following example does so with the `` component:
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', mark: [[9, 11]] }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', mark: [[9, 11]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -75,11 +75,11 @@ description: Learn how to build a complete sign-up form with Clerk Elements.
}
```
- ### Add form fields
+ ## Add form fields
Make it functional by adding input fields. The following example uses the `` component to render the `emailAddress` and `username` fields, as well as the `` component to allow users to sign up with a social connection, like Google:
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', mark: [[12, 34]] }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', mark: [[12, 34]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -122,13 +122,13 @@ description: Learn how to build a complete sign-up form with Clerk Elements.
`` takes care of wiring up the input with the label element, and `` will render any field-specific errors that get returned from Clerk's API. The `` component provides common actions that are used throughout the flows. In this case, using the `submit` action to render a submit button for the start form.
- ### Add verification
+ ## Add verification
As users progress through a sign-up attempt, they may be asked to **verify** a number of authentication factors in the `verifications` step. You can render a form for the user to complete verification, but each [verification strategy](/docs/customization/elements/reference/sign-in#strategy) requires different fields. You must render the form fields conditionally for each authentication strategy your instance supports using the `` component.
The following example demonstrates how to conditionally render a form for the `phone_code` and `email_code` strategies:
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', mark: [[35, 59]] }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', mark: [[35, 59]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -195,11 +195,11 @@ description: Learn how to build a complete sign-up form with Clerk Elements.
Verification is the final step in the sign-up flow. When a user has verified all required factors, the sign-up attempt will be complete, their account will be created, and they will be signed in.
- ### Accept additional fields
+ ## Accept additional fields
Should a user attempt to sign up via Google while a username is a required field, the `continue` step will be necessary to accept the username. The `` component will display any additional required fields.
- ```tsx {{ filename: '/app/sign-up/[[...sign-up]]/page.tsx', mark: [[35, 45]] }}
+ ```tsx {{ filename: 'app/sign-up/[[...sign-up]]/page.tsx', mark: [[35, 45]] }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -281,7 +281,7 @@ description: Learn how to build a complete sign-up form with Clerk Elements.
> [!NOTE]
> Under the hood, Clerk Elements will conditionally render the fields that are necessary to complete the sign up attempt, so there's no need to check the state of the sign up attempt yourself.
- ### Customize and add styling
+ ## Customize and add styling
Learn how to style your Clerk Elements components with the [styling guide](/docs/customization/elements/guides/styling).
diff --git a/docs/customization/elements/guides/styling.mdx b/docs/customization/elements/guides/styling.mdx
index 17aa48d8b8..2f20fb060f 100644
--- a/docs/customization/elements/guides/styling.mdx
+++ b/docs/customization/elements/guides/styling.mdx
@@ -13,7 +13,7 @@ You can style Clerk Elements components with the following props:
This guide will demonstrate multiple different styling approaches using the following basic sign-in flow as a starting point:
-```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx' }}
+```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx' }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -50,7 +50,7 @@ export default function SignInPage() {
If you are already using [Tailwind CSS](https://tailwindcss.com/), no additional setup is required. Classes from Tailwind can be applied to most Clerk Elements components. Use your editor's IntelliSense to see if `className` is a valid prop on a component you want to style.
-```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx' }}
+```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx' }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -97,7 +97,7 @@ export default function SignInPage() {
Many of the Clerk Elements components accept an `asChild` prop that allows you to swap out the rendered element. This is useful if you have an existing design system or component library that you wish to use with Clerk Elements.
-```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx' }}
+```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx' }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -161,7 +161,7 @@ const CustomInput = forwardRef(function CustomInput(props, forwardedRef) {
Classes from an imported CSS module can be applied to most Clerk Elements components with `className`.
-```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx' }}
+```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx' }}
'use client'
import * as Clerk from '@clerk/elements/common'
@@ -205,7 +205,7 @@ export default function SignInPage() {
You can also use inline styles with Clerk Elements. This is useful when you need to apply styles conditionally or avoid creating a separate CSS file.
-```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx' }}
+```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx' }}
'use client'
import * as Clerk from '@clerk/elements/common'
diff --git a/docs/customization/elements/reference/sign-in.mdx b/docs/customization/elements/reference/sign-in.mdx
index 0dae331b7c..0594c731ef 100644
--- a/docs/customization/elements/reference/sign-in.mdx
+++ b/docs/customization/elements/reference/sign-in.mdx
@@ -166,7 +166,7 @@ Conditionally renders its children depending on the authentication strategy that
- `name`
- - 'saml' | 'ticket' | 'password' | 'passkey' | 'phone\_code' | 'email\_code' | 'web3\_metamask\_signature' | 'web3\_coinbase\_wallet\_signature' | 'reset\_password\_email\_code' | 'reset\_password\_phone\_code' | 'email\_link' | 'totp' | 'backup\_code' | 'oauth' | 'web3' | [OAuthStrategy](https://github.com/clerk/javascript/blob/956d8792fefe9d6a89022f1e938149b25503ec7f/packages/types/src/strategies.ts#L15)
+ - 'saml' | 'ticket' | 'password' | 'passkey' | 'phone\_code' | 'email\_code' | 'web3\_metamask\_signature' | 'web3\_coinbase\_wallet\_signature' | 'web3\_okx\_wallet\_signature' | 'reset\_password\_email\_code' | 'reset\_password\_phone\_code' | 'email\_link' | 'totp' | 'backup\_code' | 'oauth' | 'web3' | [OAuthStrategy](https://github.com/clerk/javascript/blob/956d8792fefe9d6a89022f1e938149b25503ec7f/packages/types/src/strategies.ts#L15)
The name of the strategy for which its children will be rendered.
@@ -200,7 +200,7 @@ Renders a button that will change the current strategy that needs to be verified
- `name`
- - `'email_code' | 'email_link' | 'password' | 'passkey' | 'phone_code' | 'reset_password_email_code' | 'reset_password_phone_code' | 'web3_metamask_signature' | 'web3_coinbase_wallet_signature'`
+ - `'email_code' | 'email_link' | 'password' | 'passkey' | 'phone_code' | 'reset_password_email_code' | 'reset_password_phone_code' | 'web3_metamask_signature' | 'web3_coinbase_wallet_signature' | 'web3_okx_wallet_signature'`
The name of the strategy to switch to.
diff --git a/docs/customization/organization-profile.mdx b/docs/customization/organization-profile.mdx
index 2c9576c876..3d51ea668c 100644
--- a/docs/customization/organization-profile.mdx
+++ b/docs/customization/organization-profile.mdx
@@ -65,7 +65,7 @@ To add a custom page to the `` component, use the `` or `` component: as a component or as a direct child.
", "Dedicated page"]}>
- ```tsx {{ filename: '/app/components/Header.tsx' }}
+ ```tsx {{ filename: 'app/components/Header.tsx' }}
'use client'
import { OrganizationSwitcher } from '@clerk/nextjs'
@@ -117,7 +117,7 @@ The following example demonstrates two ways that you can render content in the `
export default Header
```
- ```tsx {{ filename: '/app/organization-profile/[[...organization-profile]]/page.tsx' }}
+ ```tsx {{ filename: 'app/organization-profile/[[...organization-profile]]/page.tsx' }}
'use client'
import { OrganizationProfile } from '@clerk/nextjs'
@@ -247,7 +247,7 @@ You can add external links to the `` navigation sidebar u
The following example adds a link to the homepage in the navigation sidebar of the `` component.
", "Dedicated page"]}>
- ```tsx {{ filename: '/app/components/Header.tsx' }}
+ ```tsx {{ filename: 'app/components/Header.tsx' }}
'use client'
import { OrganizationSwitcher } from '@clerk/nextjs'
@@ -275,7 +275,7 @@ The following example adds a link to the homepage in the navigation sidebar of t
export default Header
```
- ```tsx {{ filename: '/app/organization-profile/[[...organization-profile]]/page.tsx' }}
+ ```tsx {{ filename: 'app/organization-profile/[[...organization-profile]]/page.tsx' }}
'use client'
import { OrganizationProfile } from '@clerk/nextjs'
@@ -306,7 +306,7 @@ Note that when reordering default routes, the first item in the navigation sideb
", "Dedicated Page"]}>
- ```tsx {{ filename: '/app/components/Header.tsx' }}
+ ```tsx {{ filename: 'app/components/Header.tsx' }}
'use client'
import { OrganizationSwitcher } from '@clerk/nextjs'
@@ -358,7 +358,7 @@ Note that when reordering default routes, the first item in the navigation sideb
In the following example, `path` is set to `/organization-profile`, so the `` is rendered under the `/organization-profile` path.
- ```tsx {{ filename: '/app/organization-profile/[[...organization-profile]]/page.tsx' }}
+ ```tsx {{ filename: 'app/organization-profile/[[...organization-profile]]/page.tsx' }}
'use client'
import { OrganizationProfile } from '@clerk/nextjs'
diff --git a/docs/customization/themes.mdx b/docs/customization/themes.mdx
index c9a3b5bf6f..650029a450 100644
--- a/docs/customization/themes.mdx
+++ b/docs/customization/themes.mdx
@@ -490,7 +490,7 @@ To apply a theme to a single Clerk component, pass the `appearance` prop to the
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', mark: [2, [7, 9]] }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', mark: [2, [7, 9]] }}
import { SignIn } from '@clerk/nextjs'
import { dark } from '@clerk/themes'
diff --git a/docs/customization/user-profile.mdx b/docs/customization/user-profile.mdx
index 4cd67fe367..1fc4d377b3 100644
--- a/docs/customization/user-profile.mdx
+++ b/docs/customization/user-profile.mdx
@@ -65,7 +65,7 @@ The following example demonstrates two ways that you can render content in the `
", "Dedicated page"]}>
- ```tsx {{ filename: '/app/page.tsx' }}
+ ```tsx {{ filename: 'app/page.tsx' }}
'use client'
import { UserButton } from '@clerk/nextjs'
@@ -109,7 +109,7 @@ The following example demonstrates two ways that you can render content in the `
}
```
- ```tsx {{ filename: '/app/user-profile/[[...user-profile]]/page.tsx' }}
+ ```tsx {{ filename: 'app/user-profile/[[...user-profile]]/page.tsx' }}
'use client'
import { UserProfile } from '@clerk/nextjs'
@@ -295,7 +295,7 @@ The following example adds a link to the homepage in the navigation sidebar of t
", "Dedicated page"]}>
- ```tsx {{ filename: '/app/page.tsx' }}
+ ```tsx {{ filename: 'app/page.tsx' }}
'use client'
import { UserButton } from '@clerk/nextjs'
@@ -319,7 +319,7 @@ The following example adds a link to the homepage in the navigation sidebar of t
}
```
- ```tsx {{ filename: '/app/user-profile/[[...user-profile]]/page.tsx' }}
+ ```tsx {{ filename: 'app/user-profile/[[...user-profile]]/page.tsx' }}
'use client'
import { UserProfile } from '@clerk/nextjs'
@@ -398,7 +398,7 @@ Note that when reordering default routes, the first item in the navigation sideb
", "Dedicated page"]}>
- ```tsx {{ filename: '/app/page.tsx' }}
+ ```tsx {{ filename: 'app/page.tsx' }}
'use client'
import { UserButton } from '@clerk/nextjs'
@@ -442,7 +442,7 @@ Note that when reordering default routes, the first item in the navigation sideb
In the following example, `path` is set to `/user-profile`, so the `` is rendered under the `/user-profile` path.
- ```tsx {{ filename: '/app/user-profile/[[...user-profile]]/page.tsx' }}
+ ```tsx {{ filename: 'app/user-profile/[[...user-profile]]/page.tsx' }}
'use client'
import { UserProfile } from '@clerk/nextjs'
diff --git a/docs/customization/variables.mdx b/docs/customization/variables.mdx
index a1616d461a..f84a42f886 100644
--- a/docs/customization/variables.mdx
+++ b/docs/customization/variables.mdx
@@ -460,7 +460,7 @@ The following example shows how to customize the [``](/docs/components
- ```tsx {{ filename: '/app/sign-in/[[...sign-in]]/page.tsx', mark: [[6, 11]] }}
+ ```tsx {{ filename: 'app/sign-in/[[...sign-in]]/page.tsx', mark: [[6, 11]] }}
import { SignIn } from '@clerk/nextjs'
export default function Page() {
diff --git a/docs/deployments/migrate-from-firebase.mdx b/docs/deployments/migrate-from-firebase.mdx
index 9a7971d49b..bb12619e42 100644
--- a/docs/deployments/migrate-from-firebase.mdx
+++ b/docs/deployments/migrate-from-firebase.mdx
@@ -6,9 +6,9 @@ description: Migrating your user base from Firebase to Clerk is a 2-part process
Migrating your user base from Firebase to Clerk is a 2-part process that can be accomplished with just a few steps.
- ### Export your Firebase users
+ ## Export your Firebase users
- #### Install the Firebase CLI
+ ### Install the Firebase CLI
If you haven't already, install the Firebase CLI:
@@ -16,7 +16,7 @@ Migrating your user base from Firebase to Clerk is a 2-part process that can be
npm install -g firebase-tools
```
- #### Log in to Firebase
+ ### Log in to Firebase
Login to your Firebase account via the CLI.
@@ -24,7 +24,7 @@ Migrating your user base from Firebase to Clerk is a 2-part process that can be
firebase login
```
- #### Find your Firebase project ID
+ ### Find your Firebase project ID
Use the firebase CLI to list your projects and find the project ID you want to export.
@@ -32,7 +32,7 @@ Migrating your user base from Firebase to Clerk is a 2-part process that can be
firebase projects:list
```
- #### Export your Firebase users using the CLI
+ ### Export your Firebase users using the CLI
Use the firebase CLI to export your users to a JSON file.
@@ -52,7 +52,7 @@ Migrating your user base from Firebase to Clerk is a 2-part process that can be
You should now have a JSON file called `firebase-users.json` that contains all your Firebase users.
- ### Retrieve your password hash parameters
+ ## Retrieve your password hash parameters
In your Firebase project’s dashboard, navigate to **Authentication** and click on the 3 vertical dots at the top of the user's list, then click on **Password hash parameters**.
@@ -60,23 +60,23 @@ Migrating your user base from Firebase to Clerk is a 2-part process that can be
You can find more information about this page and the values above on [Firebase's documentation](https://firebaseopensource.com/projects/firebase/scrypt/).
- ### Create a Node.js script
+ ## Create a Node.js script
Now you have all the information you need to import your Firebase users into Clerk. This example uses Node.js, but you can use any other language or method if you so wish.
- #### init npm
+ ### init npm
```bash {{ filename: 'terminal' }}
npm init -y
```
- #### Install dependencies
+ ### Install dependencies
```bash {{ filename: 'terminal' }}
npm i node-fetch@2
```
- #### Create a script
+ ### Create a script
```js {{ filename: 'migrate-to-clerk.js' }}
const fetch = require('node-fetch')
@@ -134,7 +134,7 @@ Migrating your user base from Firebase to Clerk is a 2-part process that can be
Here, body will either hold the necessary information to migrate a password-based user or in the case of an OAuth-based user, it'll skip the password check. It will also have the previous user ID as `external_id`, so you can link the newly created users with their existing data.
- ### Run the script
+ ## Run the script
```bash {{ filename: 'terminal' }}
node migrate-to-clerk.js
diff --git a/docs/errors/sign-up.mdx b/docs/errors/sign-up.mdx
index 3c1fa0b59f..9a8b20c28a 100644
--- a/docs/errors/sign-up.mdx
+++ b/docs/errors/sign-up.mdx
@@ -41,7 +41,7 @@ An index of Clerk errors related to sign-up.
```json
{
"shortMessage": "CAPTCHA not enabled",
- "longMessage": "Bot detection can be applied only for production instances which have enabled CAPTCHA.",
+ "longMessage": "Bot detection can be applied only for instances which have enabled CAPTCHA.",
"code": "captcha_not_enabled"
}
```
diff --git a/docs/guides/architecture-scenarios.mdx b/docs/guides/architecture-scenarios.mdx
index 9ffecf275c..68cb423248 100644
--- a/docs/guides/architecture-scenarios.mdx
+++ b/docs/guides/architecture-scenarios.mdx
@@ -56,7 +56,7 @@ Clerk offers a number of building blocks to help integrate organizations into yo
- The [`` component](/docs/components/organization/organization-switcher) provides a way for your users to select which organization is active. The [`useOrganizationList()` hook](/docs/organizations/custom-organization-switcher) can be used for more control.
- The [`useOrganization()` hook](/docs/references/react/use-organization) can be used to fetch the current, active organization.
-- The [`` component](/docs/components/protect) enables you to limit who can view certain pages based on their role. Additionally, Clerk exposes a number of helper functions, such as [`auth()`](/docs/references/nextjs/auth), and hooks, such as [`useAuth()`](/docs/references/react/use-auth#how-to-use-the-use-auth-hook), to check the user's authorization throughout your app and API endpoints.
+- The [`` component](/docs/components/protect) enables you to limit who can view certain pages based on their role. Additionally, Clerk exposes a number of helper functions, such as [`auth()`](/docs/references/nextjs/auth), and hooks, such as [`useAuth()`](/docs/references/react/use-auth#how-to-use-the-use-auth-hook), to check the user's authorization throughout your app and API endpoints.
The organization's ID should be stored in your database alongside each resource so that it can be used to filter and query the resources that should be rendered or returned according to the active organization.
diff --git a/docs/guides/authjs-migration.mdx b/docs/guides/authjs-migration.mdx
index 7ccf9daa74..7f881daa42 100644
--- a/docs/guides/authjs-migration.mdx
+++ b/docs/guides/authjs-migration.mdx
@@ -23,7 +23,7 @@ description: Learn how to migrate an application using Auth.js to use Clerk for
>
- Install `@clerk/nextjs`
- Set environment variables
- - Wrap your Next.js app in ``
+ - Wrap your Next.js app in ``
- Set up sign-up and sign-in UI
- Protect your app
- Read user and session data
@@ -33,12 +33,10 @@ description: Learn how to migrate an application using Auth.js to use Clerk for
- Find further support
-## Introduction
-
This guide shows how to migrate an application using Auth.js (formerly NextAuth.js) to use Clerk for authentication.
- ### Install `@clerk/nextjs`
+ ## Install `@clerk/nextjs`
Clerk's Next.js SDK gives you access to prebuilt [components](/docs/components/overview), [hooks](/docs/references/nextjs/overview#client-side-helpers), and [helpers](/docs/references/nextjs/overview) for Next.js Server Components, Route Handlers and Middleware. Run the following command to install it:
@@ -56,7 +54,7 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
```
- ### Set environment variables
+ ## Set environment variables
Add the following code to your `.env.local` file to set your public and Secret Keys.
@@ -67,9 +65,11 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
CLERK_SECRET_KEY={{secret}}
```
- ### Wrap your Next.js app in ``
+ ## Wrap your Next.js app in ``
+
+ Remove the `` provider from Auth.js and replace it with ``.
- You will need to remove the `` provider from Auth.js and replace it with the `` provider from Clerk. `` will need to wrap your application, or wrap the portion of your app where you want to handle authentication.
+
```tsx {{ filename: 'app/layout.tsx', mark: [1, 6, 10] }}
@@ -102,26 +102,26 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
```
- ### Set up sign-up and sign-in UI
+ ## Set up sign-up and sign-in UI
- #### Account Portal
+ ### Account Portal
Account Portal is the fastest way to authenticate your app. Clerk's Account Portal hosts the ``, ``, ``, and other components for your application. Read more about [Account Portal](/docs/customization/account-portal/getting-started).
To use the Account Portal, remove the routes that mount the Auth.js sign-in and sign-up UI. Replace the links to those routes with the [``](/docs/components/unstyled/sign-in-button) or [``](/docs/components/unstyled/sign-out-button) components.
- #### Self-hosted UI
+ ### Self-hosted UI
If Clerk's Account Portal pages aren't a good fit your app, you can build a custom sign-in and sign-up UI in one of two ways:
- use the [prebuilt components](/docs/references/nextjs/custom-signup-signin-pages), such as the [``](/docs/components/authentication/sign-in) and [``](/docs/components/authentication/sign-up) components
- build a [fully custom UI using the Clerk API](/docs/custom-flows/overview), leveraging Clerk's React hooks such as [`useSignIn()`](/docs/references/react/use-sign-in) and [`useSignUp()`](/docs/references/react/use-sign-up)
- ### Protect your app
+ ## Protect your app
With Clerk, you can control access to your application in a few different ways. One way is to use Clerk's Middleware to protect your entire application, or specific routes. Another way is to use Clerk's components to conditionally render UI based on the user's authentication state. You can hide or show UI based on whether the user is signed in or not.
- #### Control access to your app with Clerk Middleware
+ ### Control access to your app with Clerk Middleware
You will need to remove the Auth.js Middleware from your application, and replace it with the Clerk's Middleware helper, `clerkMiddleware()`.
@@ -145,7 +145,7 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
}
```
- #### Control access to your app with Clerk's components
+ ### Control access to your app with Clerk's components
To conditionally render UI when the user is signed in, wrap it with [``](/docs/components/control/signed-in).
@@ -168,9 +168,9 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
}
```
- ### Read user and session data
+ ## Read user and session data
- #### Server-side
+ ### Server-side
Replace any Auth.js `getServerSession(req, res, authOptions)` with Clerk's helpers.
@@ -203,7 +203,7 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
- #### Client Side
+ ### Client Side
Replace Auth.js's `useSession()` hook with Clerk's hooks.
@@ -222,14 +222,14 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
}
```
- ### User IDs as Foreign Keys
+ ## User IDs as Foreign Keys
When you migrate to Clerk, you will likely need to resolve the foreign key that you used in your database. If you used the `userId` from NextAuth.js, you could resolve this issue with one of the following two options:
- [Use Clerk's `externalId` field](#use-clerks-external-id-field)
- [Update your Auth.js database](#update-your-database)
- #### Use Clerk's `externalId` field
+ ### Use Clerk's `externalId` field
When you migrate user data from Auth.js to Clerk, Clerk generates new user IDs for each user. If you are using existing user IDs as foreign keys in your database (e.g. in a `user_id` column), you can save those IDs as the user's `externalId` in Clerk. This `externalId` can be included in the session token by adding the following [customization](/docs/backend-requests/making/custom-session-token). The following example will set the user's ID to be `externalId` if one is present, otherwise, it will use the Clerk's user ID.
@@ -285,19 +285,19 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
> [!NOTE]
> You can not access the above from the client-side. If you are using one of Clerk's hooks, then you will need to check if `externalID` exists. If it doesn't, then read the `userId`.
- #### Update your database
+ ### Update your database
Alternatively, after the data migration, you can update all the user IDs stored in your database as a foreign key to the new Clerk user IDs.
You can read more about user IDs and user data migration in the [Migration Script README](https://github.com/clerk/migration-script?tab=readme-ov-file#handling-the-foreign-key-constraint).
- ### Create a Clerk production instance
+ ## Create a Clerk production instance
Every Clerk application has a `Development` and a `Production` instance. Before you start migrating user data, you need to configure your Clerk `Production` instance and migrate your Auth.js users directly into that instance. The [Deploying to Production](/docs/deployments/overview#deploying-to-production) page covers creating a `Production` instance.
You can migrate a small set of users on the `Development` instance for testing/staging. To enable importing users to your `Development` instance, add `IMPORT_TO_DEV_INSTANCE=true` to the `.env` for the migration script.
- ### Migrate user data from Auth.js to Clerk
+ ## Migrate user data from Auth.js to Clerk
This walkthrough will help you move user data from your existing database to Clerk.
@@ -338,7 +338,7 @@ This guide shows how to migrate an application using Auth.js (formerly NextAuth.
1. Check for an error log for any users that were not migrated successfully.
- ### Finding further support for migrating from Auth.js to Clerk
+ ## Finding further support for migrating from Auth.js to Clerk
This guide covers the most common steps that you would take for the migration. If you have more complex integrations with Auth.js that are not covered here, don't hesitate to reach out in the [Clerk Discord](/discord){{ target: '_blank' }} by creating a post in the [Support channel](https://discord.gg/bmPVkeqKzZ).
diff --git a/docs/guides/basic-rbac.mdx b/docs/guides/basic-rbac.mdx
index c162efd9d8..10504d94c5 100644
--- a/docs/guides/basic-rbac.mdx
+++ b/docs/guides/basic-rbac.mdx
@@ -8,7 +8,7 @@ To control which users can access certain parts of your app, you can use the [ro
This guide assumes that you're using Next.js App Router, but the concepts can be adapted to Next.js Pages Router and Remix.
- ### Configure the session token
+ ## Configure the session token
Clerk provides [user metadata](/docs/users/metadata#user-metadata), which can be used to store information, and in this case, it can be used to store a user's role. Since `publicMetadata` can only be read but not modified in the browser, it is the safest and most appropriate choice for storing information.
@@ -26,7 +26,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
- ### Create a global TypeScript definition
+ ## Create a global TypeScript definition
1. In your application's root folder, create a `types/` directory.
1. Inside this directory, create a `globals.d.ts` file with the following code. This file will provide auto-completion and prevent TypeScript errors when working with roles. For this guide, only the `admin` and `moderator` roles will be defined.
@@ -46,7 +46,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- ### Set the admin role for your user
+ ## Set the admin role for your user
Later in the guide, you will add a basic admin tool to change a user's role. For now, manually add the `admin` role to your own user account.
@@ -61,7 +61,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- ### Create a reusable function to check roles
+ ## Create a reusable function to check roles
Create a helper function to simplify checking roles.
@@ -81,7 +81,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
> [!NOTE]
> You can customize the behavior of the `checkRole()` helper function to suit your needs. For example, you could modify it to return the roles a user has or create a `protectByRole()` function that handles role-based redirects.
- ### Create the admin dashboard
+ ## Create the admin dashboard
Now, it's time to create an admin dashboard. The first step is to create the `/admin` route.
@@ -94,7 +94,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- ### Protect the admin dashboard
+ ## Protect the admin dashboard
To protect the `/admin` route, choose **one** of the two following methods:
@@ -104,7 +104,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
> [!IMPORTANT]
> You only need to follow **one** of the following methods to secure your `/admin` route.
- #### Option 1: Protect the `/admin` route using middleware
+ ### Option 1: Protect the `/admin` route using middleware
1. In your app's root directory, create a `middleware.ts` file with the following code. The `createRouteMatcher()` function identifies routes starting with `/admin`. `clerkMiddleware()` intercepts requests to the `/admin` route, and checks the user's role in their `metadata` to verify that they have the `admin` role. If they don't, it redirects them to the home page.
@@ -132,7 +132,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- #### Option 2: Protect the `/admin` route at the page-level
+ ### Option 2: Protect the `/admin` route at the page-level
1. Add the following code to the `app/admin/page.tsx` file. The `checkRole()` function checks if the user has the `admin` role. If they don't, it redirects them to the home page.
@@ -151,7 +151,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- ### Create server actions for managing a user's role
+ ## Create server actions for managing a user's role
1. In your `app/admin/` directory, create an `_actions.ts` file with the following code. The `setRole()` action checks that the current user has the `admin` role before updating the specified user's role using Clerk's [JavaScript Backend SDK](/docs/references/backend/user/update-user). The `removeRole()` action removes the role from the specified user.
@@ -193,7 +193,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- ### Create a component for searching for users
+ ## Create a component for searching for users
1. In your `app/admin/` directory, create a `SearchUsers.tsx` file with the following code. The `` component includes a form for searching for users. When submitted, it appends the search term to the URL as a search parameter. Your `/admin` route will then perform a query based on the updated URL.
@@ -226,7 +226,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- ### Refactor the admin dashboard
+ ## Refactor the admin dashboard
With the server action and the search form set up, it's time to refactor the `app/admin/page.tsx`.
@@ -298,7 +298,7 @@ This guide assumes that you're using Next.js App Router, but the concepts can be
}
```
- ### Finished 🎉
+ ## Finished 🎉
The foundation of a custom RBAC (Role-Based Access Control) system is now set up. Roles are attached directly to the user's session, allowing your application to access them without the need for additional network requests. The `checkRole()` helper function simplifies role checks and reduces code complexity. The final component is the admin dashboard, which enables admins to efficiently search for users and manage roles.
diff --git a/docs/guides/custom-types.mdx b/docs/guides/custom-types.mdx
index d8a4cde6d3..99a791f462 100644
--- a/docs/guides/custom-types.mdx
+++ b/docs/guides/custom-types.mdx
@@ -5,13 +5,15 @@ description: Learn about the interfaces that you can use to define custom types
Clerk provides TypeScript interfaces that you can use to define custom types for your application. Custom types provide auto-complete and prevent TypeScript errors. You can define custom types for the following:
+- `ClerkAuthorization`
- `CustomJwtSessionClaims`
- `OrganizationPublicMetadata`
- `OrganizationInvitationPublicMetadata`
- `OrganizationMembershipPublicMetadata`
+- `SignUpUnsafeMetadata`
- `UserPublicMetadata`
+- `UserPrivateMetadata`
- `UserUnsafeMetadata`
-- `ClerkAuthorization`
## Example
diff --git a/docs/guides/force-organizations.mdx b/docs/guides/force-organizations.mdx
index ecfef6948c..b3ca2eac15 100644
--- a/docs/guides/force-organizations.mdx
+++ b/docs/guides/force-organizations.mdx
@@ -23,14 +23,12 @@ description: Learn how to hide Personal Accounts and force organizations in your
- Limit access to users with active organizations only
-## Introduction
-
In this guide, you will learn how to hide a user's Personal Account in order to appear as if they only have access to organizations. You will also learn how to limit access to your application to only users with active organizations, further enforcing organization-centric access. This is useful for applications that are built for organizations only, such as B2B applications.
This guide will be written for Next.js applications using App Router, but the same concepts can be applied to any application using Clerk.
- ### Hide Personal Accounts from UI components
+ ## Hide Personal Accounts from UI components
To begin forcing organizations in your application, you need to remove a user's Personal Account from the UI. A user's Personal Account cannot be disabled; it can only be hidden.
@@ -68,11 +66,11 @@ This guide will be written for Next.js applications using App Router, but the sa
- ### Detect and set an active organization
+ ## Detect and set an active organization
With Clerk, a user can have many organization memberships, but only one of them can be active at a time.
- #### Detect an active organization
+ ### Detect an active organization
A session will always include an `orgId` via the [`Auth` object](/docs/references/nextjs/auth-object#auth-object-example-with-active-organization). This can be used to detect if a user has an active organization.
@@ -109,7 +107,7 @@ This guide will be written for Next.js applications using App Router, but the sa
- #### Set an active organization
+ ### Set an active organization
In the case of [prebuilt components](/docs/components/overview), an organization will _automatically_ be set as active each time the user creates an organization, accepts an invitation, or selects a membership from the organization switcher. In the case of custom flows, you will need to implement the logic for setting an organization as active. The [`useOrganizationList()`](/docs/references/react/use-organization-list) hook provides a `setActive` method to help you with this.
@@ -153,7 +151,7 @@ This guide will be written for Next.js applications using App Router, but the sa
}
```
- #### Set an active organization based on the URL
+ ### Set an active organization based on the URL
> [!WARNING]
> This approach still depends on the `setActive` method, which only runs on the client. Due to this limitation, during SSR, it is possible that `orgId` from `auth()` returns an incorrect value that does not match the organization ID in the URL.
@@ -213,7 +211,7 @@ This guide will be written for Next.js applications using App Router, but the sa
}
```
- ### Limit access to users with active organizations only
+ ## Limit access to users with active organizations only
Now that you have hidden Personal Accounts from the UI and can detect and set an active organization, you can limit access to your application to users with active organizations only. This will ensure that users without active organizations cannot access your application.
@@ -229,7 +227,7 @@ This guide will be written for Next.js applications using App Router, but the sa
Based on your use case, you can decide to limit users either in the entire app or a specific part of it. For example, a B2B application might need to limit access to only users with an active organization, whereas a B2B2C application might limit only the `/dashboard` path to users with an active organization.
- #### Limit access using the `clerkMiddleware()` helper
+ ### Limit access using the `clerkMiddleware()` helper
Clerk's [`clerkMiddleware()`](/docs/references/nextjs/clerk-middleware) helper can be used in both App Router and Pages Router applications to limit access to users with active organizations only.
@@ -324,7 +322,7 @@ This guide will be written for Next.js applications using App Router, but the sa
}
```
- #### Limit access using an App Router layout
+ ### Limit access using an App Router layout
In Next.js App Router applications, instead of using `clerkMiddleware()`, you also have the option to use a layout to limit access to users with active organizations only.
diff --git a/docs/guides/reverification.mdx b/docs/guides/reverification.mdx
index 31235d932d..c4d1fdac9e 100644
--- a/docs/guides/reverification.mdx
+++ b/docs/guides/reverification.mdx
@@ -22,7 +22,7 @@ To handle reverification server-side, use the [`auth.has()`](/docs/references/ne
The following example uses the [`has()`](/docs/references/nextjs/auth-object#has) helper to check if the user has verified their credentials within a specific time period. The `strict` configuration sets the time period to 10 minutes. If the user hasn't verified their credentials within 10 minutes, the `reverificationError` utility is used to return an error.
- ```ts {{ filename: '/app/actions.ts' }}
+ ```ts {{ filename: 'app/actions.ts' }}
'use server'
import { auth, reverificationError } from '@clerk/nextjs/server'
@@ -128,7 +128,7 @@ The following example demonstrates how to use the [`useReverification()`](/docs/
- ```tsx {{ filename: '/app/perform-action/page.tsx' }}
+ ```tsx {{ filename: 'app/perform-action/page.tsx' }}
'use client'
import { useReverification } from '@clerk/nextjs'
@@ -150,7 +150,7 @@ The following example demonstrates how to use the [`useReverification()`](/docs/
- ```tsx {{ filename: '/app/transfer/page.tsx' }}
+ ```tsx {{ filename: 'app/transfer/page.tsx' }}
'use client'
import { useReverification } from '@clerk/nextjs'
diff --git a/docs/guides/waitlist.mdx b/docs/guides/waitlist.mdx
index b1d25f2da8..f4012afc5a 100644
--- a/docs/guides/waitlist.mdx
+++ b/docs/guides/waitlist.mdx
@@ -6,7 +6,7 @@ description: Learn how to add a waitlist to your Next.js application.
In [**Waitlist** mode](/docs/authentication/configuration/restrictions#waitlist), users can register their interest in your app by joining a waitlist. This mode is ideal for apps in early development stages or those wanting to generate interest before launch. This guide shows you how to get Clerk integrated and how to add a waitlist to your Next.js application.
- ### Install `@clerk/nextjs`
+ ## Install `@clerk/nextjs`
Clerk's [Next.js SDK](/docs/references/nextjs/overview) gives you access to prebuilt components, React hooks, and helpers to make user authentication easier.
@@ -26,7 +26,7 @@ In [**Waitlist** mode](/docs/authentication/configuration/restrictions#waitlist)
```
- ### Set your Clerk API keys
+ ## Set your Clerk API keys
@@ -51,7 +51,7 @@ In [**Waitlist** mode](/docs/authentication/configuration/restrictions#waitlist)
CLERK_SECRET_KEY={{secret}}
```
- ### Enable Waitlist mode
+ ## Enable Waitlist mode
To enable **Waitlist** mode, follow these steps:
@@ -64,13 +64,13 @@ In [**Waitlist** mode](/docs/authentication/configuration/restrictions#waitlist)
1. On the right-side of a user's row, select the menu icon (...).
1. Select **Invite** to invite the user to your application. Select **Deny** to deny the user access to your application.
- ### Add the `` component
+ ## Add the `` component
The [``](/docs/components/waitlist) component renders a form that allows users to join for early access to your app.
The following example includes a basic implementation of the `` component hosted on the `/` route (the home page). You can use this as a starting point for your own implementation.
- ```jsx {{ filename: '/app/page.tsx' }}
+ ```jsx {{ filename: 'app/page.tsx' }}
import { Waitlist } from '@clerk/nextjs'
export default function Page() {
@@ -78,9 +78,11 @@ In [**Waitlist** mode](/docs/authentication/configuration/restrictions#waitlist)
}
```
- ### Add `` to your app
+ ## Add `` to your app
- The [``](/docs/components/clerk-provider) component wraps your app to provide active session and user context to Clerk's hooks and other components. To use the `` component in your app, you must provide the `waitlistUrl` prop, which points to the URL of your waitlist page.
+
+
+ To use the `` component in your app, you must provide the `waitlistUrl` prop, which points to the URL of your waitlist page.
```tsx {{ filename: 'app/layout.tsx', mark: [6] }}
import { ClerkProvider } from '@clerk/nextjs'
@@ -97,14 +99,14 @@ In [**Waitlist** mode](/docs/authentication/configuration/restrictions#waitlist)
}
```
- ### Add sign-in functionality
+ ## Add sign-in functionality
To allow users to sign in once they've been approved from the waitlist, you must:
- [Add `clerkMiddleware()` to your app.](#add-clerkmiddleware-to-your-app)
- [Add a sign-in page.](#add-a-sign-in-page)
- #### Add `clerkMiddleware()` to your app
+ ### Add `clerkMiddleware()` to your app
[`clerkMiddleware()`](/docs/references/nextjs/clerk-middleware#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:
@@ -132,7 +134,7 @@ In [**Waitlist** mode](/docs/authentication/configuration/restrictions#waitlist)
1. By default, `clerkMiddleware()` will not protect any routes. All routes are public and you must opt-in to protection for routes. See the [`clerkMiddleware()` reference](/docs/references/nextjs/clerk-middleware) to learn how to require authentication for specific routes.
- #### Add a sign-in page
+ ### Add a sign-in page
The following example demonstrates how to render the `` component.
diff --git a/docs/index.mdx b/docs/index.mdx
index 7a997a05a7..5d3f8701a8 100644
--- a/docs/index.mdx
+++ b/docs/index.mdx
@@ -81,6 +81,12 @@ Find all the guides and resources you need to develop with Clerk.
---
+ - [React Router (Beta)](/docs/quickstarts/react-router)
+ - Easily add secure, edge- and SSR-friendly authentication to React Router with Clerk.
+ - {}
+
+ ---
+
- [Nuxt](/docs/quickstarts/nuxt)
- Easily add secure, beautiful, and fast authentication to Nuxt with Clerk.
- {}
diff --git a/docs/integrations/databases/convex.mdx b/docs/integrations/databases/convex.mdx
index c98732de47..bbce2b5bc4 100644
--- a/docs/integrations/databases/convex.mdx
+++ b/docs/integrations/databases/convex.mdx
@@ -24,14 +24,12 @@ description: Learn how to integrate Clerk into your Convex application.
- Access user identity in Convex queries and mutations
-## Introduction
-
Convex is the full-stack TypeScript development platform. With Convex you get to build a backend with a provided realtime database, file storage, text search, scheduling and more. Paired with Clerk's user authentication and management features, you can build a powerful application with minimal effort.
This tutorial assumes that you have already [set up a Clerk application](/docs/quickstarts/setup-clerk) and a [React + Convex application](https://docs.convex.dev/quickstart/react){{ target: '_blank' }}. This tutorial will also assume that you have not added Clerk to your application yet.
- ### Create a JWT template based on Convex
+ ## Create a JWT template based on Convex
In the Clerk Dashboard, navigate to the [**JWT templates**](https://dashboard.clerk.com/last-active?path=jwt-templates) page. Select the **New template** button to create a new template based on Convex.
@@ -47,7 +45,7 @@ This tutorial assumes that you have already [set up a Clerk application](/docs/q
By default, Clerk will sign the JWT with a private key automatically generated for your application, which is what most developers use for Convex. If you so choose, you can customize this key.
- ### Configure Convex with the Clerk issuer domain
+ ## Configure Convex with the Clerk issuer domain
The next step is to configure Convex with the issuer domain provided by Clerk. From your Clerk **JWT template** screen, find the **Issuer** input and click to **Copy** the URL.
@@ -68,11 +66,11 @@ This tutorial assumes that you have already [set up a Clerk application](/docs/q
Replace the `domain` string with the **Issuer** URL you copied.
- ### Deploy your changes to Convex
+ ## Deploy your changes to Convex
Run `npx convex dev` to automatically sync your configuration to your backend.
- ### Install `@clerk/clerk-react`
+ ## Install `@clerk/clerk-react`
Run the following command to install Clerk's React SDK:
@@ -90,7 +88,7 @@ This tutorial assumes that you have already [set up a Clerk application](/docs/q
```
- ### Set environment variables
+ ## Set environment variables
In your React project's root folder, you may have an `.env.local` file alongside `package.json` and other configuration files. If you don't see it, create it.
@@ -110,11 +108,15 @@ This tutorial assumes that you have already [set up a Clerk application](/docs/q
VITE_CLERK_PUBLISHABLE_KEY={{pub_key}}
```
- ### Configure the Clerk and Convex providers
+ ## Configure the Clerk and Convex providers
+
+ Both Clerk and Convex have provider components that are required to provide authentication and client context.
+
+ Clerk's provider component is ``, which should wrap your entire app at the entry point to make authentication globally accessible. See the [reference docs](/docs/components/clerk-provider) for other configuration options.
- Both Clerk and Convex have Provider components that are required to wrap your React application to provide the authentication and client context.
+ Convex offers a provider that is specifically for integrating with Clerk called [``](https://docs.convex.dev/auth/clerk).
- You may have already had a `` configured. Be sure that `` wraps `ConvexProviderWithClerk`, and that `useAuth` is passed to `ConvexProviderWithClerk`.
+ The following example demonstrates how to configure Clerk and Convex's providers. Clerk's `useAuth()` hook must be passed to `` and Clerk's `` must be wrapped around it.
```ts {{ filename: 'src/main.tsx' }}
import React from 'react'
@@ -145,7 +147,7 @@ This tutorial assumes that you have already [set up a Clerk application](/docs/q
)
```
- ### Access user identity in Convex queries and mutations
+ ## Access user identity in Convex queries and mutations
You can access the user information from the JWT in Convex queries and mutations.
Use the `ctx.auth.getUserIdentity()` which returns the parsed information from the JWT, or `null` if the client isn't authenticated.
@@ -167,7 +169,7 @@ This tutorial assumes that you have already [set up a Clerk application](/docs/q
You can customize the information in the JWT by navigating to the [**JWT templates**](https://dashboard.clerk.com/last-active?path=jwt-templates) page in the Clerk Dashboard. Previously, Convex explicitly listed fields derived from [OpenID standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). Now, Convex allows keys to accept [custom claims](https://docs.convex.dev/api/interfaces/server.UserIdentity).
- ### Finished!
+ ## Finished!
You now have a fully functioning React and Convex application with Clerk authentication. Be aware that Convex may require usage of their custom hooks and methods rather than Clerk's, such as using Convex's `useConvexAuth()` hook instead of Clerk's `useAuth()` hook in some cases. For more information on how to use Convex with Clerk, see the [Convex docs](https://docs.convex.dev/auth/clerk).
diff --git a/docs/integrations/databases/fauna.mdx b/docs/integrations/databases/fauna.mdx
index 40ed46991e..0e01ef4f9f 100644
--- a/docs/integrations/databases/fauna.mdx
+++ b/docs/integrations/databases/fauna.mdx
@@ -30,7 +30,7 @@ Integrating Fauna with Clerk gives you the benefits of using a Fauna database wh
This guide will walk you through the steps to integrate Fauna with Clerk in your Next.js app.
- ### Get your Clerk Frontend API URL and JWKS URL
+ ## Get your Clerk Frontend API URL and JWKS URL
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 in the Clerk Dashboard.
@@ -52,7 +52,7 @@ This guide will walk you through the steps to integrate Fauna with Clerk in your
NEXT_PUBLIC_CLERK_JWKS_URL={{jwks_url}}
```
- ### Configure Fauna
+ ## Configure Fauna
1. Navigate to the [Fauna Dashboard](https://dashboard.fauna.com/) and select your database.
1. Select the **Access Providers** tab and select **Create Access Provider**.
@@ -76,7 +76,7 @@ This guide will walk you through the steps to integrate Fauna with Clerk in your
```
1. Select **Save**.
- ### Create a JWT template in Clerk
+ ## Create a JWT template in Clerk
Clerk's JWT templates allow you to generate a new valid Fauna authentication token (JWT) for each signed in user. These tokens allow authenticated users to access your data with Fauna's API.
@@ -90,7 +90,7 @@ This guide will walk you through the steps to integrate Fauna with Clerk in your
- In the **Claims** section, set the `aud` claim to the **Audience URL** you copied from Fauna in Step 2. The URL format should be `https://db.fauna.com/db/`. You can include additional claims if you’d like, but `aud` is the only required one. [Shortcodes](/docs/backend-requests/making/jwt-templates#shortcodes) are available to make adding dynamic user values easy.
- Select **Save** from the notification bubble to complete setup.
- ### Install the Fauna library
+ ## Install the Fauna library
Add the Fauna library to your project.
@@ -108,7 +108,7 @@ This guide will walk you through the steps to integrate Fauna with Clerk in your
```
- ### Authenticate Fauna queries in your Next.js app
+ ## Authenticate Fauna queries in your Next.js app
You can now create Fauna JWTs in Clerk using the JWT template you created in the previous step. Generate the Fauna JWT by calling Clerk's [`useAuth().getToken`](/docs/references/react/use-auth) method, and use it to authenticate with Fauna as an end user, as shown in the following example:
diff --git a/docs/integrations/databases/firebase.mdx b/docs/integrations/databases/firebase.mdx
index 51c692f0eb..61219e5315 100644
--- a/docs/integrations/databases/firebase.mdx
+++ b/docs/integrations/databases/firebase.mdx
@@ -32,7 +32,7 @@ Integrating Firebase with Clerk gives you the benefits of using Firebase's featu
> See the [demo repo](https://github.com/clerk/clerk-firebase-nextjs) for a full example of how to integrate Firebase with Clerk in a Next.js app.
- ### Configure the integration
+ ## Configure the integration
The Firebase integration enables you to use Clerk to generate a valid authentication token to send to Firebase Auth. This enables you to leverage Clerk's prebuilt components, auth provider options, and more, while accessing Firebase products like Firestore with a session validated by Firebase Auth.
@@ -68,7 +68,7 @@ Integrating Firebase with Clerk gives you the benefits of using Firebase's featu
- ### Enable authentication in Firebase
+ ## Enable authentication in Firebase
To use Firebase auth, ensure authentication is enabled in your Firebase dashboard. To do so:
@@ -77,7 +77,7 @@ Integrating Firebase with Clerk gives you the benefits of using Firebase's featu
1. Select **Get started**.
1. Enable any sign-in method you want, such as **Email/Password**.
- ### Add a Security Rule to your Firestore database (optional)
+ ## Add a Security Rule to your Firestore database (optional)
Adding the [Cloud Firestore](https://firebase.google.com/docs/firestore/quickstart) feature in your Firebase application is optional.
@@ -93,7 +93,7 @@ Integrating Firebase with Clerk gives you the benefits of using Firebase's featu
}
```
- ### Get your Firebase config object
+ ## Get your Firebase config object
To connect to your Firebase app in your code, you need a config object from your Firebase project. To find it:
@@ -115,7 +115,7 @@ Integrating Firebase with Clerk gives you the benefits of using Firebase's featu
See [Google's Firebase documentation](https://support.google.com/firebase/answer/7015592) for more information on the config object.
- ### Use Firebase with Clerk in your code
+ ## Use Firebase with Clerk in your code
Now that you have configured the integration, and you have retrieved your Firebase config object, it's time to use Firebase with Clerk in your code.
diff --git a/docs/integrations/databases/instantdb.mdx b/docs/integrations/databases/instantdb.mdx
index 43522defff..b72937377c 100644
--- a/docs/integrations/databases/instantdb.mdx
+++ b/docs/integrations/databases/instantdb.mdx
@@ -35,7 +35,7 @@ Integrating [InstantDB](https://www.instantdb.com/) with Clerk gives you the ben
This guide will walk you through the steps to integrate InstantDB with Clerk in your Next.js app.
- ### Configure your Clerk session token
+ ## Configure your Clerk session token
InstantDB uses Clerk's [session token](/docs/backend-requests/resources/session-tokens) to authenticate users. To use InstantDB with Clerk, you need to include the `email` claim in your session token.
@@ -50,12 +50,12 @@ This guide will walk you through the steps to integrate InstantDB with Clerk in
You can have additional claims as long as the `email` claim is set to `{{user.primary_email_address}}`.
- ### Get your Clerk Publishable Key
+ ## Get your Clerk Publishable Key
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.
- ### Configure InstantDB
+ ## Configure InstantDB
1. In the InstantDB dashboard, navigate to the [**Auth**](https://www.instantdb.com/dash?t=auth) tab.
1. Select **Setup Clerk**.
@@ -63,7 +63,7 @@ This guide will walk you through the steps to integrate InstantDB with Clerk in
1. Confirm the **The session token has the "email" claim.** message.
1. Select **Add Clerk app**.
- ### Install the InstantDB library
+ ## Install the InstantDB library
Run the following command to add the InstantDB library to your project.
@@ -81,7 +81,7 @@ This guide will walk you through the steps to integrate InstantDB with Clerk in
```
- ### Integrate InstantDB to your Clerk application
+ ## Integrate InstantDB to your Clerk application
To sign in to InstantDB with Clerk, you need to:
diff --git a/docs/integrations/databases/neon.mdx b/docs/integrations/databases/neon.mdx
index 56abd969e8..d62eba71b1 100644
--- a/docs/integrations/databases/neon.mdx
+++ b/docs/integrations/databases/neon.mdx
@@ -23,7 +23,7 @@ description: Learn how to integrate Clerk into your Neon application.
This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.js application, using `drizzle-orm` and `drizzle-kit` to interact with the database. The tutorial guides you through setting up a simple application that enables users to add, view, and delete messages using Server Actions and Middleware with Clerk.
- ### Create a new Next.js project
+ ## Create a new Next.js project
1. Create a new Next.js project using the following command:
```sh {{ filename: 'terminal' }}
@@ -37,11 +37,11 @@ This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.j
npm install -D drizzle-kit
```
- ### Integrate the Next.js Clerk SDK
+ ## Integrate the Next.js Clerk SDK
Follow the [Next.js quickstart](/docs/quickstarts/nextjs) to integrate the Clerk Next.js SDK into your application.
- ### Protect your application routes
+ ## Protect your application routes
To ensure that only authenticated users can access your application, modify [`clerkMiddleware`](/docs/references/nextjs/clerk-middleware) to require authentication for every route.
@@ -62,7 +62,7 @@ This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.j
}
```
- ### Set your neon connection string
+ ## Set your neon connection string
Add the Neon connection string to your project's environment variables. You can find the Neon connection string in the [Neon console](https://console.neon.tech/) - see the [Neon docs](https://neon.tech/docs/connect/connect-from-any-app) for more information.
@@ -74,7 +74,7 @@ This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.j
CLERK_SECRET_KEY={{secret}}
```
- ### Set up the application schema and database connection
+ ## Set up the application schema and database connection
1. Inside the `app/`, create a `db/` directory.
@@ -110,7 +110,7 @@ This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.j
})
```
- ### Push the schema to the database
+ ## Push the schema to the database
1. To load the schema into the database, create a `drizzle.config.ts` file at the root of your project and add the following configuration:
@@ -139,7 +139,7 @@ This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.j
npx drizzle-kit push
```
- ### Create Server Actions to handle user interactions
+ ## Create Server Actions to handle user interactions
To handle form submissions for adding and deleting user messages, create two Server Actions in `app/actions.ts`. Use Clerk's [`auth()` helper](/docs/references/nextjs/auth) to obtain the user ID, which will be used to interact with the database.
@@ -170,7 +170,7 @@ This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.j
}
```
- ### Create the UI for the Home Page
+ ## Create the UI for the Home Page
In your `app/page.tsx` file, add the following code to create the UI for the home page. If a message exists, the user can view and delete it; otherwise, they can add a new message.
@@ -211,7 +211,7 @@ This tutorial demonstrates how to integrate Neon Postgres with Clerk in a Next.j
}
```
- ### Run the application
+ ## Run the application
Run your application and open `http://localhost:3000` in your browser. Sign in with Clerk and interact with the application to add and delete user messages.
diff --git a/docs/manifest.json b/docs/manifest.json
index 5cc863fd1e..99eea32fda 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -30,6 +30,12 @@
"href": "/docs/quickstarts/nextjs",
"icon": "nextjs"
},
+ {
+ "title": "React Router",
+ "tag": "(Beta)",
+ "href": "/docs/quickstarts/react-router",
+ "icon": "react-router"
+ },
{
"title": "Remix",
"href": "/docs/quickstarts/remix",
@@ -584,6 +590,17 @@
}
]
]
+ },
+ {
+ "title": "OIDC",
+ "items": [
+ [
+ {
+ "title": "Custom provider",
+ "href": "/docs/authentication/enterprise-connections/oidc/custom-provider"
+ }
+ ]
+ ]
}
]
]
@@ -1621,6 +1638,10 @@
{
"title": "Protect email link sign-ins and sign-ups",
"href": "/docs/security/email-link-protection"
+ },
+ {
+ "title": "Unauthorized sign-in",
+ "href": "/docs/security/unauthorized-sign-in"
}
]
]
@@ -1674,8 +1695,8 @@
"href": "/docs/custom-flows/oauth-connections"
},
{
- "title": "SAML connections",
- "href": "/docs/custom-flows/saml-connections"
+ "title": "Enterprise connections",
+ "href": "/docs/custom-flows/enterprise-connections"
},
{
"title": "Sign out",
@@ -1862,17 +1883,6 @@
"title": "Overview",
"href": "/docs/references/react/overview"
},
- {
- "title": "Guides",
- "items": [
- [
- {
- "title": "Add React Router",
- "href": "/docs/references/react/add-react-router"
- }
- ]
- ]
- },
{
"title": "Client-side Helpers",
"items": [
@@ -2173,6 +2183,10 @@
"title": "DeletedObject",
"href": "/docs/references/javascript/types/deleted-object"
},
+ {
+ "title": "Metadata types",
+ "href": "/docs/references/javascript/types/metadata"
+ },
{
"title": "OAuth types",
"href": "/docs/references/javascript/types/oauth"
@@ -2279,34 +2293,41 @@
"href": "/docs/references/expo/overview"
},
{
- "title": "Guides",
+ "title": "Hooks",
"items": [
[
{
- "title": "Read session and user data",
- "href": "/docs/references/expo/read-session-user-data"
+ "title": "useLocalCredentials()",
+ "href": "/docs/references/expo/use-local-credentials"
},
{
- "title": "Use biometrics with local credentials",
- "href": "/docs/references/expo/local-credentials"
+ "title": "useOAuth()",
+ "href": "/docs/references/expo/use-oauth"
}
]
]
},
{
- "title": "Hooks",
+ "title": "Guides",
"items": [
[
{
- "title": "useLocalCredentials()",
- "href": "/docs/references/expo/use-local-credentials"
+ "title": "Read session and user data",
+ "href": "/docs/references/expo/read-session-user-data"
+ },
+ {
+ "title": "Use biometrics with local credentials",
+ "href": "/docs/references/expo/local-credentials"
+ },
+ {
+ "title": "Offline support",
+ "href": "/docs/references/expo/offline-support"
}
]
]
},
{
"title": "Web support",
- "icon": "route",
"collapse": true,
"items": [
[
@@ -2387,6 +2408,55 @@
]
]
},
+ {
+ "title": "React Router",
+ "collapse": true,
+ "icon": "react-router",
+ "tag": "(Beta)",
+ "items": [
+ [
+ {
+ "title": "Overview",
+ "href": "/docs/references/react-router/overview"
+ },
+ {
+ "title": "Guides",
+ "items": [
+ [
+ {
+ "title": "Read session and user data",
+ "href": "/docs/references/react-router/read-session-data"
+ },
+ {
+ "title": "Add custom sign up and sign in pages",
+ "href": "/docs/references/react-router/custom-signup-signin-pages"
+ },
+ {
+ "title": "Library mode",
+ "href": "/docs/references/react-router/library-mode"
+ }
+ ]
+ ]
+ },
+ {
+ "title": "General References",
+ "items": [
+ [
+ {
+ "title": "`rootAuthLoader()`",
+ "wrap": false,
+ "href": "/docs/references/react-router/root-auth-loader"
+ },
+ {
+ "title": "`getAuth()`",
+ "href": "/docs/references/react-router/get-auth"
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
{
"title": "Remix",
"collapse": true,
diff --git a/docs/manifest.schema.json b/docs/manifest.schema.json
index d8178bddf0..3773be9eef 100644
--- a/docs/manifest.schema.json
+++ b/docs/manifest.schema.json
@@ -125,6 +125,7 @@
"react",
"redwood",
"remix",
+ "react-router",
"rocket",
"route",
"ruby",
@@ -138,6 +139,7 @@
"user-dotted-circle",
"vue",
"x",
+ "expo",
"nuxt"
]
}
diff --git a/docs/organizations/verify-user-permissions.mdx b/docs/organizations/verify-user-permissions.mdx
index 1d0063c620..b46651b529 100644
--- a/docs/organizations/verify-user-permissions.mdx
+++ b/docs/organizations/verify-user-permissions.mdx
@@ -24,7 +24,7 @@ The following examples work for both SSR and CSR.
The following example uses the `` component to only render the form for users with the correct permission. The example uses the `fallback` prop to render a different UI if the user is not authorized.
- ```tsx {{ filename: '/app/dashboard/settings/form.tsx' }}
+ ```tsx {{ filename: 'app/dashboard/settings/form.tsx' }}
'use client'
import { Protect } from '@clerk/nextjs'
@@ -44,7 +44,7 @@ The following examples work for both SSR and CSR.
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' }}
+ ```tsx {{ filename: 'app/dashboard/settings/form.tsx' }}
'use client'
import { useAuth } from '@clerk/nextjs'
@@ -76,7 +76,7 @@ The following examples work for both SSR and CSR.
> [!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' }}
+ ```tsx {{ filename: 'app/dashboard/settings/layout.tsx' }}
import type { PropsWithChildren } from 'react'
import { Protect } from '@clerk/nextjs'
@@ -92,7 +92,7 @@ The following examples work for both SSR and CSR.
> [!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' }}
+ ```tsx {{ filename: 'app/dashboard/settings/layout.tsx' }}
import type { PropsWithChildren } from 'react'
import { auth } from '@clerk/nextjs/server'
@@ -121,7 +121,7 @@ The following examples work for both SSR and CSR.
- 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/page.tsx' }}
+ ```tsx {{ filename: 'app/dashboard/settings/page.tsx' }}
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
@@ -322,7 +322,7 @@ 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/Page.tsx' }}
+ ```tsx {{ filename: 'app/dashboard/settings/Page.tsx' }}
import { Protect } from '@clerk/nextjs'
export default function Page() {
@@ -347,7 +347,7 @@ 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/page.tsx' }}
+ ```tsx {{ filename: 'app/dashboard/settings/page.tsx' }}
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
@@ -363,7 +363,7 @@ You can pass a `role` the same way you can pass a `permission` in all the exampl
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' }}
+ ```tsx {{ filename: 'app/dashboard/settings/form.tsx' }}
'use client'
import { useAuth } from '@clerk/nextjs'
diff --git a/docs/quickstarts/astro.mdx b/docs/quickstarts/astro.mdx
index f1767b7ed2..c46a85d9c8 100644
--- a/docs/quickstarts/astro.mdx
+++ b/docs/quickstarts/astro.mdx
@@ -31,7 +31,7 @@ description: Add authentication and user management to your Astro app with Clerk
- ### Install `@clerk/astro`
+ ## Install `@clerk/astro`
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.
@@ -51,7 +51,7 @@ description: Add authentication and user management to your Astro app with Clerk
```
- ### Set your Clerk API keys
+ ## 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 in the Clerk Dashboard.
@@ -70,7 +70,7 @@ description: Add authentication and user management to your Astro app with Clerk
CLERK_SECRET_KEY={{secret}}
```
- ### Update `astro.config.mjs`
+ ## Update `astro.config.mjs`
To configure Clerk in your Astro app, you will need to update your `astro.config.mjs`.
@@ -90,7 +90,7 @@ description: Add authentication and user management to your Astro app with Clerk
})
```
- ### Add `clerkMiddleware()` to your app
+ ## Add `clerkMiddleware()` to your app
[`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:
@@ -105,7 +105,7 @@ description: Add authentication and user management to your Astro app with Clerk
```
1. By default, `clerkMiddleware()` will not protect any routes. All routes are public and you must opt-in to protection for routes. See the [`clerkMiddleware()` reference](/docs/references/astro/clerk-middleware) to learn how to require authentication for specific routes.
- ### Add TypeScript declarations
+ ## Add TypeScript declarations
Update the `env.d.ts` file in your `src/` directory to add type definitions for the `locals` added by the middleware.
@@ -118,7 +118,7 @@ description: Add authentication and user management to your Astro app with Clerk
///
```
- ### Add Clerk 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:
@@ -170,7 +170,7 @@ description: Add authentication and user management to your Astro app with Clerk
```
- ### Create your first user
+ ## Create your first user
Run your project with the following command:
diff --git a/docs/quickstarts/chrome-extension.mdx b/docs/quickstarts/chrome-extension.mdx
index fcc1493cae..fef197f686 100644
--- a/docs/quickstarts/chrome-extension.mdx
+++ b/docs/quickstarts/chrome-extension.mdx
@@ -21,19 +21,19 @@ description: Add authentication and user management to your Chrome Extension wit
- Create a new app with Plasmo
- Install `@clerk/chrome-extension`
- Set your Clerk API keys
- - Add `` and Clerk components to your app
+ - Add `` and Clerk components to your app
- Configure your app to use a consistent CRX ID
- Build, load, and test your Chrome Extension
- ### Configure your authentication options
+ ## Configure your authentication options
When creating your Clerk application in the Clerk Dashboard, your authentication options will depend on how you configure your Chrome Extension. Chrome Extensions can be used as a popup, a side panel, or in conjunction with a web app. Popups and side panels have limited authentication options. [Learn more about what options are available.](/docs/references/chrome-extension/overview#authenication-options)
This guide will use a popup.
- ### Create a new app using the Plasmo framework
+ ## Create a new app using the Plasmo framework
[Plasmo](https://docs.plasmo.com/framework) is a browser extension framework that includes hot reloading and creating development and production extension builds easily from the same code.
@@ -46,7 +46,7 @@ description: Add authentication and user management to your Chrome Extension wit
cd clerk-chrome-extension
```
- ### Install `@clerk/chrome-extension`
+ ## Install `@clerk/chrome-extension`
Clerk's [Chrome Extension SDK](/docs/references/chrome-extension/overview) gives you access to prebuilt components, React hooks, and helpers to make user authentication easier.
@@ -56,7 +56,7 @@ description: Add authentication and user management to your Chrome Extension wit
pnpm add @clerk/chrome-extension
```
- ### Set your Clerk API keys
+ ## Set your Clerk API keys
Plasmo offers [several options](https://docs.plasmo.com/framework/env) for environment variable files, as the same codebase can be used for development and production builds, as well as for targeting different browsers. This guide uses `.env.development` and `.env.chrome` files.
@@ -77,9 +77,9 @@ description: Add authentication and user management to your Chrome Extension wit
CLERK_FRONTEND_API={{fapi_url}}
```
- ### Add `` to your app
+ ## Add `` to your app
- All Clerk hooks and components must be children of the [``](/docs/components/clerk-provider) component, which provides active session and user context. Wrap your app in the `` component and pass your Publishable Key as a prop.
+
```tsx {{ filename: 'src/popup.tsx', mark: [1, [7, 11], 15, 19] }}
import { ClerkProvider } from '@clerk/chrome-extension'
@@ -107,7 +107,7 @@ description: Add authentication and user management to your Chrome Extension wit
export default IndexPopup
```
- ### Create a header with Clerk components
+ ## Create a header with Clerk components
You can control what content signed in and signed out users can see with Clerk's [prebuilt components](/docs/components/overview). Create a header with the following Clerk components. (With Chrome Extensions, you can also add this logic to a footer).
@@ -157,7 +157,7 @@ description: Add authentication and user management to your Chrome Extension wit
export default IndexPopup
```
- ### Update `` props for Chrome Extension navigation
+ ## Update `` props for Chrome Extension navigation
To avoid navigation errors, set the `afterSignOutUrl`, `signInFallbackRedirectUrl` and `signUpFallbackRedirectUrl` props for ``. Chrome Extensions don't use an `http` URL, such as `http://localhost:3000`. Instead, they use a `chrome-extension://` URL appended with an unique extension ID called a CRX ID. This URL is what you will pass to these props.
@@ -209,7 +209,7 @@ description: Add authentication and user management to your Chrome Extension wit
export default IndexPopup
```
- ### Create a consistent CRX ID for your extension
+ ## Create a consistent CRX ID for your extension
Chrome Extensions have a unique CRX ID that rotates by default, which can cause errors with the Clerk integration. To avoid these problems, ensure that you have a **consistent** CRX ID in both development and production for your extension by following these steps:
@@ -217,7 +217,7 @@ description: Add authentication and user management to your Chrome Extension wit
1. Select **Generate KeyPairs**.
1. Save the **Private Key** somewhere secure in case you need it in the future. Save the **Public Key** and the **CRX ID** for the next steps.
- ### Create an `.env.chrome` file to store your public key
+ ## Create an `.env.chrome` file to store your public key
Create an `.env.chrome` file and add your public key to it, as shown in the following example:
@@ -225,7 +225,7 @@ description: Add authentication and user management to your Chrome Extension wit
CRX_PUBLIC_KEY=
```
- ### Edit your `package.json` to use the new public key
+ ## Edit your `package.json` to use the new public key
Plasmo [uses the `package.json` to generate a `manifest.json` on build](https://docs.plasmo.com/framework#where-is-the-manifestjson-file), and allows for the use of environment variables in `package.json`.
@@ -246,7 +246,7 @@ description: Add authentication and user management to your Chrome Extension wit
}
```
- ### Use `pnpm dev` to start your development server and create a build
+ ## Use `pnpm dev` to start your development server and create a build
Plasmo facilitates Chrome Extension development by automatically "hot loading" the app whenever you save a changed file in the project. This ensures the `build/chrome-mv3-dev` folder remains up to date. Without the plugin, you would need to manually execute the build command and reload your Chrome Extension after each change. Plasmo automates this process, streamlining development.
@@ -256,7 +256,7 @@ description: Add authentication and user management to your Chrome Extension wit
pnpm dev
```
- ### Load your Chrome Extension into your Chromium-based browser
+ ## Load your Chrome Extension into your Chromium-based browser
To load your Chrome Extension, follow these steps:
@@ -266,7 +266,7 @@ description: Add authentication and user management to your Chrome Extension wit
1. Navigate to where your project is located and select the `build/chrome-mv3-dev` folder. Then select **Select**. Your extension will now be loaded and shown in the list of extensions.
1. Confirm that the ID shown in your extension matches the CRX ID you saved [earlier](#create-a-consistent-crx-id-for-your-extension).
- ### Test your Chrome Extension
+ ## Test your Chrome Extension
In your Chrome browser, open the extension popup. Ensure that the `` appears, and that selecting it opens the `` modal. Sign in and ensure that the `` appears in the header.
diff --git a/docs/quickstarts/expo.mdx b/docs/quickstarts/expo.mdx
index 65d5069244..1ef8b7da8e 100644
--- a/docs/quickstarts/expo.mdx
+++ b/docs/quickstarts/expo.mdx
@@ -17,61 +17,63 @@ description: Add authentication and user management to your Expo app with Clerk.
title: "Set up a Clerk application",
link: "/docs/quickstarts/setup-clerk",
icon: "clerk",
- }
+ },
+ {
+ title: "Create an Expo app",
+ link: "https://docs.expo.dev/get-started/create-a-project/",
+ icon: "expo",
+ },
]}
>
- - Create an Expo app
- Install `@clerk/expo`
- Set your Clerk API keys
- - Add ``
+ - Add ``
- Protect specific pages with authentication
- Use Clerk hooks to enable users to sign in and out
- ### Create an Expo app
+ ## Install `@clerk/clerk-expo`
+
+ Clerk's [Expo SDK](/docs/references/expo/overview) gives you access to prebuilt components, hooks, and helpers to make user authentication easier.
- Run the following commands to create a new Expo project and install the necessary dependencies:
+ Run the following command to install the SDK:
```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
-
+ npm install @clerk/clerk-expo
```
```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
+ yarn add @clerk/clerk-expo
```
```bash filename="terminal"
- pnpm dlx create-expo-app application-name --template blank && cd application-name
- pnpm dlx expo install react-dom react-native-web @expo/metro-runtime
+ pnpm add @clerk/clerk-expo
```
- ### Install `@clerk/clerk-expo`
+ ## Install `@clerk/types` (optional)
- Clerk's [Expo SDK](/docs/references/expo/overview) gives you access to prebuilt components, hooks, and helpers to make user authentication easier.
+ Clerk's `@clerk/types` package provides TypeScript type definitions.
- Run the following command to install the SDK:
+ Add the package to your project by running the following command:
```bash filename="terminal"
- npm install @clerk/clerk-expo
+ npm install @clerk/types
```
```bash filename="terminal"
- yarn add @clerk/clerk-expo
+ yarn add @clerk/types
```
```bash filename="terminal"
- pnpm add @clerk/clerk-expo
+ pnpm add @clerk/types
```
- ### Set your Clerk API keys
+ ## Set your Clerk API keys
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 in the Clerk Dashboard.
@@ -89,9 +91,11 @@ description: Add authentication and user management to your Expo app with Clerk.
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY={{pub_key}}
```
- ### Add `` to your root layout
+ ## Add `` to your root layout
+
+
- 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.
+ You must pass your Publishable Key as a prop to the `` component.
Clerk also provides [``](/docs/components/control/clerk-loaded), which won't render its children until the Clerk API has loaded.
@@ -118,143 +122,98 @@ description: Add authentication and user management to your Expo app with Clerk.
}
```
- ### 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 apps.
-
- Install `expo-secure-store`, which you'll use as your token cache:
-
-
- ```bash {{ filename: 'terminal' }}
- npm install expo-secure-store
- ```
-
- ```bash {{ filename: 'terminal' }}
- yarn add expo-secure-store
- ```
-
- ```bash {{ filename: 'terminal' }}
- pnpm add expo-secure-store
- ```
-
-
- When configuring a custom token cache, you must create an object that conforms to the `TokenCache` interface:
-
- ```tsx {{ filename: 'TokenCache' }}
- export interface TokenCache {
- getToken: (key: string) => Promise
- saveToken: (key: string, token: string) => Promise
- clearToken?: (key: string) => void
- }
- ```
-
- 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 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'
- import { ClerkProvider, ClerkLoaded } from '@clerk/clerk-expo'
- import { Slot } from 'expo-router'
-
- export default function RootLayout() {
- const tokenCache = {
- async getToken(key: string) {
- try {
- const item = await SecureStore.getItemAsync(key)
- if (item) {
- console.log(`${key} was used 🔐 \n`)
- } else {
- console.log('No values stored under key: ' + key)
- }
- return item
- } catch (error) {
- console.error('SecureStore get item error: ', error)
- await SecureStore.deleteItemAsync(key)
- return null
- }
- },
- async saveToken(key: string, value: string) {
- try {
- return SecureStore.setItemAsync(key, value)
- } catch (err) {
- return
- }
- },
- }
-
- const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!
-
- if (!publishableKey) {
- throw new Error('Add EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env')
- }
-
- return (
-
-
-
-
-
- )
- }
- ```
+ ## Configure the token cache
+
+ Clerk stores the active user's session token in memory by default. In Expo apps, the recommended way to store sensitive data, such as tokens, is by using `expo-secure-store` which encrypts the data before storing it.
+
+ To use `expo-secure-store` as your token cache:
+
+ 1. Run the following command to install the library:
+
+
+ ```bash {{ filename: 'terminal' }}
+ npm install expo-secure-store
+ ```
+
+ ```bash {{ filename: 'terminal' }}
+ yarn add expo-secure-store
+ ```
+
+ ```bash {{ filename: 'terminal' }}
+ pnpm add expo-secure-store
+ ```
+
+ 1. In your root directory, create a `cache.ts` file and add the following code:
+ ```tsx {{ filename: 'cache.ts' }}
+ import * as SecureStore from 'expo-secure-store'
+ import { Platform } from 'react-native'
+ import { TokenCache } from '@clerk/clerk-expo/dist/cache'
+
+ const createTokenCache = (): TokenCache => {
+ return {
+ getToken: async (key: string) => {
+ try {
+ const item = await SecureStore.getItemAsync(key)
+ if (item) {
+ console.log(`${key} was used 🔐 \n`)
+ } else {
+ console.log('No values stored under key: ' + key)
+ }
+ return item
+ } catch (error) {
+ console.error('secure store get item error: ', error)
+ await SecureStore.deleteItemAsync(key)
+ return null
+ }
+ },
+ saveToken: (key: string, token: string) => {
+ return SecureStore.setItemAsync(key, token)
+ },
+ }
+ }
+
+ // SecureStore is not supported on the web
+ export const tokenCache = Platform.OS !== 'web' ? createTokenCache() : undefined
+ ```
+ 1. Update your root layout to use the token cache:
+ ```tsx {{ filename: 'app/_layout.tsx', mark: [3, 13] }}
+ import { tokenCache } from '@/cache'
+ import { ClerkProvider, ClerkLoaded } from '@clerk/clerk-expo'
+ import { Slot } from 'expo-router'
+
+ export default function RootLayout() {
+ const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!
+
+ if (!publishableKey) {
+ throw new Error('Add EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env')
+ }
+
+ return (
+
+
+
+
+
+ )
+ }
+ ```
> [!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.
- ### Protect your pages
-
- 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**.
-
- To get started, create a `(home)` route group with the following layout file:
-
- ```tsx filename="app/(home)/_layout.tsx"
- import { Stack } from 'expo-router/stack'
-
- export default function Layout() {
- return
- }
- ```
-
- Then, in the same folder, create an `index.tsx` file and add the following code. It displays the user's email if they're signed in, or sign-in and sign-up links if they're not:
+ ## Add sign-up and sign-in pages
- ```tsx filename="app/(home)/index.tsx"
- import { SignedIn, SignedOut, useUser } from '@clerk/clerk-expo'
- import { Link } from 'expo-router'
- import { Text, View } from 'react-native'
+ Clerk currently only supports [control components](/docs/components/overview#what-are-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.
- export default function Page() {
- const { user } = useUser()
+ ### Layout page
- return (
-
-
- Hello {user?.emailAddresses[0].emailAddress}
-
-
-
- Sign In
-
-
- Sign Up
-
-
-
- )
- }
- ```
-
- ### Add `sign-up` and `sign-in` pages
+ First, protect your 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 the Clerk 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.
+ 1. Create an `(auth)` [route group](https://docs.expo.dev/router/layouts/#groups). This will group your sign-up and sign-in pages.
+ 1. In the `(auth)` group, create a `_layout.tsx` file.
+ 1. Paste the following code. The [`useAuth()`](/docs/references/react/use-auth) hook is used to access the user's authentication state. If the user is already signed in, they will be redirected to the home page.
- 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:
-
- ```tsx filename="/app/(auth)/_layout.tsx"
+ ```tsx filename="app/(auth)/_layout.tsx"
import { Redirect, Stack } from 'expo-router'
import { useAuth } from '@clerk/clerk-expo'
@@ -269,13 +228,14 @@ 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.
+ 1. In the `(auth)` group, create a `sign-up.tsx` file.
+ 1. Paste the following code. The [`useSignUp()`](/docs/references/react/use-sign-up) hook is used to create a sign-up flow. The user can sign up using their email and password and will receive an email verification code to confirm their email.
- ```tsx filename="/app/(auth)/sign-up.tsx"
+ ```tsx {{ filename: 'app/(auth)/sign-up.tsx', collapsible: true }}
import * as React from 'react'
- import { TextInput, Button, View } from 'react-native'
+ import { Text, TextInput, Button, View } from 'react-native'
import { useSignUp } from '@clerk/clerk-expo'
import { useRouter } from 'expo-router'
@@ -288,85 +248,100 @@ description: Add authentication and user management to your Expo app with Clerk.
const [pendingVerification, setPendingVerification] = React.useState(false)
const [code, setCode] = React.useState('')
+ // Handle submission of sign-up form
const onSignUpPress = async () => {
- if (!isLoaded) {
- return
- }
+ if (!isLoaded) return
+ // Start sign-up process using email and password provided
try {
await signUp.create({
emailAddress,
password,
})
+ // Send user an email with verification code
await signUp.prepareEmailAddressVerification({ strategy: 'email_code' })
+ // Set 'pendingVerification' to true to display second form
+ // and capture OTP code
setPendingVerification(true)
- } catch (err: any) {
+ } catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}
- const onPressVerify = async () => {
- if (!isLoaded) {
- return
- }
+ // Handle submission of verification form
+ const onVerifyPress = async () => {
+ if (!isLoaded) return
try {
- const completeSignUp = await signUp.attemptEmailAddressVerification({
+ // Use the code the user provided to attempt verification
+ const signUpAttempt = await signUp.attemptEmailAddressVerification({
code,
})
- if (completeSignUp.status === 'complete') {
- await setActive({ session: completeSignUp.createdSessionId })
+ // If verification was completed, set the session to active
+ // and redirect the user
+ if (signUpAttempt.status === 'complete') {
+ await setActive({ session: signUpAttempt.createdSessionId })
router.replace('/')
} else {
- console.error(JSON.stringify(completeSignUp, null, 2))
+ // If the status is not complete, check why. User may need to
+ // complete further steps.
+ console.error(JSON.stringify(signUpAttempt, null, 2))
}
- } catch (err: any) {
+ } catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}
+ if (pendingVerification) {
+ return (
+ <>
+ Verify your email
+ setCode(code)}
+ />
+
+ >
+ )
+ }
+
return (
- {!pendingVerification && (
- <>
- setEmailAddress(email)}
- />
- setPassword(password)}
- />
-
- >
- )}
- {pendingVerification && (
- <>
- setCode(code)} />
-
- >
- )}
+ <>
+ Sign up
+ setEmailAddress(email)}
+ />
+ setPassword(password)}
+ />
+
+ >
)
}
```
- #### 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.
+ 1. In the `(auth)` group, create a `sign-in.tsx` file.
+ 1. Paste the following code. The [`useSignIn()`](/docs/references/react/use-sign-in) hook is used to create a sign-in flow. The user can sign in using email address and password, or navigate to the sign-up page.
- ```tsx filename="/app/(auth)/sign-in.tsx"
+ ```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
import { useSignIn } from '@clerk/clerk-expo'
import { Link, useRouter } from 'expo-router'
import { Text, TextInput, Button, View } from 'react-native'
@@ -379,26 +354,30 @@ description: Add authentication and user management to your Expo app with Clerk.
const [emailAddress, setEmailAddress] = React.useState('')
const [password, setPassword] = React.useState('')
+ // Handle the submission of the sign-in form
const onSignInPress = React.useCallback(async () => {
- if (!isLoaded) {
- return
- }
+ if (!isLoaded) return
+ // Start the sign-in process using the email and password provided
try {
const signInAttempt = await signIn.create({
identifier: emailAddress,
password,
})
+ // If sign-in process is complete, set the created session as active
+ // and redirect the user
if (signInAttempt.status === 'complete') {
await setActive({ session: signInAttempt.createdSessionId })
router.replace('/')
} else {
- // See https://clerk.com/docs/custom-flows/error-handling
- // for more info on error handling
+ // If the status isn't complete, check why. User might need to
+ // complete further steps.
console.error(JSON.stringify(signInAttempt, null, 2))
}
- } catch (err: any) {
+ } catch (err) {
+ // See https://clerk.com/docs/custom-flows/error-handling
+ // for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}, [isLoaded, emailAddress, password])
@@ -408,16 +387,16 @@ description: Add authentication and user management to your Expo app with Clerk.
setEmailAddress(emailAddress)}
/>
setPassword(password)}
/>
-
+ Don't have an account?
@@ -431,7 +410,56 @@ description: Add authentication and user management to your Expo app with Clerk.
For more information about building these custom flows, including guided comments in the code examples, see the [Build a custom email/password authentication flow](/docs/custom-flows/email-password) guide.
- ### Create your first user
+ ## Conditionally render content
+
+ 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**.
+
+ To get started:
+
+ 1. Create a `(home)` route group.
+ 1. In the `(home)` group, create a `_layout.tsx` file.
+ 1. Paste the following code.
+
+ ```tsx filename="app/(home)/_layout.tsx"
+ import { Stack } from 'expo-router/stack'
+
+ export default function Layout() {
+ return
+ }
+ ```
+
+ Then, in the same folder, create an `index.tsx` file with the following code. It displays the user's email if they're signed in, or sign-in and sign-up links if they're not:
+
+ ```tsx filename="app/(home)/index.tsx"
+ import { SignedIn, SignedOut, useUser } from '@clerk/clerk-expo'
+ import { Link } from 'expo-router'
+ import { Text, View } from 'react-native'
+
+ export default function Page() {
+ const { user } = useUser()
+
+ return (
+
+
+ Hello {user?.emailAddresses[0].emailAddress}
+
+
+
+ Sign in
+
+
+ Sign up
+
+
+
+ )
+ }
+ ```
+
+ ## Create your first user
Run your project with the following command:
diff --git a/docs/quickstarts/express.mdx b/docs/quickstarts/express.mdx
index dd3f092403..4ce49c5754 100644
--- a/docs/quickstarts/express.mdx
+++ b/docs/quickstarts/express.mdx
@@ -33,7 +33,7 @@ description: Learn how to use Clerk to quickly and easily add secure authenticat
Learn how to integrate Clerk into your Express backend for secure user authentication and management. This guide covers backend implementation only and requires a Clerk frontend SDK in order for any of this to work.
- ### Install `@clerk/express`
+ ## Install `@clerk/express`
Clerk's [Express SDK](/docs/references/express/overview) ships with a variety of helpers for the backend to make user authentication easier.
@@ -53,7 +53,7 @@ Learn how to integrate Clerk into your Express backend for secure user authentic
```
- ### Set your Clerk API keys
+ ## Set your Clerk API keys
Add the following keys to your `.env` file. These keys can always be retrieved from the [**API keys**](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard.
@@ -88,7 +88,7 @@ Learn how to integrate Clerk into your Express backend for secure user authentic
```
- ### Add `clerkMiddleware()` to your application
+ ## Add `clerkMiddleware()` to your application
The [`clerkMiddleware()`](/docs/references/express/overview#clerk-middleware) function checks the request's cookies and headers for a session JWT and, if found, attaches the [`Auth`](/docs/references/nextjs/auth-object#auth-object){{ target: '_blank' }} object to the `request` object under the `auth` key.
@@ -106,7 +106,7 @@ Learn how to integrate Clerk into your Express backend for secure user authentic
})
```
- ### Protect your routes using `requireAuth()`
+ ## Protect your routes using `requireAuth()`
To protect your routes, use the [`requireAuth()`](/docs/references/express/overview#require-auth) middleware. This middleware functions similarly to `clerkMiddleware()`, but also protects your routes by redirecting unauthenticated users to the sign-in page.
diff --git a/docs/quickstarts/fastify.mdx b/docs/quickstarts/fastify.mdx
index 1d760b5f72..9e146a2029 100644
--- a/docs/quickstarts/fastify.mdx
+++ b/docs/quickstarts/fastify.mdx
@@ -39,7 +39,7 @@ Learn how to integrate Clerk into your Fastify backend for secure user authentic
> This guide uses ECMAScript Modules (ESM). To use ESM in your project, you must include `"type": "module"` in your `package.json`.
- ### Install `@clerk/fastify`
+ ## Install `@clerk/fastify`
[Clerk's Fastify SDK](https://github.com/clerk/javascript/tree/main/packages/fastify) provides a range of backend utilities to simplify user authentication and management in your application.
@@ -59,7 +59,7 @@ Learn how to integrate Clerk into your Fastify backend for secure user authentic
```
- ### Set your Clerk API keys
+ ## 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 in the Clerk Dashboard.
@@ -78,7 +78,7 @@ Learn how to integrate Clerk into your Fastify backend for secure user authentic
CLERK_SECRET_KEY={{secret}}
```
- ### Configure `clerkPlugin` for all routes
+ ## Configure `clerkPlugin` for all routes
The `clerkPlugin` is a Fastify plugin provided by Clerk to integrate authentication into your Fastify application. To ensure that Clerk's authentication and user management features are applied across your Fastify application, configure the `clerkPlugin` to handle all routes or limit it to specific ones.
@@ -108,7 +108,7 @@ Learn how to integrate Clerk into your Fastify backend for secure user authentic
start()
```
- ### Use `getAuth()` to access the auth state and protect routes
+ ## Use `getAuth()` to access the auth state and protect routes
The following example uses [`getAuth()`](/docs/references/nextjs/get-auth){{ target: '_blank' }} to retrieve the `userId`, which is used to protect the route and is passed to [`clerkClient.users.getUser()`](/docs/references/backend/user/get-user){{ target: '_blank' }} to retrieve the current user's `User` object.
@@ -150,7 +150,7 @@ Learn how to integrate Clerk into your Fastify backend for secure user authentic
```
-### Configure `clerkPlugin` for specific routes
+## Configure `clerkPlugin` for specific routes
If you want to use Clerk for specific pages only, you can register the plugin for specific routes. In the following example, the routes are split into protected and public routes.
diff --git a/docs/quickstarts/ios.mdx b/docs/quickstarts/ios.mdx
index 0cb4ffdf5a..fd19fc1cd5 100644
--- a/docs/quickstarts/ios.mdx
+++ b/docs/quickstarts/ios.mdx
@@ -23,17 +23,17 @@ description: Add authentication and user management to your iOS app with Clerk.
- ### Create an iOS Project
+ ## Create an iOS Project
To get started using Clerk with iOS, create a new project in Xcode. Select SwiftUI as your interface and Swift as your language.
See the [Xcode documentation](https://developer.apple.com/documentation/xcode/creating-an-xcode-project-for-an-app) for more information.
- ### Install the Clerk iOS SDK
+ ## Install the Clerk iOS SDK
Follow [the Swift Package Manager instructions](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app) to install Clerk as a dependency.
When prompted for the package URL, enter [https://github.com/clerk/clerk-ios](https://github.com/clerk/clerk-ios). Be sure to add the package to your target.
- ### Load Clerk
+ ## Load Clerk
To use Clerk in your app, you must first configure and load `Clerk`.
@@ -69,7 +69,7 @@ description: Add authentication and user management to your iOS app with Clerk.
}
```
- ### Conditionally render content
+ ## Conditionally render content
To render content based on whether a user is authenticated or not:
@@ -97,9 +97,9 @@ description: Add authentication and user management to your iOS app with Clerk.
}
```
- ### Create views for sign-up and sign-in
+ ## Create views for sign-up and sign-in
- #### `SignUpView`
+ ### `SignUpView`
The following example creates a `SignUpView` that allows users to sign up using their email address and password, and sends an email verification code to confirm their email address.
@@ -165,7 +165,7 @@ description: Add authentication and user management to your iOS app with Clerk.
}
```
- #### `SignInView`
+ ### `SignInView`
The following example creates a `SignInView` that allows users to sign in using their email address and password.
@@ -205,7 +205,7 @@ description: Add authentication and user management to your iOS app with Clerk.
}
```
- #### `SignUpOrSignInView`
+ ### `SignUpOrSignInView`
Finally, create a `SignUpOrSignInView` container view that allows users to switch between sign up and sign in.
@@ -238,7 +238,7 @@ description: Add authentication and user management to your iOS app with Clerk.
}
```
- ### Allow users to sign up or sign in
+ ## Allow users to sign up or sign in
Go back to your `ContentView` and render your newly created `SignUpOrSignInView` when the user isn't signed in.
@@ -261,7 +261,7 @@ description: Add authentication and user management to your iOS app with Clerk.
}
```
- ### Allow users to sign out
+ ## Allow users to sign out
Finally, provide users with a way to sign out of your app:
diff --git a/docs/quickstarts/javascript.mdx b/docs/quickstarts/javascript.mdx
index 9feb90d979..4d917d89bc 100644
--- a/docs/quickstarts/javascript.mdx
+++ b/docs/quickstarts/javascript.mdx
@@ -36,7 +36,7 @@ Use the following tabs to choose your preferred method.
- ### Set up a JavaScript app using Vite
+ ## Set up a JavaScript app using Vite
To install Clerk's JavaScript SDK, you need to use a bundler like [Vite](https://vitejs.dev/) or [Webpack](https://webpack.js.org/).
@@ -65,7 +65,7 @@ Use the following tabs to choose your preferred method.
```
- ### Install `@clerk/clerk-js`
+ ## Install `@clerk/clerk-js`
Run the following command to add the JavaScript SDK to your project:
@@ -83,7 +83,7 @@ Use the following tabs to choose your preferred method.
```
- ### Set your Clerk API keys
+ ## Set your Clerk API keys
It's recommended to use environment variables to store your Clerk Publishable Key. In JavaScript projects, you can add these values in an `.env` file and load them into your app using a package like [`dotenv`](https://www.npmjs.com/package/dotenv). For Vite projects, environment variables in an `.env` file at the project root are automatically accessible through the [`import.meta.env` object](https://vitejs.dev/guide/env-and-mode.html#env-variables).
@@ -109,7 +109,7 @@ Use the following tabs to choose your preferred method.
const clerkPubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
```
- ### Initialize Clerk
+ ## Initialize Clerk
To initialize Clerk, import the `Clerk` class and instantiate it with your Clerk Publishable Key. Then, call the `load()` method, as shown in the following example:
@@ -127,7 +127,7 @@ Use the following tabs to choose your preferred method.
> [!NOTE]
> Calling the `load()` method initializes Clerk. For more information on the `load()` method and what options you can pass to it, see the [reference documentation](/docs/references/javascript/clerk/clerk#load).
- ### Add Clerk components to your app
+ ## Add Clerk components to your app
Clerk's [prebuilt components](/docs/components/overview) are the easiest way to add authentication and user management to your app. They come styled out-of-the-box and are customizable to fit your app's design.
@@ -183,7 +183,7 @@ Use the following tabs to choose your preferred method.