# Clerk Blog — Guides — Page 6

# Understanding and Properly Using React Global State
URL: https://clerk.com/blog/understanding-and-properly-using-react-global-state.md
Date: 2023-04-14
Category: Guides
Description: Explore the benefits of global state and discover two methods to implement it: the React context API and the Clerk React context API component.

React global state refers to the data or state that all components in a React application share. This data is typically stored in a global object, such as a state manager like Redux or the React context API, and it can be accessed by any component in the application that needs it.

By using global state, React components can communicate with each other and share data even if they're not directly connected in the component hierarchy. This allows data in a React application to be better organized and managed.

This article starts by explaining the benefits of using global state in React and when it's best to use it. It then shows you how to implement global state in React using two methods: a custom implementation of a React context using the [context API](https://reactjs.org/docs/context.html) and an implementation of the [Clerk React context API component](/docs/reference/clerk-react/clerkprovider). Lastly, it considers when each of these methods is most useful.

> For comprehensive React authentication with built-in state management, [learn more about our React support](/react-authentication).

The code for the tutorial can be found in [this GitHub repository](https://github.com/pjcjonas/clerk-dev-global-state-with-context).

## Why Use React Global State

As mentioned, using global state in a React application can help to make your code more organized, manageable, and performant.

Global state makes managing shared data easier. Storing all of an application's state in a global object makes it easier to manage from a single location rather than having to pass data down through the component hierarchy. It can make code easier to understand and maintain.

It also enables communication between components that are not directly connected. Any component in an application can access and update the shared data even if it's not directly connected to the component that initially stored the data. This can be useful for triggering updates or changes in other parts of the application.

Lastly, using global state improves performance. Because the global state is stored in a centralized location, components that need the same data can access it from the global state as opposed to each component having to fetch the data separately. This can improve the performance of an application by reducing the amount of data that needs to be fetched and processed.

## When to Use React Global State

Using React global state is not a must, but it can be a useful tool in certain situations.

It's most useful when data is needed by multiple components in an application because it ensures that these components all have access to the latest and most up-to-date version of the data. For example, for a [login form](/blog/building-a-react-login-page-template) that's used by multiple components, the global state could be used to store the user's authentication status and other information, which could then be accessed by any component that needs it.

Another common use case for React global state is to allow components to update the data in the global state. For example, a shopping cart application could use the global state to store a list of items in the cart and then allow any component that displays the cart items to update the list when a user adds or removes an item. It allows any component that displays the cart items to always have the latest version of the data.

## Prerequisites

To follow along with this tutorial, you'll need the following prerequisites installed on your system:

- Node.js and npm: Vite is built on top of Node.js and npm, so you must have these installed to use the npm create command.
- TypeScript: Vite supports TypeScript out of the box, but you must have TypeScript installed to create a React TypeScript project with Vite.

## Method 1: Using the React Context API to Implement Global State

In this section, you'll learn the basic structure for creating a globally managed state object using a context provider to get and update information without creating a dependency chain of properties.

### Cloning and Setting Up the Project

Clone the project from [GitHub](https://github.com/pjcjonas/clerk-dev-global-state-with-context).

Below is a directory tree of the cloned project. Make sure that you are on the `main` branch but running `git checkout main` in the project root.

```bash
|..
├── index.html
├── package.json
├── README.md
├── src                                     # Main application source code
|  ├── app-context                          # Application context
|  |   └── user-context.tsx                 # Main application user context
|  |   └── user-context-provider.tsx        # Application context provider
|  ├── components                           # UI Components
|  |   └── AdminPage                        # Admin page locked by a user object
|  |       └── index.tsx
|  |   └── LoginStatus                      # Login status display component
|  |       └── index.tsx
|  |   └── SignInSignOut                    # Log in and log out buttons
|  |       └── index.tsx
|  |   └── WelcomePage                      # Landing page
|  |       └── index.tsx
|  ├── App.tsx
|  ├── assets
|  ├── main.tsx
|  └── vite-env.d.ts                        # ViteJs env type declarations
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts                          # ViteJs configuration
```

Once the project has been cloned, you need to install the project's node modules using `npm i` or `npm install`. To test the React app, use `npm run dev` to start the server at [http://localhost:5173](http://localhost:5173).

Once the server is running, the following should appear in the terminal window to indicate that the server is running correctly:

```bash
VITE v4.0.3  ready in 3140 ms

➜  Local:   http://localhost:5173/
➜  Network: use --host to expose
➜  press h to show help
```

If your web browser does not open automatically, open the browser and enter the following URL in the address bar: `http://localhost:5173/welcome`. Here is what will be visible in the browser:

![Basic welcome page with sign-in button](./d8ab2c29394a05c65abf4d9bcbc70c8a8f2eaea7-1082x722.png)

### Declaring the Context API and Setting the Initial Application

Let's have a look how this first example is configured in `~./src/app-context`. This directory has two files. The first is **user-context.tsx**, which is where the React context state is first declared, then initialized with default values, and lastly exported for global use when the context provider wraps the global application node:

```typescript
// FILE - ./src/app-context/user-context.tsx
// ----------------------------------

import React from 'react'

export interface UserContract {
  id?: number
  username?: string
  firstName?: string
  email?: string
}

// The dummy user object used for this example
export const DummyUser: UserContract = {
  id: 1,
  username: 'MyUserName',
  firstName: 'John',
  email: 'john@doe.com',
}

/**
 * Application state interface
 */
export interface AppState {
  user?: UserContract
  updateState: (newState: Partial<AppState>) => void
}

/**
 * Default application state
 */
const defaultState: AppState = {
  user: {},
  updateState: (newState?: Partial<AppState>) => {},
}

/**
 * Creating the Application state context for the provider
 */
export const UserContext = React.createContext<AppState>(defaultState)
```

First, the `AppState` interface is declared containing the `user` object type and `updateState` function. Included on the `AppState` interface is the `updateState` method, which will accept a partial state object that allows specific sections of the user object to be updated.

After the interface has been declared, the default state is created and set to the type of the `AppState` and then defaulted. In this case, it's an empty object.

Finally, the React context is created and exported as `UserContext` with the [React.createContext](https://beta.reactjs.org/reference/react/createContext) SDK API.

### Adding React Global State Using the Context Provider

Inside **./src/app-context/user-context-provider.tsx** is `UserContextProvider`. This is where the global state and provider methods like `updateState` get assigned.

```typescript
// FILE - ./src/app-context/user-context-provider.tsx
// ----------------------------------

import React, { useState } from 'react'
import { AppState, UserContext } from './user-context'

interface Props {
  children: React.ReactNode
}

/**
 * The main context provider
 */
export const UserContextProvider: React.FunctionComponent<Props> = (props: Props): JSX.Element => {
  /**
   * Using react hooks, set the default state
   */
  const [state, setState] = useState({})

  /**
   * Declare the update state method that will handle the state values
   */
  const updateState = (newState: Partial<AppState>) => {
    setState({ ...state, ...newState })
  }

  /**
   * Context wrapper that will provider the state values to all its children nodes
   */
  return (
    <UserContext.Provider value={{ ...state, updateState }}>{props.children}</UserContext.Provider>
  )
}
```

To make the global state available to the entire application, you need to provide it as the main parent wrapper to all the child nodes. This is done by setting the `<App />` component as the child node of `UserContextProvider`:

```typescript
// FILE - ./src/main.tsx
// ----------------------------------

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { UserContextProvider } from './app-context/user-context-provider'

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    // Context provider wrapper
    <UserContextProvider>
      // Every child node will have access to the UserContext state.
      <App />
    </UserContextProvider>
  </React.StrictMode>,
)
```

### Making Use of the Global State Using the Context API

At this stage, the context can be included in the component using the [useContext](https://beta.reactjs.org/reference/react/useContext) React hook whenever it needs to be used:

```typescript
// FILE - ./src/App.tsx
// ----------------------------------

const App: React.FunctionComponent = (): JSX.Element => {
  /*
   * Using react's useContext to tell the component which context to use,
   * the relevant state properties can be extracted. In the example below,
   * the user object, clerk object and the updateState method is made available.
   */
  const { user, clerk, updateState } = useContext(UserContext)

  /* Application logic ... */

  return (
    <Container maxWidth="sm">
      <BrowserRouter>{/* Application components */}</BrowserRouter>
    </Container>
  )
}
```

## Method 2: Using Clerk's Global State Manager to Implement Global State

Now, let's consider another method that you can use to achieve global state. Clerk offers its own context provider called [ClerkProvider](/docs/reference/clerk-react/clerkprovider). It provides a wrapper for a ReactJS application that handles the user session and state as well as a list of child components and hooks for use in your application.

### Setting Up Clerk

First, you need to create a Clerk application.

Clerk handles authentication requests when users sign in. For Clerk to know which sign-in session belongs to which client account, there needs to be a unique reference between the React application and the Clerk API. This is achieved by setting up an application on the Clerk platform to get a unique application key against which the sign in will occur.

1. [Sign up](https://dashboard.clerk.com/sign-up) for a free trial account.

![Sign up for a Clerk account](./76635162bbe2076eff6a14cc9c8de347dea9c1c2-1042x717.png)

2. [Create](https://dashboard.clerk.com/apps/new) a Clerk application from the dashboard.

![Create a Clerk application](./e3ce61718a7c64b1f6e058c92f3d982677c1ec18-1069x932.png)

3. On the application settings page, go to **API Keys** and select the **React** framework from the dropdown list.

![Select React from the dropdown list](./fb4af61da9e756b05d13dccc9837d0456a3934fb-1382x873.png)

4. Copy the API key shown on the page as this will be used in the project.

![Copy the API key from the key field listed on the page](./1f0d428805d0dbf681c9c7997874df9a68718d48-1372x887.png)

### Clone the Repo

Now, return to the repository you cloned for the previous example and check out the Clerk branch by running the following commands:

1. `~/$: cd ./clerk-dev-global-state-with-context`
2. `~/clerk-dev-global-state-with-context/$: git checkout feat/main-clerk_devi`

Here's the file structure for the project once the `main-clerk_dev` branch has been checked out:

```bash
.
├── index.html
├── package.json
├── README.md
├── src                 # Main application source code
|  ├── App.tsx          # Application main component
|  ├── components       # Application components
|  |  ├── AdminPage     # Admin page requires login session
|  |  ├── common        # Holds the application routes
|  |  ├── LoginStatus   # Uses ClerkProvider context to show login status
|  |  └── WelcomePage   # Welcome page that incorporates login status component
|  ├── main.tsx         # Application render component
|  └── vite-env.d.ts    # ViteJs env type declarations
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts      # ViteJs configuration
```

## Implement Clerk React

In this section, you'll implement the Clerk context provider as well as the Clerk React components. These components help make it simple to manage content based on login status. Wrapping elements with the node list `<SingedIn />` means that they will only show when the user is signed in, and conversely, wrapping them with `<SignedOut />` will only display child nodes and components when the user is out.

First, you need to open the **main.tsx** file and wrap the `<App />` component with the `<ClerkProvider />`, as shown below:

```typescript
// FILE - ./src/main.tsx
// ----------------------------------

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { ClerkProvider } from '@clerk/clerk-react'

const clerkApiKey = import.meta.env.VITE_CLERK_API_URI

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    // The clerk provider wrapper for React Applications.
    <ClerkProvider frontendApi={clerkApiKey}>
      <App />
    </ClerkProvider>
  </React.StrictMode>,
)
```

In the code sample above, the `VITE_CLERK_API_URI` environment variable is assigned to the `clerkApiKey`, which is the key that you got in the section on setting up Clerk. You then add it to the Clerk provider context wrapper (`<ClerkProvider frontendApi={clerkApiKey}>`) used by the Clerk React components.

The code block below shows the `main.tsx` component, which is where you would have the main entry into your applications via the `<App />` component. Using the ClerkProvider React component, wrap your app component with it. This will set the application component as a child element. Next, add the `clerkApiKey` to the `ClerkProvider component using the `publishableKey\` property.

Now with the application component as the child of the Clerk provider component, all the user components will be passed down into each child component.

```typescript
// FILE - ./src/main.tsx

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { ClerkProvider } from '@clerk/clerk-react'
import { BrowserRouter } from 'react-router-dom'

const clerkApiKey = import.meta.env.VITE_CLERK_API_URI
console.log(clerkApiKey)

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <BrowserRouter>
      <ClerkProvider publishableKey={clerkApiKey}>
        <App />
      </ClerkProvider>
    </BrowserRouter>
  </React.StrictMode>,
)
```

## Clerk React Components and Hooks

Clerk has [numerous components and functions](/docs/authentication/using-clerk-components) that can be used inside child components of the `<ClerkProvider />` context provider component, allowing for simple implementation and secure authentication for React applications.

As long as all the components that utilize the Clerk hooks and components are child nodes of the `<ClerkProvider />`, those components and hooks will interact with the user session and state.

### Clerk useUser Hook

You can use the [Clerk `useUser()` hook](/docs/nextjs/useuser) to get the current user state in the form of an object `{ isLoaded, isSignedIn, user }`. The `isLoaded` property checks to see if Clerk has finished requesting the user session, `isSignedIn` determines if the current user has signed in, and `user` contains the user info for the current user session.

```typescript
// FILE - ./src/components/LoginStatus/index.tsx

import React from 'react'
import { Typography } from '@mui/material'
import { useUser } from '@clerk/clerk-react'

export const LoginStatus: React.FunctionComponent = (): JSX.Element => {
  const { user } = useUser() // << Implementation
  return (
    <React.Fragment>
      <Typography variant="body1">
        Login status: // Get the user's first name
        {user ? `Signed in as ${user.firstName}` : 'You are signed out'}
      </Typography>
    </React.Fragment>
  )
}
```

### Clerk SignIn, SignedIn, and SignedOut Components

The routes file below shows the use of three Clerk react components. [`SignIn`](/docs/nextjs/signin), [`SignedIn`](/docs/component-reference/signed-in), and [`SignedOut`](/docs/component-reference/signed-out):

```tsx {{ prettier: false }}
// FILE - ./src/components/common/routes.tsx

import { Route, Routes } from 'react-router-dom'
// ...

export const MainRoutes: React.FunctionComponent = (): JSX.Element => {
  //...
  <Route
    path="/admin"
    element={
      <React.Fragment>
        <SignedIn>
          <AdminPage />
        </SignedIn>
        <SignedOut>
          <SignIn afterSignInUrl="/admin" />
        </SignedOut>
      </React.Fragment>
    }
  />
  // ...
}
```

The Clerk components are placed as children to the ClerkProvider to allow you to determine which content to show based on login status.

When the `SignIn` component (`<SignIn afterSignInUrl="/admin" />`) is rendered, it displays the Clerk user sign-in modal on the React application. The optional parameter `afterSignInUrl` means the application will update the URL of the page once login is successful.

![Clerk sign in modal rendered](./9bfbf4436f6dbbb77ae43cc3c754919ee25f3b4a-849x661.png)

`<SignedIn>` and `<SignedOut>` act as conditional wrappers. The current sign-in status will determine whether child components will or will not render. So if a component is wrapped with `<SignedOut> {... Child Components} </SignedOut>`, those components will only show if the user is signed out. The same applies to the `SignedIn` component.

### Clerk User Metadata

Clerk lets you store and manage [user metadata](/docs/users/user-metadata) in a central location. This data can include information such as user preferences, settings, and usage statistics. Using Clerk lets you easily access and update this information as needed without constantly having to ask users for it, resulting in a better user experience.

By having all of this information in one place, developers can tailor their app or website to individual users' needs and preferences. This can help increase engagement and retention as users are more likely to use a personalized app or website.

Three types of user metadata can be configured: private, public, and unsafe.

[Private metadata](/docs/users/user-metadata#private-metadata) is set and configured on the backend. It's not accessible via the ClerkJS [frontend API](https://clerk.com/docs/reference/frontend-api) to ensure that no sensitive information is visible on the client side of the application that could potentially compromise personal information. If any private data needs to be accessible from the frontend API, the user to whom the data belongs must give consent.

[Public metadata](/docs/users/user-metadata#public-metadata) is also set on the backend but is visible in the ClerkJS frontend API as read-only properties for use on the client side. None of these values can be changed directly from the client side though. The only way to change these values is to update the metadata using the `users.updateUsers` method.

[Unsafe metadata](/docs/users/user-metadata#unsafe-metadata) is set by both the frontend and backend APIs. For example, when a user signs up via the frontend API, custom fields can be set and saved to the user object on the backend, and the same can be done the other way around. These attributes and values can also be set after the user has signed in to the application and then be persisted on the user object with `users.updateUsers`.

See a code sample of this below:

```javascript
// Source: https://clerk.com/docs/users/user-metadata#unsafe-metadata

import { useUser } from '@clerk/nextjs'

const updateMetadata = async () => {
  const { user } = useUser()
  const data = 'Data to store unsafely'

  try {
    const response = await user.update({
      unsafeMetadata: { data },
    })
    if (response) {
      console.log('res', response)
    }
  } catch (err) {
    console.error('error', err)
  }
}
```

## React Context API vs. Clerk Context Provider

You've seen how to use both methods to handle global state in React, so how do they compare?

Clerk's state management solution is more suited for larger, more complex applications that need a more powerful and flexible state management solution, while the React Context API is better for smaller applications that don't need as much state management functionality.

So, use the React Context API if:

- you need to share a small amount of state between a few components;
- you don't need to manage complex state dependencies or updates; or
- you want a lightweight solution for state management that doesn't add too much overhead to an application.

In contrast, use Clerk if:

- you need a centralized store for the application's state;
- you need to handle complex state management scenarios that involve nested data structures or multiple dependencies;
- you want to easily manage state updates and subscriptions across different components in an application; or
- you want a simple, intuitive API for state management that's easy to understand and use.

Are you interested in trying Clerk? You can [sign up](https://dashboard.clerk.com/sign-up) for a free tier for POCs as well as individual and private use, or you could look into the [paid solutions](/pricing) for large-scale client bases and enterprise-level tools.

---

# Implementing reCAPTCHA in React
URL: https://clerk.com/blog/implementing-recaptcha-in-react.md
Date: 2023-04-14
Category: Guides
Description: Learn how to protect your React app from spam and abuse using reCAPTCHA. Follow this tutorial to create a sign-up form with reCAPTCHA validation.

reCAPTCHA is a free service provided by Google that protects websites from spam and abuse by using risk analysis techniques to differentiate between humans and bots.

Developers can use reCAPTCHA to detect and block malicious user sign-ups, usually automated bots that attempt to create fake accounts. Additionally, reCAPTCHA acts as a guardrail against data scraping bots accessing and collecting information from a website, ensuring the protection of sensitive information.

In this article, you'll learn about reCAPTCHA and how to implement it on your own site. More specifically, you'll create a sign-up form in a React application and use reCAPTCHA to verify that the user is a human before they can submit that form.

## What Is reCAPTCHA?

Before you implement reCAPTCHA on your website, let's take a look at how it works and its common use cases.

### How reCAPTCHA Works

When users visit a website with reCAPTCHA enabled, they're presented with a challenge they must complete to prove that they're human. This challenge can take several forms:

- **An image challenge:** The user is presented with a distorted image of letters and numbers and asked to type the characters they see into a text box.
- **An audio challenge:** Instead of images, an audio recording of letters and numbers is used and the user is asked to type the characters they hear into a text box.
- **A No CAPTCHA reCAPTCHA:** The user is asked to click on a checkbox to indicate that they're not a robot. In some cases, Google might also ask the user to complete a separate image or audio challenge if it needs further proof that the user is human. You'll use this type of reCAPTCHA in the tutorial later in this article.

Once the user completes the challenge, the website will receive a response from the reCAPTCHA server indicating whether the user is human or not. Based on this response, the website can decide whether to allow the user to access certain pages or forms or deny access if it determines that the user is likely a bot.

Note that there's also a form of reCAPTCHA that doesn't actually present a challenge to the user. Instead, the system uses advanced risk analysis techniques to determine whether the user is human. This method is called *invisible reCAPTCHA*.

### reCAPTCHA Use Cases

These are some prominent use cases for reCAPTCHA:

- **Preventing spam and bots on online forms:** This is a top use case. reCAPTCHA can protect online forms such as survey forms, blog post comment forms, and customer feedback from spamming bots.

- **Protecting login pages:** reCAPTCHA can be used to protect [login pages](/blog/building-a-react-login-page-template) from automated bots trying to gain unauthorized access by brute-force attacks. Requiring a user to solve a reCAPTCHA challenge before completing the login process makes it much more difficult for bots to gain access to an account.

- **Preventing scraping and data harvesting:** Adding reCAPTCHA verification stops automated bots from accessing the website, which stops attempts at data scraping and harvesting at an early stage. For example, [Cloudflare](https://www.cloudflare.com) runs bot checks as a measure to prevent bots from opening websites and scraping data.

## Implementing reCAPTCHA in Your React Application

In this tutorial, you'll create a newsletter sign-up page to collect users' email addresses and names using React. You'll then add a reCAPTCHA to the sign-up form on this page to verify if the user is a human and filter out bots and spam.

Before getting started, ensure that you have the following installed on your computer:

- Node.js (version 16 or above)
- npm (version 8 or above)
- A code editor ([Visual Studio Code](https://code.visualstudio.com) is recommended)

You can also clone this [GitHub repository](https://github.com/Anshuman71/react-recaptcha-example) to try the example application.

### Set Up a React Project

Open your terminal and run the following command to initialize a React project using [Create React App](https://reactjs.org/docs/create-a-new-react-app.html):

```bash
npx create-react-app react-recaptcha-example -y
```

Now change the directory to the project and open it in your code editor:

```bash
cd react-recaptcha-example
```

First, update the title on the `public/index.html` page to "reCAPTCHA example".

```html
<!doctype html>
<html lang="en">
  <head>
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!-- Rest meta tags -->
    <title>reCAPTCHA example</title>
  </head>
  <body>
    <!-- Rest of the body -->
  </body>
</html>
```

Then, open the **src/App.js** file to update the application to show a simple `<h1>` tag with "Sign up for Newsletter" as the content.

```jsx
function App() {
  return (
    <div>
      <h1>Sign up for Newsletter</h1>
    </div>
  )
}

export default App
```

Run `npm start` in the terminal to start the application. This command will run the React application on `http://localhost:3000` and open it in your default browser.

![Initial layout](./610f211ff2e472d8f091bd98b0182008114f42ae-1277x723.png)

The initial setup is now ready. Next, you'll create the sign-up form for the newsletter.

### Create a Sign-Up Form

To create a sign-up form, open the **App.js** file in the code editor and add a `form` element in the `App` component. In the `form` element, add two input boxes—`Email` and `Name`—to collect the user's email address and name. To allow users to submit the form, add a `button` in the `form`.

To track the input value of the two input fields, create two state variables: `email` and `name`. Add the `onChange` event handler on the `input` elements to update the input value using `setEmail` and `setName` functions:

```jsx
import { useState } from 'react'
import './App.css'

function App() {
  const [email, setEmail] = useState('')
  const [name, setName] = useState('')
  return (
    <div>
      <h1>Sign up for Newsletter</h1>
      <form>
        <input
          name="Email"
          type={'email'}
          value={email}
          required
          placeholder="joe@example.com"
          onChange={(event) => setEmail(event.target.value)}
        />
        <input
          name="Name"
          type={'name'}
          value={name}
          required
          placeholder="Joe"
          onChange={(event) => setName(event.target.value)}
        />
        <button type="submit">Sign up</button>
      </form>
    </div>
  )
}

export default App
```

You'll see a basic sign-up form, as shown below:

![Basic sign-up form](./0eaa635f3245e18383e213bced5d1f88cf6ac835-1605x903.png)

While functional, this form doesn't look very stylish. To make it look nicer, open the **App.css** file, remove all existing styles, and paste the CSS rules from below to align the form in the center and add some padding:

```css
h1 {
  text-align: center;
}

form {
  margin: 40px auto;
  width: 300px;
  display: flex;
  flex-direction: column;
}

input {
  margin-bottom: 20px;
  padding: 5px;
  border-radius: 5px;
}

button {
  padding: 5px;
  border-radius: 5px;
  margin-bottom: 20px;
}
```

After you add the above styles, the sign-up form should look more welcoming.

![Sign-up form with styles](./138673dd082c392bd8ebf8e90e1116571014db13-1616x909.png)

### Configure reCAPTCHA

Now that the sign-up form is ready, it's time to configure the reCAPTCHA verification. To use Google's reCAPTCHA, you must register a site on the [reCAPTCHA admin console](https://www.google.com/recaptcha/admin/create).

In the admin console, use `react-example` as the **Label**. Then, select **reCAPTCHA v2 > "I'm not a robot" Checkbox** as the reCAPTCHA type.

Add the domains where you want to use the reCAPTCHA, starting with `localhost`.

![Register form](./a2992ff2a2c6689c9c2663e62705ce4a3b9e98f1-2802x1817.png)

Select **Accept the reCAPTCHA Terms of Service** and click **Submit**.

On the next page, click on **COPY SITE KEY** and **COPY SECRET KEY** to copy the values.

![Copy site and secret key](./77b912977987b70663d35378cce3d349c477eb45-2394x1507.png)

Now create a new `.env` file in your project and paste these values, as shown below:

```bash
REACT_APP_SITE_KEY=<from-admin-dashboard>
SITE_SECRET=<from-admin-dashboard>
```

*Note:* You must append environment variables used in Create React App with `REACT_APP_`, as per the [documentation](https://create-react-app.dev/docs/adding-custom-environment-variables).

To use the reCAPTCHA in your React application, install the [react-google-recaptcha](https://www.npmjs.com/package/react-google-recaptcha) npm package by running the following command:

```bash
npm i react-google-recaptcha
```

In the **App.js** file, import the `ReCAPTCHA` component and place it below the `<button>`. Pass the `siteKey` prop and assign it to the `process.env.REACT_APP_SITE_KEY` so Google can recognize your reCAPTCHA:

```jsx
import { useState } from 'react'
import './App.css'
import ReCAPTCHA from 'react-google-recaptcha'

function App() {
  const [email, setEmail] = useState('')
  const [name, setName] = useState('')
  return (
    <div>
      <h1>Sign up for Newsletter</h1>
      <form>
        <input
          name="Email"
          type={'email'}
          value={email}
          required
          placeholder="joe@example.com"
          onChange={(event) => setEmail(event.target.value)}
        />
        <input
          name="Name"
          type={'name'}
          value={name}
          required
          placeholder="Joe"
          onChange={(event) => setName(event.target.value)}
        />
        <button type="submit">Sign up</button>
        <ReCAPTCHA sitekey={process.env.REACT_APP_SITE_KEY} />
      </form>
    </div>
  )
}

export default App
```

You'll now see the reCAPTCHA rendering inside the `form`:

![reCAPTCHA rendering](./ce25dd5373b69f840506c07894e1ee3b0152dc3a-1606x900.png)

### Test reCAPTCHA

To test the reCAPTCHA on form submission, you need to call the `getValue` method on the reCAPTCHA instance and verify its value. For this, you need to keep a reference to the reCAPTCHA component, which you can do using the `useRef` hook.

Create a `recaptcha` reference using the `useRef` hook and assign it as the value for the `ref` prop on the `ReCAPTCHA` component:

```jsx
import { useRef, useState } from 'react'
import './App.css'
import ReCAPTCHA from 'react-google-recaptcha'

function App() {
  const recaptcha = useRef()
  const [email, setEmail] = useState('')
  const [name, setName] = useState('')
  return (
    <div>
      <h1>Sign up for Newsletter</h1>
      <form>
        {/* input elements*/}
        <button type="submit">Sign up</button>
        <ReCAPTCHA ref={recaptcha} sitekey={process.env.REACT_APP_SITE_KEY} />
      </form>
    </div>
  )
}

export default App
```

To handle form submission, create a `submitForm` function that'll execute on the form `submit` event and verify the reCAPTCHA before form submission.

To verify the reCAPTCHA, the `submitForm` function calls the `getValue` method on the `recaptcha` ref object. The `getValue` method returns a token or `undefined`. If it's a token, the user has verified themselves. Otherwise, you show them an alert. Add the `submitForm` to the `onChange` event handler on the `form` element:

```jsx
import { useRef, useState } from 'react'
import './App.css'
import ReCAPTCHA from 'react-google-recaptcha'

function App() {
  const recaptcha = useRef()
  const [email, setEmail] = useState('')
  const [name, setName] = useState('')

  async function submitForm(event) {
    event.preventDefault()
    const captchaValue = recaptcha.current.getValue()
    if (!captchaValue) {
      alert('Please verify the reCAPTCHA!')
    } else {
      // make form submission
      alert('Form submission successful!')
    }
  }

  return (
    <div>
      <h1>Sign up for Newsletter</h1>
      <form onSubmit={submitForm}>{/* other elements */}</form>
    </div>
  )
}

export default App
```

### Server-Side Validation

So far, you've only checked if the user verified themselves using the reCAPTCHA, but you have yet to determine whether the token value is valid. If you open your reCAPTCHA admin console, you'll see the following message.

![Warning message on reCAPTCHA console](./d908b6f75bd8d468972b947f6d30a7825dc2e2aa-3587x1447.png)

To rectify this, you can request Google's reCAPTCHA verify API to confirm whether the provided token is valid. As this operation requires you to share the `SITE_SECRET` with Google, you must handle this operation on the server side for security reasons.

You can create a simple HTTP server using Node.js to implement the server-side validation. To quickly create a Node.js server, you need the following dependencies:

- `express`: to create the server application
- `axios`: to make network requests on the server side
- `cors`: to allow requests coming from a different origin (localhost: 3000)
- `dotenv`: to read the environment variables from the `.env` file

Run the following command to install all these dependencies:

```bash
npm i express axios dotenv cors
```

Now create the new file **server.js**, and set up a server that listens on port `8000`. Use the `cors` middleware to allow incoming requests from all origins and the `express.json` middleware to parse the JSON payload in the request body. Retrieve the `SITE_SECRET` from the environment variables.

The server accepts POST requests on the `/verify` route. In the POST request handler, you use the Google reCAPTCHA API to verify the `captchaValue` sent in the request body. You then send the response back to the user with the data returned from the reCAPTCHA API:

```js
require('dotenv').config()
const express = require('express')
const cors = require('cors')
const axios = require('axios')
const app = express()
const port = 8000

const SITE_SECRET = process.env.SITE_SECRET

app.use(cors())
app.use(express.json())

app.post('/verify', async (request, response) => {
  const { captchaValue } = request.body
  const { data } = await axios.post(
    `https://www.google.com/recaptcha/api/siteverify?secret=${SITE_SECRET}&response=${captchaValue}`,
  )
  response.send(data)
})

app.listen(port, () => {
  console.log(`Server listening at ${port}`)
})
```

Run **node server.js** to start the server application.

On the frontend, you need to update the `submitForm` method to send the `captchaValue` to the `/verify` endpoint in a POST request. In the **App.js** file, update the `submitForm` function to request the `http://localhost:8000/verify` endpoint for server-side validation and show the user an alert based on whether the validation was successful using the returned `success` property on the response data:

```js
async function submitForm(event) {
  event.preventDefault()
  const captchaValue = recaptcha.current.getValue()
  if (!captchaValue) {
    alert('Please verify the reCAPTCHA!')
  } else {
    const res = await fetch('http://localhost:8000/verify', {
      method: 'POST',
      body: JSON.stringify({ captchaValue }),
      headers: {
        'content-type': 'application/json',
      },
    })
    const data = await res.json()
    if (data.success) {
      // make form submission
      alert('Form submission successful!')
    } else {
      alert('reCAPTCHA validation failed!')
    }
  }
}
```

The reCAPTCHA validation flow is now complete. See it in action below.

## Conclusion

In this article, you learned the importance of reCAPTCHA validation and how to use it to prevent malicious users from misusing your application. By following this tutorial, you successfully created a sign-up form with reCAPTCHA validation and you also created a Node.js server to further validate the reCAPTCHA value for better security.

Clerk provides an easy way to add authentication and user management to your application. It offers beautiful components ready to plug into your application and build the authentication flow in no time. If you're looking for a complete authentication and identity platform, sign up to try [Clerk](https://dashboard.clerk.com/sign-up) today.

---

# Implementing OAuth 2.0 to React for User Authorization
URL: https://clerk.com/blog/oauth2-react-user-authorization.md
Date: 2023-04-13
Category: Guides
Description: Learn how to implement OAuth 2.0 in a React app for user authorization. OAuth 2.0 lets users share information securely without passwords.

In today's digital age, applications are used for everything. From social media to online banking, so much can be done online. However, as society's reliance on online services grows, so does the need to keep personal information secure. This is where [OAuth 2.0](https://oauth.net/2) comes in.

OAuth 2.0 is a popular protocol for both developers and users that lets you share certain information with a third-party app without providing a password. It's become the standard for many online businesses because it's secure and easy to use.

In this article, you'll learn more about OAuth 2.0 and the different ways it can be used. You'll also learn how to implement OAuth 2.0 in a React application for user authorization.

> Looking for a simpler way to add OAuth to React? [Learn more about our React support](/react-authentication) with pre-built flows for Google, GitHub, and other providers.

## Authentication and Authorization

The first step in understanding OAuth 2.0 is understanding that while there are similarities between authentication and authorization, the two concepts are different.

*Authentication* is the process of verifying the identity of a user or system. Using a set of credentials, such as a username or password, authentication makes sure that users are who they say they are.

Meanwhile, *authorization* is the process of figuring out if an authenticated user has the right privileges to access certain resources or do certain things. It's mainly focused on figuring out what a user can do and what resources they can use based on their role or other characteristics.

Authentication and authorization are both important parts of web security. They work together to make sure that only people who are allowed to can use a system or its resources.

Now that you know how authentication and authorization work, let's dig into what OAuth 2.0 is.

## What Is OAuth 2.0

OAuth 2.0, also referred to as the [OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749), is an open standard for authorization that lets users give third-party applications limited access to their web server resources without giving the applications their private credentials. OAuth 2.0 gives users more control over their data; they can selectively grant access to the applications they want to use.

For instance, OAuth 2.0 can be utilized to help users sign in to third-party applications with their Google account. This is often referred to as social login and is so common you've probably used it.

Here is a brief explanation of what occurs when you use a social login:

1. A Google sign-up button will pop up on the screen of the third-party app.
2. When you click the button, you'll be taken to Google's authorization server, where you'll be asked to sign into your Google account (if you aren't currently).
3. Google displays a consent screen after you log in, listing the permissions the third-party application is requesting (*ie* your public information, such as email and name).
4. Once you give your approval, Google will send you back to the app and provide it with an access token that will allow the app to access your public information.
5. The third-party app can then use the access token to make API calls to Google on your behalf as long as the requests are within the scope of the permissions you granted.

This five-step process defines the OAuth 2.0 flow or grant type. An OAuth 2.0 flow (*ie* an OAuth 2.0 grant type) typically defines the steps involved in getting an access token, as seen here:

![Sample OAuth 2.0 flow, courtesy of Gideon Idoko](./df567d4006d298abd0a27f3997a08d1bf903c842-1000x732.png)

By following this implicit OAuth 2.0 flow (more on this later), you can use a third-party application without giving it access to your Google credentials. You can also stop the application from using your account at any time.

### Types of OAuth 2.0 Flows

OAuth 2.0 identifies a number of different grant types, or OAuth 2.0 flows, that can be used to get an access token (which is used to access a protected resource). The OAuth 2.0 flow chosen usually depends on the client application, the protected resource, and the trust between the client and the server that does the authorization.

The following are some of the most popular types of OAuth 2.0 flows:

#### Authorization Code Flow

In an [authorization code flow](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.1), the resource owner is sent from the client application to the authorization server's authorization endpoint. Then the resource owner logs in and grants consent to the client, and is sent back to the client with an authorization code. Then the client exchanges this code for an access token.

Web applications commonly use this flow; however, it can also be used by mobile apps using the [Proof Key for Code Exchange (PKCE) technique](https://datatracker.ietf.org/doc/html/rfc7636).

#### Implicit Flow with Form Post

The [implicit flow with form post](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.2) is similar to the authorization code flow but is used for browser-based client applications, especially single-page apps. In this case, instead of trading an authorization code for an access token, the authorization server gives the access token directly to the client application, as in the example flow discussed previously.

#### Resource Owner Password Flow

In a [resource owner password flow](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.3), the resource owner already knows the client and feels comfortable giving them access to their credentials. The owner of the resource gives the client their private credentials directly, which the client then trades for an access token.

#### Client Credentials Flow

In the case of a [client credentials flow](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.4), the client uses their own credentials to access protected resources instead of using the credentials of the resource owner. Afterward, the authorization server gives the client an access token.

### OAuth 2.0 Roles

OAuth 2.0 roles define the entities in an OAuth 2.0 flow, and there are four major roles:

1. **Resource owner:** The user who owns the protected resource that the client application needs to access. The resource owner may be a person, a system, or a device.
2. **Resource server:** The server where the client wants to access a protected resource. The resource server is in charge of enforcing access controls on the protected resource.
3. **Client:** The third-party app that wants to access the protected resource on behalf of the resource owner. The client could be a server-based, mobile, or web application.
4. **Authorization server:** The server that verifies the resource owner's identity and gives access tokens to the client after the resource owner gives permission. The authorization server also checks the client's access tokens before letting them use protected resources.

Now that you have a better understanding of OAuth 2.0 and the different roles and flows, let's implement OAuth 2.0 in a React application.

## Implementing OAuth 2.0 in a React Application

In this section, you'll learn how to implement an OAuth 2.0 authorization code flow in your React application. Additionally, you'll learn a less complicated approach to implementing user authorization with [Clerk](/).

All the code for this tutorial can be found in this [GitHub repo](https://github.com/iamgideonidoko/user-auth).

### Prerequisites

Before you begin, you'll need [Node.js version 16 or later](https://nodejs.org/en/download) installed on your machine. Node.js ships with npm, which you'll use to install the necessary packages.

In addition, it's recommended that you have a basic knowledge of React and JavaScript to help you complete this tutorial with ease.

#### OAuth 2.0 with the Standard Flow

So far, you've only learned about the various OAuth 2.0 flow types. Here, you'll implement one.

The authorization code flow [is the most secure flow for web server applications](https://developer.constantcontact.com/api_guide/server_flow.html), and this is how it works:

![Authorization code OAuth 2.0 flow courtesy of Gideon Idoko](./3b201d8285ee3e6a5ab107338c2312a64e20e75d-5320x3236.png)

There are three main components: the authorization server, the frontend, and the backend. The final component is the resource (which is part of the backend) that only authorized users can access. In order for a user to be authorized, they must complete the authorization code flow:

1. A user goes to the authorization server from the frontend to get an authorization code.
2. The authorization code is then sent to the backend.
3. The backend verifies the authorization code by getting tokens from the authorization server.
4. The backend then authorizes the user to have access to the resource.

In this scenario, the frontend is a React application, and the backend/resource is a Node.js application. Building the authorization server is beyond the scope of this article, so instead, you'll leverage [Google OAuth 2.0](https://developers.google.com/identity/protocols/oauth2/web-server).

Alright, let's get started!

### Get Your Google Client ID and Secret

Interacting with the authorization server to get the authorization code is the first step in the OAuth 2.0 flow. You'll need a Google client ID and secret to be able to achieve that.

Follow these steps to obtain the client ID and secret:

1. Create a [new Google Cloud project](https://console.cloud.google.com/projectcreate).

   ![New Google Cloud project](./da8e6340b83862ba6c2339dca589b4cea85afd1c-1302x904.png)

2. Name it. In this example, it's "standard-auth".

3. Locate the **More Products** section on the sidebar, and click on **APIs & Services** and then the **OAuth consent screen**. Select **External** user type and click on **CREATE**. This will create a new OAuth consent screen. The OAuth consent screen tells users what app is asking for access to their information and what information the app can access:

   ![Create a new OAuth consent screen](./4100f9724d464df3968b86ba0b40bc712c7e4f3d-825x524.png)

4. Enter a name for your OAuth consent and the required email addresses; then click **SAVE AND CONTINUE**. At this point, you'll be shown the scope tab. Select the scopes indicated in the following image and click on the **Update** button to save it:

   ![Select scopes](./bdee261ca223628d250a732f2d4348eaa1bd5647-2348x1146.png)

5. Add the email that you want to use to test the consent screen in the **Test users** section:

   ![Test users section](./ec3ed297053c78b639430b516a0c2a6bdbb77956-775x485.png)

6. Click on **APIs & Services** on the sidebar again, and then select **Credentials**. Click on the **CREATE CREDENTIALS** button and then select **OAuth client ID**:

   ![CREATE CREDENTIALS](./98d544bb353feecf40c43daded6ee9f900bc6bba-900x501.png)

7. Complete the form and click on **CREATE** when you're done:

   ![OAuth Credentials screen](./79bd74261e7a902f86be11478439387cded923d1-1722x2024.png)

   The redirect URI specifies where Google should navigate after the consent screen. This means that the redirect or callback has to be created on the React frontend.

8. Copy your newly created client ID and secret, and save them somewhere safe. You'll need them later when requesting an authorization code and tokens.

### Implement the Node.js Backend

Now that you have your client ID and secret, it's time to implement the backend with Node.js and the [Express](https://expressjs.com) framework.

To do so, create a new directory (*ie* `standard-auth`) to house the backend project:

```bash
mkdir standard-auth
```

Then create another directory inside it called `server`:

```bash
cd standard-auth && mkdir server
```

Initialize a new project within the `server` directory:

```bash
npm init esnext -y
```

And install the necessary packages by running this command:

```bash
npm install axios@1.3.4 cookie-parser@1.4.6 cors@2.8.5 dotenv@16.0.3 express@4.18.2 jsonwebtoken@9.0.0 query-string@8.1.0
```

Create a new `.env` file and add the following to it:

```text
GOOGLE_CLIENT_ID=<the client ID you created earlier>
GOOGLE_CLIENT_SECRET=<the client secret you created earlier>
REDIRECT_URL=http://localhost:3000/auth/callback
CLIENT_URL=http://localhost:3000
TOKEN_SECRET=<any random string>
```

Update the environment variables accordingly.

Create a new `server.js` file, which is where the server-side code will be stored:

```bash
touch server.js
```

Add the following code to `server.js` to import all the necessary dependencies and create a config object:

```javascript
import 'dotenv/config'
import express from 'express'
import cors from 'cors'
import axios from 'axios'
import queryString from 'query-string'
import jwt from 'jsonwebtoken'
import cookieParser from 'cookie-parser'

const config = {
  clientId: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
  authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
  tokenUrl: 'https://oauth2.googleapis.com/token',
  redirectUrl: process.env.REDIRECT_URL,
  clientUrl: process.env.CLIENT_URL,
  tokenSecret: process.env.TOKEN_SECRET,
  tokenExpiration: 36000,
  postUrl: 'https://jsonplaceholder.typicode.com/posts',
}
```

Here, `config.authUrl` is a link to the OAuth consent screen. It is sent along with [some query parameters](https://developers.google.com/identity/protocols/oauth2/web-server#creatingclient) to the frontend. Then a request is made to `config.tokenUrl`, along with [some query parameters](https://developers.google.com/identity/protocols/oauth2/web-server#exchange-authorization-code) to verify an authorization code.

You need to define the parameters for both URLs by adding the following code to `server.js`:

```javascript
const authParams = queryString.stringify({
  client_id: config.clientId,
  redirect_uri: config.redirectUrl,
  response_type: 'code',
  scope: 'openid profile email',
  access_type: 'offline',
  state: 'standard_oauth',
  prompt: 'consent',
})
const getTokenParams = (code) =>
  queryString.stringify({
    client_id: config.clientId,
    client_secret: config.clientSecret,
    code,
    grant_type: 'authorization_code',
    redirect_uri: config.redirectUrl,
  })
```

Initialize a new Express app:

```javascript
const app = express()
```

And add the following middlewares to resolve CORS, parse cookies, and verify authorization, respectively:

```javascript
// Resolve CORS
app.use(
  cors({
    origin: [config.clientUrl],
    credentials: true,
  }),
)

// Parse Cookie
app.use(cookieParser())

// Verify auth
const auth = (req, res, next) => {
  try {
    const token = req.cookies.token
    if (!token) return res.status(401).json({ message: 'Unauthorized' })
    jwt.verify(token, config.tokenSecret)
    return next()
  } catch (err) {
    console.error('Error: ', err)
    res.status(401).json({ message: 'Unauthorized' })
  }
}
```

At this point, you can start adding endpoints for different tasks.

Add the following endpoint (`/auth/url`) to return the authorization URL to the frontend:

```javascript
app.get('/auth/url', (_, res) => {
  res.json({
    url: `${config.authUrl}?${authParams}`,
  })
})
```

Then add another endpoint (`/auth/token`) that will get an authorization code from the frontend and verify it:

```javascript
app.get('/auth/token', async (req, res) => {
  const { code } = req.query
  if (!code) return res.status(400).json({ message: 'Authorization code must be provided' })
  try {
    // Get all parameters needed to hit authorization server
    const tokenParam = getTokenParams(code)
    // Exchange authorization code for access token (id token is returned here too)
    const {
      data: { id_token },
    } = await axios.post(`${config.tokenUrl}?${tokenParam}`)
    if (!id_token) return res.status(400).json({ message: 'Auth error' })
    // Get user info from id token
    const { email, name, picture } = jwt.decode(id_token)
    const user = { name, email, picture }
    // Sign a new token
    const token = jwt.sign({ user }, config.tokenSecret, {
      expiresIn: config.tokenExpiration,
    })
    // Set cookies for user
    res.cookie('token', token, {
      maxAge: config.tokenExpiration,
      httpOnly: true,
    })
    // You can choose to store user in a DB instead
    res.json({
      user,
    })
  } catch (err) {
    console.error('Error: ', err)
    res.status(500).json({ message: err.message || 'Server error' })
  }
})
```

If the authorization code is verified (*ie* exchanged for an access token successfully), a new token is signed for the current user. The signed token will then be set as a cookie that will expire based on the `tokenExpiration` key in the `config` object.

Add the `/auth/logged_in` endpoint to check the logged-in state of a user:

```javascript
app.get('/auth/logged_in', (req, res) => {
  try {
    // Get token from cookie
    const token = req.cookies.token
    if (!token) return res.json({ loggedIn: false })
    const { user } = jwt.verify(token, config.tokenSecret)
    const newToken = jwt.sign({ user }, config.tokenSecret, {
      expiresIn: config.tokenExpiration,
    })
    // Reset token in cookie
    res.cookie('token', newToken, {
      maxAge: config.tokenExpiration,
      httpOnly: true,
    })
    res.json({ loggedIn: true, user })
  } catch (err) {
    res.json({ loggedIn: false })
  }
})
```

Then add the `/auth/logout` endpoint to log out a user in session:

```javascript
app.post('/auth/logout', (_, res) => {
  // clear cookie
  res.clearCookie('token').json({ message: 'Logged out' })
})
```

This will clear the `token` cookie, which invalidates a logged-in user's session.

Finally, add the resource endpoint:

```javascript
app.get('/user/posts', auth, async (_, res) => {
  try {
    const { data } = await axios.get(config.postUrl)
    res.json({ posts: data?.slice(0, 5) })
  } catch (err) {
    console.error('Error: ', err)
  }
})
```

This basically fetches posts (resources) and returns them as a response. The middleware for validating user authorization (`auth`) is used here because only authorized users are allowed to access this endpoint.

Now you need to make the Express app listen on port `5000`:

```javascript
const PORT = process.env.PORT || 5000

app.listen(PORT, () => console.log(`🚀 Server listening on port ${PORT}`))
```

### Implement the React Frontend

The easiest way to start a React project is to use boilerplate code. Go to the `standard-auth` directory and bootstrap a new React project using [Create React App](https://create-react-app.dev):

```bash
npx create-react-app client
```

This will create a `client` directory with your React project inside it.

Change to the `client` directory using `cd client` and install the following packages:

```bash
npm install axios@1.3.4 react-router-dom@6.9.0
```

Next, create a `.env` file in the root directory of your React project:

```bash
echo REACT_APP_SERVER_URL = http://localhost:5000 > .env
```

Open the `App.css` file in the `src` directory of your React project and add the following CSS code:

```css
.btn {
  border-radius: 100rem;
  padding: 12px 16px;
  background: linear-gradient(170deg, #61dbfb, #2e849b) !important;
  width: 10rem;
  border: none;
  color: white;
  font-weight: 600;
  margin: 1rem 0;
  cursor: pointer;
}
```

This will help style a button using the `btn` class.

Update your `App.js` file to import the necessary method and hooks by adding the following code just above the `App` component:

```javascript
import { RouterProvider, createBrowserRouter, useNavigate } from 'react-router-dom'
import axios from 'axios'
import { useEffect, useRef, useState, createContext, useContext, useCallback } from 'react'

// Ensures cookie is sent
axios.defaults.withCredentials = true

const serverUrl = process.env.REACT_APP_SERVER_URL
```

After updating the `App.js` file, you need to create a new React context to hold the logged-in and user states so they can be shared globally. To do so, add the following code just above the `App` component:

```javascript
const AuthContext = createContext()

const AuthContextProvider = ({ children }) => {
  const [loggedIn, setLoggedIn] = useState(null)
  const [user, setUser] = useState(null)

  const checkLoginState = useCallback(async () => {
    try {
      const {
        data: { loggedIn: logged_in, user },
      } = await axios.get(`${serverUrl}/auth/logged_in`)
      setLoggedIn(logged_in)
      user && setUser(user)
    } catch (err) {
      console.error(err)
    }
  }, [])

  useEffect(() => {
    checkLoginState()
  }, [checkLoginState])

  return (
    <AuthContext.Provider value={{ loggedIn, checkLoginState, user }}>
      {children}
    </AuthContext.Provider>
  )
}
```

The `checkLoginState` function in this React context makes a call to your backend's `/auth/logged_in` endpoint. Here, it's called in a `useEffect` block to run every time the app initially renders.

Next, add the following `Dashboard` component just before the `App` component:

```javascript
const Dashboard = () => {
  const { user, loggedIn, checkLoginState } = useContext(AuthContext)
  const [posts, setPosts] = useState([])
  useEffect(() => {
    ;(async () => {
      if (loggedIn === true) {
        try {
          // Get posts from server
          const {
            data: { posts },
          } = await axios.get(`${serverUrl}/user/posts`)
          setPosts(posts)
        } catch (err) {
          console.error(err)
        }
      }
    })()
  }, [loggedIn])

  const handleLogout = async () => {
    try {
      await axios.post(`${serverUrl}/auth/logout`)
      // Check login state again
      checkLoginState()
    } catch (err) {
      console.error(err)
    }
  }

  return (
    <>
      <h3>Dashboard</h3>
      <button className="btn" onClick={handleLogout}>
        Logout
      </button>
      <h4>{user?.name}</h4>
      <br />
      <p>{user?.email}</p>
      <br />
      <img src={user?.picture} alt={user?.name} />
      <br />
      <div>
        {posts.map((post, idx) => (
          <div>
            <h5>{post?.title}</h5>
            <p>{post?.body}</p>
          </div>
        ))}
      </div>
    </>
  )
}
```

Later, you'll render this component conditional based on the logged-in state of a user.

Add the `Login` component:

```javascript
const Login = () => {
  const handleLogin = async () => {
    try {
      // Gets authentication url from backend server
      const {
        data: { url },
      } = await axios.get(`${serverUrl}/auth/url`)
      // Navigate to consent screen
      window.location.assign(url)
    } catch (err) {
      console.error(err)
    }
  }
  return (
    <>
      <h3>Login to Dashboard</h3>
      <button className="btn" onClick={handleLogin}>
        Login
      </button>
    </>
  )
}
```

This component renders a button that takes the user to the OAuth consent screen you made earlier.

Do you remember when you provided a callback URL when you created your client ID and secret? Because of this, you need to add a component to handle the callback:

```javascript
const Callback = () => {
  const called = useRef(false)
  const { checkLoginState, loggedIn } = useContext(AuthContext)
  const navigate = useNavigate()
  useEffect(() => {
    ;(async () => {
      if (loggedIn === false) {
        try {
          if (called.current) return // prevent rerender caused by StrictMode
          called.current = true
          const res = await axios.get(`${serverUrl}/auth/token${window.location.search}`)
          console.log('response: ', res)
          checkLoginState()
          navigate('/')
        } catch (err) {
          console.error(err)
          navigate('/')
        }
      } else if (loggedIn === true) {
        navigate('/')
      }
    })()
  }, [checkLoginState, loggedIn, navigate])
  return <></>
}
```

Create a router to define routes that render the components you created earlier:

```javascript
const Home = () => {
  const { loggedIn } = useContext(AuthContext)
  if (loggedIn === true) return <Dashboard />
  if (loggedIn === false) return <Login />
  return <></>
}

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
  },
  {
    path: '/auth/callback', // google will redirect here
    element: <Callback />,
  },
])
```

Finally, update the `App` component with the following code:

```javascript
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <AuthContextProvider>
          <RouterProvider router={router} />
        </AuthContextProvider>
      </header>
    </div>
  )
}
```

Now, it's time to test out the implementation. Go to your `server` directory and run the following command to spin up the server:

```bash
node server.js
```

Open another terminal in your `client` directory and run this command to spin up your React server:

```bash
npm start
```

This command will open up [http://localhost:3000](http://localhost:3000) in your default browser. You should see something like this when the server is fully running:

![React home](./091fb8fed6fd17f2e008bd4dbdd9a86646395e73-2266x1514.png)

If you click on the login button, you'll be redirected to the OAuth consent screen:

![OAuth consent screen](./623c6dc5c09ec64a461287a8ad4a3e9986bf93ff-1133x757.png)

After you're redirected, you'll be logged in and authorized to access the post resources:

![Dashboard](./5e501876abe9edd3b02784cb0c47c8207b4f5d41-1409x807.png)

If you've followed along, you've officially implemented the OAuth 2.0 authorization code flow in React. Great work!

## Authorization with Clerk

As you can see, implementing OAuth 2.0 is complicated and time-consuming. This is where Clerk can help.

Clerk is a service that takes care of user management. This means developers don't have to keep reinventing the wheel and can focus on what they do best. Moreover, Clerk can also take care of authorization.

In this section, you'll see how Clerk can easily be used to replicate the implementation in the previous section.

Before you proceed, you need to have a Clerk account. An account will give you access to both a publishable key and a secret key, as well as other customizations.

If you don't already have an account, [go to Clerk's sign-up page](https://dashboard.clerk.com/sign-up) and create one:

![Clerk sign-up page](./e199148109142f1e8a96f307613cbbb7ba2fd5a4-1271x882.png)

After you've signed up, click on **Add application** to create a new project:

![Add a new application on Clerk](./6392464d7662055edb1392579e84f065e473b943-1080x501.png)

Update the settings for your new application to match the settings shown here:

![New application settings](./a7b74dbf275c4429d20314c8b397ceef0cda8ff7-1179x767.png)

When you're done, click on **FINISH**, and a new application will be created.

Navigate to the **API Keys** section. Copy your publishable and secret keys, and save them somewhere safe:

![Clerk API Keys page](./b9d2c985fa6955f697579bc70e15c91948c861ee-1504x824.png)

### Implement the Node.js Backend

For this Clerk example, you need to rewrite the Node.js implementation you did previously. Update your `.env` file in the `server` directory with the following:

```text
CLERK_SECRET_KEY=<the secret key you copied from your Clerk account>
```

Update the environment variable accordingly.

Then run the following command in your `server` directory to install Clerk's Node.js SDK:

```bash
npm install @clerk/clerk-sdk-node@4.7.11
```

Update your `server.js` file with the following code:

```javascript
import 'dotenv/config'
import express from 'express'
import cors from 'cors'
import axios from 'axios'
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node'

const config = {
  postUrl: 'https://jsonplaceholder.typicode.com/posts',
  clerkSecretKey: process.env.CLERK_SECRET_KEY, // Clerk automatically picks this from the env
}

const app = express()

app.use(cors())

app.get('/user/posts', ClerkExpressRequireAuth(), async (req, res) => {
  console.log('REQUEST AUTH: ', req.auth)
  try {
    const { data } = await axios.get(config.postUrl)
    res.json({ posts: data?.slice(0, 5) })
  } catch (err) {
    console.error('Error: ', err)
  }
})

const PORT = process.env.PORT || 5000

app.listen(PORT, () => console.log(`🚀 Server listening on port ${PORT}`))
```

Here, you're using the `ClerkExpressRequireAuth()` middleware to allow only authorized access to the `/user/posts/` route. It's that easy!

### Implement the React Frontend

To implement the React frontend, update the `.env` file in your `client` directory with the following:

```text
REACT_APP_CLERK_PUBLISHABLE_KEY=<the publishable key you copied from your Clerk account>
REACT_APP_SERVER_URL = http://localhost:5000
```

Remember to update the environment variable accordingly.

Then run the following command in the `client` directory to install the Clerk React SDK:

```bash
npm install @clerk/clerk-react@4.12.4
```

Update the `App.js` file inside the `src` directory in your `client` directory with the following code:

```javascript
import logo from './logo.svg'
import './App.css'
import {
  ClerkProvider,
  SignedIn,
  SignedOut,
  UserButton,
  RedirectToSignIn,
  useAuth,
} from '@clerk/clerk-react'
import { useState, useEffect } from 'react'
import axios from 'axios'

const clerkPubKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY
const serverUrl = process.env.REACT_APP_SERVER_URL

const Dashboard = () => {
  const [posts, setPosts] = useState([])
  const { getToken } = useAuth()

  useEffect(() => {
    ;(async () => {
      try {
        const token = await getToken()
        console.log('token: ', token)
        // Get posts from server
        const {
          data: { posts },
        } = await axios.get(`${serverUrl}/user/posts`, {
          headers: { Authorization: `Bearer ${token}` },
        })
        setPosts(posts)
      } catch (err) {
        console.error(err)
      }
    })()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  return (
    <>
      <h3>Dashboard</h3>
      <UserButton />
      <div>
        {posts.map((post, idx) => (
          <div>
            <h5>{post?.title}</h5>
            <p>{post?.body}</p>
          </div>
        ))}
      </div>
    </>
  )
}

function App() {
  return (
    // Don't forget to pass the publishableKey prop
    <ClerkProvider publishableKey={clerkPubKey}>
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <SignedIn>
            <Dashboard />
          </SignedIn>
          <SignedOut>
            <RedirectToSignIn />
          </SignedOut>
        </header>
      </div>
    </ClerkProvider>
  )
}

export default App
```

Clerk's React SDK exports prebuilt components that are very useful. For instance, the `SignedIn` component renders its children (in this case, the `Dashboard` component) only when a user is signed in. The `SignedOut` component does the opposite.

The `RedirectToSignIn` component redirects the users to a form where they can choose their authentication method. In this case, the users will be prompted to use their [Google account](/blog/nextjs-google-authentication) or email address (you set this when creating your Clerk application).

The `Dashboard` component makes a request to get post resources using the token provided by the `useAuth` hook from the Clerk SDK.

If you go through the sign-up process, you'll end up with something like this:

![Dashboard after Clerk](./676a08c311b93de33c0d16fec4533db950b13cd5-903x629.png)

## Standard Authorization vs. Clerk

As you can see, implementing a standard and secure authorization can be difficult, time-consuming, and in some cases, unnecessary. However, you can solve these issues with [Clerk](/), which can help you implement user authentication and authorization with ease.

Clerk does this by providing a range of authentication methods, including social login, password-based, and multifactor authentication. It also gives developers access to a user interface where they can control their applications' authentication and user management settings. Moreover, analytics and reporting capabilities are available to developers to help them keep track of user behavior.

If you enjoyed this article, you might also like our guide to [implementing session-based authentication with React and Express](/blog/building-a-react-login-page-template).

---

# Validating, Creating, and Styling React-Bootstrap Forms
URL: https://clerk.com/blog/validate-create-style-react-bootstrap-forms.md
Date: 2023-01-25
Category: Guides
Description: Create a complete login and sign-up flow with React Bootstrap forms, then learn how to use tools like Clerk to easily manage authentication and authorization.

Building user interfaces works best by building small components and then combining and reusing them across your application. This ensures that different components in your application are not tightly coupled and encourages reusability. [React.js](https://reactjs.org), or React, is a free and open source JavaScript library that can help you do this.

However, creating a new page in React can be difficult, especially if you have a complex view with multiple components that must be rendered based on various conditions. This is where React-Bootstrap comes in.

React-Bootstrap is a frontend library providing an array of components and many other functionalities out of the box that you can directly import into your website instead of building them from scratch. One such component is bootstrap forms that you can use to easily create and design complex forms in React.

In this article, you'll learn about React-Bootstrap by creating a complete login and sign-up flow with bootstrap forms; you'll then see how to use tools like [Clerk](/) to further ease your life in terms of managing authentication and authorization flow.

Let's start with React-Bootstrap; the next section will talk about what React-Bootstrap forms are and how they can help you increase the quality of your application while saving you time and effort.

## What Is React-Bootstrap?

React-Bootstrap is a frontend component library that provides [pure React components](https://dev.to/sumitkharche/pure-components-in-react-57on). React-Bootstrap includes a plethora of ready-to-use components that you can import directly into your application. It's also very simple to make these components responsive, which would otherwise be a very time-consuming task.

The [documentation for React-Bootstrap](https://react-bootstrap.github.io/docs/getting-started/introduction) is also very well supported and simple to understand, allowing you to get started with a lower learning curve.

### Why Use React-Bootstrap Forms?

There are several scenarios in which you might want to create forms for your website. Perhaps you need a sign-in/sign-up page for your customers to log in, an address page for an e-commerce app, or have some other use case where you want multiple inputs from your app's user. Even something as simple as adding a task to your to-do app requires a form.

Creating complex workflows in forms can be difficult. You must have an array of input types, such as text, password, and so on, as well as various validations based on input types and state attributes. This can eventually lead to hundreds of lines of code that are difficult to understand and debug.

This is where [React-Bootstrap forms](https://react-bootstrap.github.io/docs/forms/overview) shine. With bootstrap forms, you can create a form with minimal code.

In the following sections, you'll learn how to design and build a sign-in/sign-up page using bootstrap forms. Let's get started!

## Implementation

In this section, you'll first see how to create a React project and then use React-Bootstrap to create your own sign-in/sign-up page.

### Project Setup

Before you can start writing code, you must first install React, React-Bootstrap, and other dependencies in your project. If you already have these installed, you can skip this section.

#### Installing npm and Node.js

Run the commands `node —version` and `npm —version` to see if Node.js and npm are already installed. If it says `command not found` for either command, proceed to the next step.

The first thing you need to do is [download a Node.js installer](https://nodejs.org/en/download) for your system. As recommended, download the LTS version. Install and run the software. This will automatically install Node.js and npm for you.

Once you're done installing, run the above commands once more to verify that both npm and Node.js have been correctly installed.

#### Setting Up a React Project

Once you have npm installed, it's easy to create a React project. Just run the command `npx create-react-app <projectname>`. This example will use "bootstraplogin" as the project name.

Once the project is created, you need to install [React-Bootstrap](https://react-bootstrap.github.io/docs/getting-started/introduction). For that, first run `cd bootstraplogin` and then run `npm install react-bootstrap bootstrap`. This will install React-Bootstrap and bootstrap to your project and add them as dependencies in your **package.json** file.

To ensure that everything is working as it should, run the command `npm start` and visit `http://localhost:3000` to ensure that the React default page is getting loaded like this.

![Default React page](./TXXEXU3.jpg)

If this page is loading correctly, your setup is complete.

### Creating a Form Using React-Bootstrap

In the section below, you'll get to grips with form creation using React-Bootstrap. You'll create and style a basic form in which users are asked to provide their email and password in order to sign in.

#### React-Bootstrap Form Basics

Before you dive into implementing your login flow, let's get the basics of bootstrap forms right.

Initially, your **App.js** file, which you can find in the `src` folder of the project, will look something like this:

```js
import logo from './logo.svg'
import './App.css'

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  )
}

export default App
```

You will now update your **App.js** to create a basic form page as described below.

The first thing you need to do is import the React-Bootstrap CSS. For that, add `import 'bootstrap/dist/css/bootstrap.min.css';` to your **index.js** file.

Once that's done, update your **App.js** file to use bootstrap forms as below:

```jsx
import React from 'react'
import Button from 'react-bootstrap/Button'
import Form from 'react-bootstrap/Form'

function App() {
  return (
    <Form>
      <Form.Group className="mb-3" controlId="formBasicEmail">
        <Form.Label>Email address</Form.Label>
        <Form.Control type="email" placeholder="Enter email" />
        <Form.Text className="text-muted">We'll never share your email with anyone else.</Form.Text>
      </Form.Group>

      <Form.Group className="mb-3" controlId="formBasicPassword">
        <Form.Label>Password</Form.Label>
        <Form.Control type="password" placeholder="Password" />
      </Form.Group>
      <Form.Group className="mb-3" controlId="formBasicCheckbox">
        <Form.Check type="checkbox" label="Check me out" />
      </Form.Group>
      <Button variant="primary" type="submit">
        Submit
      </Button>
    </Form>
  )
}

export default App
```

The UI should now look like this.

![Form using React-Bootstrap](./LgxT3uJ.jpg)

The first thing to notice in the above example is that you're importing `Form` from `react-bootstrap/Form`.

`<Form>` is the top-level API provided by React-Bootstrap, which wraps all the functionality required to build forms.

The `<Form.Control>` component renders the input component with bootstrap styling. Forms support different types of inputs like plaintext, email, password, file, or even color as input.
After that, you have `<Form.Group>`, which creates a section inside the form view by wrapping the `<Form.Control>` with its own styling and validations.

There's also `<Form.Label>`, which works as the title for the form group, and `<Form.Text>`, where you can add additional text.

#### Styling with React-Bootstrap

React-Bootstrap provides two main features for users to easily build responsive and well-designed web pages.

1. **The grid system:** Bootstrap's grid system uses a series of containers, rows, and columns to lay out and align content. It's built with [Flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes) and is fully responsive. The grid also offers the following:

   - **Containers:** Containers provide a means to center and horizontally pad your site's contents. Use the container feature for a responsive pixel width. You can use containers as the wrapper for your component to correctly align it.
   - **Row:** Row is used to align elements in rows one after another.
   - **Column:** Column is used to align elements as columns inside a row.

![Grid system in React-Bootstrap](./ztkYOZQ.png)

2. **CSS utilities:** Bootstrap provides a [SASS](https://sass-lang.com)-based utility class to add CSS to your components. Using the utility API, you can easily add [various CSS properties](https://getbootstrap.com/docs/4.0/utilities/borders) like border, color, background, etc. You can add these utilities with any component by adding `className` to your component.

For example, `<div className="mb-3 mt-4"/>` provides a bottom margin of 3 pixels and a top margin of 4 pixels for the div.

Now that you've covered the fundamentals, let's create a sign-in/sign-up page for your website. You can find the entire code in [this GitHub repo](https://github.com/himanishm07/loginforclerk).

### Sign-In Page

The first thing to do is create the **SignIn.js** file in your `src` folder and add the below code:

```jsx
import React from 'react'
import { Col, Button, Row, Container, Card, Form } from 'react-bootstrap'

export default function Login() {
  return (
    <Container>
      <Row className="vh-100 d-flex justify-content-center align-items-center">
        <Col md={8} lg={6} xs={12}>
          <div className="border-primary border border-3"></div>
          <Card className="shadow">
            <Card.Body>
              <div className="mt-4 mb-3">
                <h2 className="fw-bold text-uppercase mb-2">Brand</h2>
                <p className="mb-5">Please enter your login and password!</p>
                <Form className="mb-3">
                  <Form.Group className="mb-3" controlId="formBasicEmail">
                    <Form.Label className="text-center">Email address</Form.Label>
                    <Form.Control type="email" placeholder="Enter email" />
                  </Form.Group>

                  <Form.Group className="mb-3" controlId="formBasicPassword">
                    <Form.Label>Password</Form.Label>
                    <Form.Control type="password" placeholder="Password" />
                  </Form.Group>
                  <div className="mb-3">
                    <p className="small">
                      <a className="text-primary" href="#!">
                        Forgot password?
                      </a>
                    </p>
                  </div>
                  <div className="d-grid">
                    <Button variant="primary" type="submit">
                      Login
                    </Button>
                  </div>
                </Form>
                <div className="mt-3">
                  <p className="mb-0 text-center">
                    Don't have an account?{' '}
                    <a href="{''}" className="text-primary fw-bold">
                      Sign In
                    </a>
                  </p>
                </div>
              </div>
            </Card.Body>
          </Card>
        </Col>
      </Row>
    </Container>
  )
}
```

Now, let's see exactly what's happening in the above example.

1. You use a `<Container>` to wrap the component. Containers provide an easy means to center and horizontally pad the content you put inside it.
2. Then, you use a `<Row>` and a `<Col>` element. The former is used to add CSS to the component to orient the entire screen horizontally and align the internal component to center; the latter is used to add breakpoints to ensure a responsive view across any screen size.
3. Next, `<div>` adds a blue horizontal line to the view for which the div is styled using the border utility provided by React-Bootstrap.
4. Next, you have `<Card>` and `<Card.Body>`. Card is a basic container with inherent styling like a rounded border and some padding. Inside the card, you can have a header, footer, and body. In the example, you only use Card.Body.
5. Then there's a `<div>` with className values as `mb-3` and `mt-4`, which provide a bottom margin of 3 pixels and a top margin of 4 pixels to the div.
6. After that, you add an `<h2>` tag for the heading in the view. `fw-bold` sets font weight as bold, `text-uppercase` makes the text uppercase, while `mb-2` is again setting 2 pixels as the bottom margin.
7. After that, you use the `<p>` tag to add text.
8. Next, you want to add inputs for the user to add username and password. For this, you use `<Form>`.
9. In code, there are two groups in `<Form>`: one for the username and the other for the password using `<Form.Group>`. `ControlId` here works as a unique id for the FormGroup.
10. Then, you add `<Form.Label>` to add a heading for the input.
11. `<Form.Control>` converts to the actual HTML input element in the view. `type` is given as `email`, which checks for a valid email address, and `placeholder` is added, which will be shown when the user has not yet provided input.
12. You then repeat steps 10 and 11 but this time for the password. Adding `type` as `Password` for `Form.Control` also ensures that the input is not visible but is added as a `**`.
13. After that, you add a `<div>`, wrapping a clickable link and a `p` tag inside it; the `p` tag has `className` "small" and "text-primary", which sets size and color for the inside text respectively.
14. An anchor tag is used to make the text clickable. You can also add an actual link that provides "Forgot password" functionality by replacing `#` with that link.
15. After that, there's another `<div>` wrapping a clickable button. If you want to find out more, React-Bootstrap provides [an API for buttons](https://react-bootstrap.github.io/docs/components/buttons).
16. Finally, you add another `<div>` with a link that once clicked should open a sign-up page for the user.

Your sign-in page should look like below.

![Sign-in page using React-Bootstrap](./dEx5e1b.jpg)

### Sign-Up Page

The sign-up page has similar components to the sign-in page but requires some extra details, which you'll see below.

First, you need to create the **SignUp.js** file in your `src` folder and add the below code:

```jsx
import React from 'react'
import { InputGroup, Col, Button, Row, Container, Card, Form } from 'react-bootstrap'

export default function SignUp() {
  return (
    <Container>
      <Row className="vh-100 d-flex justify-content-center align-items-center">
        <Col md={10} lg={8} xs={12}>
          <div className="border-primary border border-3"></div>
          <Card className="shadow">
            <Card.Body>
              <div className="mt-4 mb-3">
                <h2 className="fw-bold text-uppercase mb-2">Brand</h2>
                <p className="mb-5">Please enter your details to join us!</p>
                <Form>
                  <Row className="mb-3">
                    <Form.Group as={Col} className="mb-3" controlId="formFullName">
                      <Form.Label className="text-center">Your full name</Form.Label>
                      <Form.Control type="text" placeholder="Enter name" />
                    </Form.Group>

                    <Form.Group as={Col} className="mb-3" controlId="formPhoneNumber">
                      <Form.Label>Phone Number</Form.Label>
                      <Form.Control type="number" placeholder="Enter phone number" />
                    </Form.Group>
                  </Row>
                  <Row className="mb-3">
                    <Form.Group as={Col} className="mb-3" controlId="formUsername">
                      <Form.Label className="text-center">Email address</Form.Label>
                      <InputGroup>
                        <Form.Control type="email" placeholder="Enter username" />
                        <InputGroup.Text className="text-primary">@brand.com</InputGroup.Text>
                      </InputGroup>
                    </Form.Group>

                    <Form.Group as={Col} className="mb-3" controlId="formBasicPassword">
                      <Form.Label>Password</Form.Label>
                      <Form.Control type="password" placeholder="Password" />
                    </Form.Group>
                  </Row>
                  <div className="d-grid">
                    <Button variant="primary" type="submit">
                      Sign Up
                    </Button>
                  </div>
                </Form>
                <div className="mt-3">
                  <p className="mb-0 text-center">
                    Already have an account?{' '}
                    <a href="{''}" className="text-primary fw-bold">
                      Sign In
                    </a>
                  </p>
                </div>
              </div>
            </Card.Body>
          </Card>
        </Col>
      </Row>
    </Container>
  )
}
```

Let's see what each line of code does.

1. Similarly to the sign-in page, you create a container, then add a row and column to it.
2. You again have a div representing the horizontal line just for the view.
3. Then you once more add `<Card>`, including `<Card.Body>`, which captures the header text, and then the `<Form>`.
4. Now you have a `<Row>`, which was not the case in the sign-in page. Row has two `<Form.Group>`s: one for a name and another for a phone number. This is so that these two form groups can be rendered in a single row. Along with adding `<Row>`, you also have to add `as={Col}` to the`<Form.Group>` to align these two form groups in a single row.
5. You again have a `<Row>`, which includes two form groups. These form groups are for users to add their username and password.
6. In the username form group, `<InputGroup>` is added. InputGroup easily extends the Form.Control component by adding text, buttons, or button groups on either side of the input.
7. In the above code, `@brand.com` is added as `<InputGroup>` text, which signifies that the email address for the user will be "[username@brand.com](mailto:username@brand.com)".
8. After that, much like with the sign-in page, you have a clickable button for signing up and a link to move to the sign-in page.

![Sign-up page using React-Bootstrap](./OPNonsY.jpg)

## What's Next?

You saw above how easy it is to create your own sign-in and sign-up page using Bootstrap; however, there are aspects that Bootstrap doesn't automatically take care of, which are essential in creating a secure and functional website. For example, along with asking the user to upload their information, you also need to store that information in your database and validate the username and password when the user tries to log in.

There are various other features like authorization, social logins, and multifactor authentication, which are very complex workflows in themselves where you must ensure that your system's security is never compromised. This means that as the product owner, you must keep up with advancements to ensure a secure product.

In light of these considerations, it might be a good idea for you to delegate the sign-in/sign-up functionality to a SaaS platform like [Clerk](/) that takes care of all these complex tasks for you.

## Using Clerk to Create More Secure Login Forms

Clerk is a tool that makes it simple for you to integrate authentication and authorization functionality with your web and mobile apps without having to worry about low-level security details or even the design of the sign-in/sign-up page.

### Creating a Login Form Using Clerk

Before we get into integrating Clerk into your application, you'll have to create an account. [Sign up with Clerk](https://dashboard.clerk.com/sign-up) and you'll be shown the below page.

![Create a sign-in page using Clerk](./KBjmiuQ.jpg)

Let's go section by section. First, you need your application name. You can add more applications later, so make sure the name is specific to the project you're working on.

After that, you need to specify how you want to authenticate your users. You can choose multiple options based on your requirements. You can also mention the social media platforms you want to use for authentication.

Once you're done, click **Submit** and you'll be directed to your application page. Just click **Try it now** and it will redirect you to your sign-in/sign-up page.

### Integrating Clerk with Your Application

Integrating Clerk with your React application is a simple process. All you have to do is follow the instructions in this article. Let's set it up step by step below.

#### Set Up Clerk in Your Project

1. Go to your project repository in the command line, if you're not already there, using `cd <path_to_your_project>`.
2. Install Clerk React SDK using `npm install @clerk/clerk-react`.
3. Create a file to store `env` variables using the `touch .env.local` command.
4. Run `echo "REACT_APP_CLERK_FRONTEND_API=clerk.sharp.mustang-37.lcl.dev" > .env.local`. This will add `REACT_APP_CLERK_FRONTEND_API` as an `env` variable in your file.

And that's all you need to integrate with Clerk. It's fairly easy, right? Now let's go and make the required code changes to integrate your application with Clerk.

#### Code Changes

Add the below code to the **App.js** file in your `src` folder:

```js
import React from 'react'
import './App.css'
import {
  ClerkProvider,
  SignedIn,
  SignedOut,
  UserButton,
  useUser,
  RedirectToSignIn,
} from '@clerk/clerk-react'

const frontendApi = process.env.REACT_APP_CLERK_FRONTEND_API

function App() {
  return (
    // Wrap your entire app with ClerkProvider
    // Don't forget to pass the frontendApi prop
    <ClerkProvider frontendApi={frontendApi}>
      <SignedIn>
        <Hello />
      </SignedIn>
      <SignedOut>
        <RedirectToSignIn />
      </SignedOut>
    </ClerkProvider>
  )
}

function Hello() {
  // Get the user's first name
  const { user } = useUser()
  return (
    <div className="App-header">
      {/* Mount the UserButton component */}
      <UserButton />
      {user ? <h1>Hello, {user.firstName}!</h1> : null}
    </div>
  )
}
export default App
```

Now let's see what the above code is doing:

1. You import the required dependencies from the Clerk module.
2. `frontendApi` tells the Clerk framework which API endpoint to hit to get the user-related information.
3. The `<ClerkProvider>` component wraps your React application to provide active session and user context. It must always be added to the entrypoint of your React application.
4. The `<SignedIn>` component offers authentication checks for your application. Any child components wrapped by a `SignedIn` component will be rendered only if there's a user signed into an active session in your application. For example, when you want the cart and profile page to be visible only to logged-in users, you can use `<SignedIn>`.
5. Similarly, any child nodes wrapped by a `<SignedOut>` component will be rendered only if the user is not yet signed in to your application.
6. In the `Hello` component, the `useUser` hook gets the information regarding the logged-in user. The `<UserButton>` provides you with a clickable button.
7. In your application, if the user is signed in, it will show the `<Hello />` component, which shows user information and a `<UserButton>`.
8. If the user is signed out, you're just redirecting the app to show the sign-in page using `<RedirectToSignIn>`.

The signed-out view looks like the following.
![Sign-in page using Clerk](./A6u38wZ.jpg)

And here's the signed-in view.

![Sign-out page using Clerk](./JlidDZF.jpg)

### Clerk.com vs. React-Bootstrap

Now that you understand how Clerk works and what features it provides, let's discuss the benefits it offers over implementing your own login flow using React-Bootstrap.

1. **Customized UI:** With Clerk, you can create your sign-in/sign-up pages with just a few clicks. You don't need to worry about creating different components, styling them, and handling their state. Just import the ClerkProvider and you're done.
2. **Offloading complexity of authentication and authorization:** As discussed above, implementing authentication and authorization for your application is a very complex task. Clerk takes care of this complexity for you.
3. **Advanced functionality out of the box:** Along with authentication and authorization, Clerk provides various other functionalities like [social media links and single sign-on (SSO)](/features/social-sso), [multifactor authentication](/features/multifactor-authentication), phone-number- and email-based login, and many other features.
4. **Seamless integration with different projects:** With Clerk, you can integrate your login module with different frontend applications, be it mobile apps, web pages, etc. If you're migrating from one JS framework to another—for example, from React.js to Next.js—you just need to integrate with your new project rather than write all the code again.
5. **Better control and monitoring:** Clerk also provides you with the metadata information like registered users, registration date, and last sign in. You can also integrate with Google Analytics and Firebase for analyzing data.

## Conclusion

In this article, you learned how to create your sign-in and sign-up page, first using React-Bootstrap and then recreating it using Clerk. You also learned various benefits of React-Bootstrap and Clerk and how the latter enables you to completely offload the complex authentication and authorization flow.

Clerk helps you in [building your sign-in](/blog/building-a-react-login-page-template) and sign-up page just with a few clicks. It provides an array of functionalities like social sign in, SSO, multifactor authentication, user information, session management, etc. By doing so, it helps you focus on solving your business problems without worrying about the security of your application.

---

# Adding Google Login to Your Next.js 13 Application
URL: https://clerk.com/blog/add-google-login-next13-app.md
Date: 2023-01-25
Category: Guides
Description: Compare adding Google Login to your Next.js 13 Application by building it yourself, with using a third-party service like Clerk.

External identity providers offer several benefits, such as adding a visibly trusted sign-in option, enabling sign-in without usernames and passwords, and getting additional information about users from the identity provider if they consent to it.

A well-known identity provider seen on many websites is Google login. Users can choose to log in with their Google account on a website, which lets Google authenticate them and return their details to your application.

In this article, you'll learn how to integrate Google login in your Next.js app. First, you'll see how to use a library like [NextAuth.js](https://next-auth.js.org) to manually add a Google login to your website. Then, you'll learn how to use a third-party [authentication provider like Clerk](/nextjs-authentication) to quickly add a Google login to your website. Lastly, this article compares the two methods.

You'll find the code for this article in [this GitHub repository](https://github.com/ivankahl/nextjs-gotham-newspaper).

## Prerequisites

To follow along with this tutorial, you'll need the latest versions of [Node.js](https://nodejs.org/en/download), which, at the time of writing, is 18.12.1, and [npm](https://docs.npmjs.com/cli/v9/configuring-npm/install?v=true), which, at the time of writing, is 9.1.3.

## The Base Project

You can find the base project for this article [here](https://github.com/ivankahl/nextjs-gotham-newspaper/tree/master/nextjs-gotham-newspaper-base). The project is a Next.js 13 application that imitates a news website with a user paywall preventing users from reading articles without being logged in. Tailwind CSS is used to style the different pages and components in the project.

If you browse through the files, you'll notice that the authentication logic is incomplete. The `<LoginButton />` component shows a **Sign In** or **Sign Out** button depending on whether the user is authenticated. However, if you open the **[components/LoginButton.jsx](https://github.com/ivankahl/nextjs-gotham-newspaper/blob/master/nextjs-gotham-newspaper-base/components/LoginButton.jsx#L4)** file, you'll see there's no logic to check if the user is authenticated, and the `loggedIn` variable is always `false`. Similarly, the **[page/index.jsx](https://github.com/ivankahl/nextjs-gotham-newspaper/blob/master/nextjs-gotham-newspaper-base/pages/index.jsx)** file should display a banner prompting the user to log in if they're unauthenticated and the article if the user is authenticated. However, the logic is also missing, and `loggedIn` is always `false`. You'll add this functionality as part of the tutorial.

## Adding Google Login Using NextAuth.js

The first demonstration below shows you how to use the [NextAuth.js](https://next-auth.js.org) library to add a Google Login to your website.

To get started, create a new Next.js app using the base project above as a template. Open a new terminal window and execute the following `npx` command.

```bash
npx create-next-app gotham-newspaper-website-nextauth -e https://github.com/ivankahl/nextjs-gotham-newspaper/tree/master/nextjs-gotham-newspaper-base
```

The command will create a new Next.js application in the `gotham-newspaper-website-nextauth` folder and clone the base project from the GitHub repository.

### Register Your Website in Google Cloud

Before you can add a Google login to your website using NextAuth.js, you must register your website in Google Cloud to get OAuth keys for your application.

Navigate to [Google Cloud](https://cloud.google.com) in your browser. If you have a Google account already, you can click on **Sign in**. Otherwise, click on **Start free** to create a new account.

![A screenshot of the Google Cloud home page with the Sign in and Start free button highlighted](./Ty2XAtk.png)

Once you're logged in, click the **Select a project** dropdown in the top menu. In the dialog box that appears, click **New Project** in the top right of the dialog.

![A screenshot of the dialog box that appears when clicking on the Select a project dropdown](./3XK6PJa.png)

Give your project a descriptive name and click **Create**.

![A screenshot of the Google Cloud interface prompting for a project name and location](./Xo4SoWi.png)

Wait for Google Cloud to finish creating the project, then select the project from the **Select a project** dropdown menu in the top menu. A menu will appear on the left side of the page. Find and hover over the **APIs and services** menu item. In the submenu that appears, click **OAuth consent screen**.

![A screenshot of the menu in Google Cloud with the OAuth consent screen menu item highlighted](./7ixwc5q.png)

Google Cloud will prompt you for **User Type**. Since your application will let anyone log in using Google, select the **External** user type and click on **Create**.

![A screenshot of the Google Cloud console with External User Type selected when configuring the project's OAuth consent screen](./ogSsFCV.png)

In the next screen, provide your website's information, such as the app name and user support email. You can skip the **App domain** section and click the **Save and Continue** button at the bottom of the page.

![A screenshot of Google Cloud showing the fields you need to populate for your app](./38Jiy3k.png)

Now you'll need to configure the OAuth scopes your website will need. Click on **Add or Remove Scopes**. A window should slide out from the right where you can select which scopes your application will need. In this case, since you're using only Google to authenticate the user, select the following scopes:

- ../auth/userinfo.email
- ../auth/userinfo.profile
- openid

Click on the **Update** button and continue using the **Save and Continue** button.

![A screenshot of the Google Cloud console showing the scopes you need to add to your app](./qqijiXe.png)

The screen will prompt you to specify test users for your application while it's still in development. Click **Add Users** and add your Google email address to log in to your website. You can add up to one hundred test users. Then, when you're ready to release your application, you can change it so that anyone can log in.

Once you've added the users, click on **Save and Continue** to continue to the Summary screen.

![A screenshot of Google Cloud showing a screen where you can add test users to your website](./kLLERwh.png)

Now that you've configured your website in Google Cloud, you need to retrieve your Client Key and Client Secret, which you'll use to configure NextAuth.js.

First, click on **Credentials** in the left menu and then on **Create Credentials** at the top of the screen. In the menu that appears, select **OAuth client ID**.

![A screenshot of Google Cloud with the Create Credentials menu open and OAuth client ID highlighted](./Q7KdOj0.png)

Select `Web application` in the **Application type** field and give your application a name. Then, in **Authorised JavaScript origins**, add `http://localhost:3000` as an origin. In **Authorised redirect URIs**, add `http://localhost:3000/api/auth/callback/google` as a callback URL. Finally, click **Create** at the bottom of the page.

![A screenshot of the Google Cloud console showing the configuration options for a web application using OAuth](./oEXLHq6.png)

A dialog should appear with your Client ID and Client Secret. Copy both values and keep them somewhere safe as you'll need them when configuring **NextAuth.js**.

![A screenshot of the dialog box that appears in Google Cloud with the OAuth Client ID and Client Secret for your app](./6EZkDyR.png)

### Install NextAuth.js

Open a terminal instance and navigate to your project directory. Then, run the following command to install the NextAuth.js package in your Next.js app:

```bash
npm install next-auth
```

### Add Google Login to NextAuth.js

Once the package is installed, you need to create an auth endpoint in your Next.js app for NextAuth.js. Create a new subfolder called `auth` in the `pages/api`. Then, create a new file in the folder called **\[...nextauth].js** and paste the following code in it:

```js
import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'

export const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET,
    }),
  ],
}

export default NextAuth(authOptions)
```

The code snippet above declares an `authOptions` variable containing configuration settings for your website's Google login.

Inside the `authOptions` object, notice how you access the Google ID and Secret as environment variables. To set these environment variables, create a **.env.local** file in the root directory of your project and paste the code below. Replace `<GOOGLE_ID>` and `<GOOGLE_SECRET>` with the Google ID and Secret you retrieved in the previous section when setting up your application in Google Cloud:

```plaintext
GOOGLE_ID=<GOOGLE_ID>
GOOGLE_SECRET=<GOOGLE_SECRET>
```

Lastly, you must set up `SessionProvider` in your Next.js app. This provider will let you use hooks such as the `useSession` hook and manage client sessions across browsers and windows. To do this, open your **pages/\_app.jsx** file and paste the following code:

```jsx
import '../styles/globals.css'
import { SessionProvider } from 'next-auth/react'

const App = ({ Component, pageProps: { session, ...pageProps } }) => (
  <SessionProvider session={session}>
    <Component {...pageProps} />
  </SessionProvider>
)

export default App
```

### Create Sign In with Google Button

Now that you can access the user's session inside your components, create a **Sign In with Google** button, which you'll display on your login page. In your `components` folder, create a new file called **GoogleButton.jsx** and paste the following code.

```jsx
import { signIn } from 'next-auth/react'

const GoogleButton = () => {
  return (
    <button
      className="flex w-full justify-center gap-5 rounded bg-white px-4 py-4 text-sm font-bold drop-shadow-md hover:bg-gray-50"
      onClick={() => signIn('google')}
    >
      <GoogleLogo />
      <div>Sign in with Google</div>
    </button>
  )
}

export default GoogleButton

const GoogleLogo = (props) => (
  <svg
    width="24"
    height="24"
    viewBox="0 0 775 794"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    <path
      d="M775 405.797C775 373.248 772.362 349.496 766.653 324.865H395.408V471.773H613.32C608.929 508.282 585.204 563.264 532.482 600.209L531.743 605.127L649.124 696.166L657.256 696.979C731.943 627.921 775 526.315 775 405.797"
      fill="#4285F4"
    />
    <path
      d="M395.408 792.866C502.167 792.866 591.792 757.676 657.256 696.979L532.482 600.209C499.093 623.521 454.279 639.796 395.408 639.796C290.845 639.796 202.099 570.741 170.463 475.294L165.826 475.688L43.772 570.256L42.1759 574.698C107.198 704.013 240.758 792.866 395.408 792.866Z"
      fill="#34A853"
    />
    <path
      d="M170.463 475.294C162.116 450.662 157.285 424.269 157.285 397C157.285 369.728 162.116 343.338 170.024 318.706L169.803 313.46L46.2193 217.373L42.1759 219.299C15.3772 272.961 0 333.222 0 397C0 460.778 15.3772 521.036 42.1759 574.698L170.463 475.294"
      fill="#FBBC05"
    />
    <path
      d="M395.408 154.201C469.656 154.201 519.74 186.31 548.298 213.143L659.891 104.059C591.356 40.2812 502.167 1.13428 395.408 1.13428C240.758 1.13428 107.198 89.9835 42.1759 219.299L170.024 318.706C202.099 223.259 290.845 154.201 395.408 154.201"
      fill="#EB4335"
    />
  </svg>
)
```

The button itself is relatively simple. First, you created a button that contains the Google logo and the text "Sign In with Google". Then, you called the `signIn` method included in NextAuth.js and specified that you want to sign in using Google.

### Update the Login Page and Related Components

Once you've created the Google Button, add the button to your login page. Open the **pages/login.jsx** file and replace the comment `/*Place login form here*/` with the Google button.

You'll also want to prevent logged-in users from accessing the login page. To do this, you can use the `useSession` hook and check the user's authentication status before returning the page. See the changes in the file below:

```jsx
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useSession } from 'next-auth/react'

import GoogleButton from '../components/GoogleButton'
import BrandLogo from '../components/Logo'

const Login = () => {
  // Retrieve the session and router so that we can navigate
  // the user back home if they are already authenticated
  const { status } = useSession()
  const router = useRouter()

  // If the user is authenticated, redirect them to the home
  // page
  if (status === 'authenticated') {
    router.replace('/')
  }

  return (
    <div className="grid h-screen grid-cols-8 overflow-hidden">
      <div
        className="col-span-5 overflow-hidden"
        style={{
          backgroundImage: "url('https://placeimg.com/1000/1000/nature/grayscale')",
          backgroundSize: 'cover',
        }}
      ></div>

      <div className="col-span-3 px-12 py-12">
        <BrandLogo className="mx-auto w-96" />
        <p className="mt-2 text-center">
          Gain immediate access to thousands of news articles from around the world.
        </p>
        <h2 className="mt-12 mb-8 text-2xl font-bold">Sign In</h2>
        <div className="mb-8">
          <GoogleButton />
        </div>
        <Link href="/" className="block text-center text-sm text-gray-500 underline">
          Go Back Home
        </Link>
      </div>
    </div>
  )
}

export default Login
```

You can test your app by running it using the following command in your terminal.

```bash
npm run dev
```

Click on the **Sign In** button on the home page and try to log in using the **Sign In with Google** button. You should be able to select your Google account and be redirected back to your website's home page. However, you'll still see the `LoginBanner` prompting you to sign in.

To fix this, update your `index.jsx` page and your `LoginButton.jsx` component. First, open the **pages/index.jsx** file and paste the code below, which will display the `<Article />` component to logged-in users and the `<LoginBanner />` tag to unauthenticated users:

```jsx
import { useSession } from 'next-auth/react'

import PageHeader from '../components/PageHeader'
import Article from '../components/Article'
import LoginBanner from '../components/LoginBanner'

const Home = () => {
  const { status } = useSession()

  return (
    <div>
      <PageHeader />
      {status === 'authenticated' ? <Article /> : <LoginBanner />}
    </div>
  )
}

export default Home
```

Next, open your **components/LoginButton.jsx** file and paste the following code, which will show authenticated users the **Sign Out** rather than the **Sign In** button:

```jsx
import Link from 'next/link'
import { useSession, signOut } from 'next-auth/react'

const LoginButton = ({ size, signInOnly }) => {
  // Get the user session so you can see if they are authenticated
  // or not.
  const { status } = useSession()

  const padding = size === 'large' ? 'py-2 px-4' : 'py-1 px-2'

  if (status === 'authenticated') {
    return !signInOnly ? (
      <button
        className={`${padding} rounded bg-red-600 text-sm font-bold text-white`}
        onClick={() => signOut()}
      >
        Sign Out
      </button>
    ) : null
  }

  return (
    <Link
      className={`${padding} my-1 rounded bg-red-600 text-sm font-bold text-white`}
      href="/login"
    >
      Sign In
    </Link>
  )
}

export default LoginButton
```

### Test the Google Login

Run your application using the `npm run dev` command.

Once you're authenticated, you can now see the article and a **Sign Out** button. Try logging out and in again to see how the website behaves as a logged-in and logged-out user.

Congratulations! You've implemented a Google login on your website using NextAuth.js.

However, remember that this is only the first piece of the puzzle. You must still develop additional authentication logic, like creating a database to store your registered users. For this, NextAuth.js provides [adapters](https://authjs.dev/reference/core/adapters) that let you store user details in different databases or backend systems. You'll also have to add logic and screens for registering users and, if users can sign in with a password, a "forgot password" screen.

So, while you have a simple website with authentication, some work is still needed to get it production-ready.

## Adding Google Login Using Clerk.com

[Clerk.com](/) is an authentication and user management service that lets you integrate authentication in your Next.js application with minimal effort. It also offers integrations with many third-party identity providers, such as Google.

Create a new project using the same base project mentioned previously. Execute the following `npx` command in a new terminal window.

```bash
npx create-next-app gotham-newspaper-website-clerkdev -e https://github.com/ivankahl/nextjs-gotham-newspaper/tree/master/nextjs-gotham-newspaper-base
```

### Register with Clerk.com

Before you can integrate Clerk.com in your Next.js app, you'll need to sign up for an account and create an application.

![A screenshot of the signup page in Clerk.com](./QgHgM2j.png)

[Sign up for a Clerk.com account](https://dashboard.clerk.com/sign-up). Once you've verified your email address and phone number (if you specified one), you'll land on the Dashboard page, where you can create a new application.

### Create an Application in Clerk.com

On your Clerk.com Dashboard, click on **Add application** to create an application in Clerk.com for your Next.js app.

![A screenshot of the Clerk.com Dashboard with no applications](./6xtu8sC.png)

Clerk.com will prompt you for your application's name. You'll also need to select which methods of authentication you want for your application. After naming your application, switch on **Email** in the **Standard Authentication** section and **Google** under the **Social Connections** header in the **Connected accounts** section.

![A screenshot of Clerk.com showing the interface where you configure sign in for your app](./4Rs67Vv.png)

Click **Finish** to continue to your application screen.

When configuring Clerk.com in your Next.js app, you'll need to specify some environment variables for Clerk.com. You can access these environment variables by clicking on **API Keys** in the left menu.

![A screenshot of the Clerk.com dashboard showing the API Keys for your app](./BGt21r1.png)

Copy your **Frontend API key** somewhere as you'll need it in the next section. You can also click the **Show key** in the **Backend API keys** section and copy that. Finally, copy the **JWT verification key** and store it somewhere handy.

### Install the Clerk.com Package

Clerk.com has created an [npm package](https://www.npmjs.com/package/@clerk/nextjs) that simplifies adding Clerk.com authentication to your Next.js application. Install it in your app using the following command:

```bash
npm install @clerk/nextjs
```

### Configure Clerk.com in the Next.js App

Once the package has finished installing, set up the environment variables needed for Clerk.com. In your project's root directory, create a new file called **.env.local** and paste the following code, but replace `<CLERK_FRONTEND_API>`, `<CLERK_API_KEY>`, and `<CLERK_JWT_KEY>` with the API Keys you retrieved in the Clerk.com Dashboard:

```plaintext
NEXT_PUBLIC_CLERK_FRONTEND_API=<CLERK_FRONTEND_API>
CLERK_API_KEY=<CLERK_API_KEY>
CLERK_JWT_KEY=<CLERK_JWT_KEY>
```

You'll notice that the code snippet prefixes the Clerk Frontend API key with `NEXT_PUBLIC_` so that it [can be accessed on the client side in your Next.js application](https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser).

Now, surround your application in the `<ClerkProvider />` component so your app can check if the user is authenticated and use other features in Clerk.com. To do so, open your **pages/\_app.jsx** file and surround your `<Component />` component with a `<ClerkProvider />` element. The sample below shows the final result:

```jsx
import '../styles/globals.css'
import { ClerkProvider } from '@clerk/nextjs'

const App = ({ Component, pageProps }) => (
  <ClerkProvider {...pageProps}>
    <Component {...pageProps} />
  </ClerkProvider>
)

export default App
```

That's all that's needed to get Clerk.com to work in your Next.js app.

One thing to note is that if you're using Next.js API routes or server-side rendering that relies on authentication, you'll need to [configure the Clerk.com middleware](/docs/nextjs/configure-middleware) as well. However, you can skip this step since this demonstration uses neither of these features.

### Update the Login Page and Related Components

Now that Clerk.com is set up, you can add the `<SignIn />` component to your login page. This component will render the login form, which prompts users to log in with Google login or to use an email address. The page should also redirect authenticated users to the home page.

Open the **pages/login.jsx** file and replace the code there with the following code sample:

```jsx
import { SignIn, useUser } from '@clerk/nextjs'
import Link from 'next/link'
import { useRouter } from 'next/router'
import colors from 'tailwindcss/colors'

import BrandLogo from '../components/Logo'

const Login = () => {
  const { isLoaded, isSignedIn } = useUser()
  const router = useRouter()

  // Redirect the user if they are already authenticated
  if (isLoaded && isSignedIn) router.replace('/')

  return (
    <div className="grid h-screen grid-cols-8 overflow-hidden">
      <div
        className="col-span-5 overflow-hidden"
        style={{
          backgroundImage: "url('https://placeimg.com/1000/1000/nature/grayscale')",
          backgroundSize: 'cover',
        }}
      ></div>

      <div className="col-span-3 px-12 py-12">
        <BrandLogo className="mx-auto w-96" />
        <p className="mt-2 text-center">
          Gain immediate access to thousands of news articles from around the world.
        </p>
        <h2 className="mt-12 mb-8 text-2xl font-bold">Sign In</h2>
        <div className="mb-8">
          <SignIn
            appearance={{
              variables: { colorPrimary: colors.red[600] },
              elements: { rootBox: 'mx-auto' },
            }}
          />
        </div>
        <Link href="/" className="block text-center text-sm text-gray-500 underline">
          Go Back Home
        </Link>
      </div>
    </div>
  )
}

export default Login
```

The `<SignIn />` component [offers customization options](/docs/nextjs/appearance-prop) that let you customize the component's appearance. In this case, the code sets the primary color to the website's primary color and the sign-in form is centered using the `mx-auto` TailwindCSS class.

Run your app using the `npm run dev` command and navigate to your website in a browser. When you click on **Sign In** and are taken to the login page, you'll notice the Clerk.com sign-in component.

![A screenshot of your Gotham website login screen containing the Clerk.com sign-in component](./5cbDied.png)

Test your authentication by clicking on **Continue with Google**. Once you're authenticated, the app should redirect you to the home page.

However, you'll still see the `<LoginBanner />` component instead of the article. Fix this by opening the **pages/index.jsx** file and replacing the code there with the following code sample, which will check whether the user is authenticated and show the appropriate component:

```jsx
import PageHeader from '../components/PageHeader'
import Article from '../components/Article'
import LoginBanner from '../components/LoginBanner'
import { SignedIn, SignedOut } from '@clerk/nextjs'

const Home = () => (
  <div>
    <PageHeader />
    <SignedIn>
      <Article />
    </SignedIn>
    <SignedOut>
      <LoginBanner />
    </SignedOut>
  </div>
)

export default Home
```

The code sample uses the `<SignedIn />` and `<SignedOut />` components from Clerk.com. The `<SignedIn />` component will [display its contents to logged-in users](/docs/component-reference/signed-in) while the `<SignedOut />` component [displays its contents to unauthenticated users](/docs/component-reference/signed-out).

You must also update the `<LoginButton />` component to show authenticated users the **Sign Out** button. Do this by opening the **components/LoginButton.jsx** file and replacing the contents with the following.

```jsx
import Link from 'next/link'
import { useAuth } from '@clerk/nextjs'

const LoginButton = ({ size, signInOnly }) => {
  const { isLoaded, isSignedIn, signOut } = useAuth()

  const padding = size === 'large' ? 'py-2 px-4' : 'py-1 px-2'

  if (isLoaded && isSignedIn && !signInOnly) {
    return (
      <button
        className={`${padding} rounded bg-red-600 text-sm font-bold text-white`}
        onClick={() => signOut()}
      >
        Sign Out
      </button>
    )
  }

  return (
    <Link
      className={`${padding} my-1 rounded bg-red-600 text-sm font-bold text-white`}
      href="/login"
    >
      Sign In
    </Link>
  )
}

export default LoginButton
```

Notice how the code sample above uses the `useAuth` hook instead of the `useUser` hook. The `useAuth` hook is similar to the `useUser` hook. However, it also returns a `signOut` method used in the **Sign Out** button's `onClick` handler to sign the user out.

Rerun your application using the `npm run dev` command. Next, test authenticating and logging out of your Google account. The website should display the article and **Sign Out** button when logged in and the login banner and **Sign In** button when logged out.

## NextAuth.js vs. Clerk.com

As is clear from this tutorial, Clerk.com is easier to implement with fewer and simpler steps than NextAuth.js. It also has some added benefits.

Clerk.com manages the OAuth Keys required to make Google authentication work and lets you add [other social logins](/features/social-sso) such as Facebook, Twitter, GitHub, and more by simply toggling it in your dashboard.

With NextAuth.js, the security burden falls on you as the developer. You're responsible for transporting and saving user credentials. You also need to develop additional functionality like the "forgot password" flow and, where applicable, ensure you're GDPR and CCPA compliant.

Clerk.com [simplifies user management and authentication](/features/passwords) by managing the authentication process and storing your user's credentials securely. It provides standard functionality like "forgot password" out of the box. It also lets you view all the users who have signed up to your website, enable/disable them, and more without any additional development on your part.

Clerk.com is also already [GDPR and CCPA compliant](/features/security). They are regularly audited by third parties and conduct pen testing to ensure their infrastructure and services are secure.

If you want to provide additional security for your users using OTP codes using NextAuth.js, you'll have to develop this logic manually. Clerk.com provides [out-of-the-box support for OTP codes using both SMS and email](/features/email-sms-passcodes-otp).

With Web3 gaining traction, you might want to support logging in with Web3. While NextAuth.js's [Credentials provider](https://next-auth.js.org/providers/credentials#example---web3--signin-with-ethereum) lets you use Web3, it does require [significant development](https://docs.login.xyz/integrations/nextauth.js). Adding [Web3 authentication](/features/web3) to your app with Clerk.com is pretty effortless. Simply enable your application's authentication with Metamask and use it alongside other authentication providers such as Google login and with other Clerk.com features such as OTP codes.

## Conclusion

This article showed you how to integrate Google login manually with NextAuth.js as well as how to do it with Clerk.com's user management service. The code for both methods is in [this GitHub repository](https://github.com/ivankahl/nextjs-gotham-newspaper).If you enjoyed this article, you might also like our guide to [implementing session-based authentication with React and Express](/blog/building-a-react-login-page-template).

Compared to using NextAuth.js, Clerk.com is easier and provides additional benefits like out-of-the-box "forgot password", OTP, and Web3 authentication functionality as well as user management features. It's also GDPR and CCPA compliant.

---

# Guide to Conditional Rendering in React
URL: https://clerk.com/blog/conditional-rendering-react.md
Date: 2023-01-25
Category: Guides
Description: Learn how conditional rendering is used to show a personalized UI, complete a user flow without changing routes, or show a loading or error state.

Conditional rendering is a pattern used in React to render a different user interface (UI) based on whether a condition is `true` or `false`. This can be as simple as rendering a loading message while waiting for an API to return the data, where the loading message is conditionally rendered based on whether the loading is `true` or `false`.

Conditional rendering is quite helpful for showing a personalized UI based on the user's preference, completing a user flow without changing routes, or showing a loading or error state.

In this article, you'll learn about different conditional rendering methods in React applications. You'll use the [Clerk client for React](/docs/reference/clerk-react/installation) to implement a simple dashboard application that conditionally shows the UI based on whether or not the user is signed in.

## What's Conditional Rendering in React?

Conditional rendering in React allows you to implement interactive interfaces where you render different UIs based on the application state; these can range from user inputs to user preferences. Let's dig into conditional rendering with some practical use cases.

### Showing Personalized UIs

This can be based on your preference as a user and is one of the most common uses you'll see out there. Consider [Twitter](https://twitter.com), for example. You'll only see the **Explore** section if you're not signed in to Twitter.

![Twitter hiding sections conditionally](./nxa2ZXD.png)

When you're signed in, you'll see a personalized feed in sections like **Home** and **Messages**.

![Conditionally show personalized feed in Twitter](./x1wicjE.png)

### Completing a User Flow without Changing Routes

This is another use case for conditional rendering. Consider [Typeform](https://www.typeform.com/templates/t/user-persona-survey-template), for example. The application has multiple pages in a single form, but rather than navigating to a new page for every question, it uses conditional rendering to show only the current question.

![Conditional rendering in Typeform](./5cOXLts.jpg)

### Showing a Loading or Error State

This is essential for any application dealing with data loading. Consider Twitter again. See how **Home** and **Trending** both show a loader while fetching the feed.

![Conditional rendering for loading](./0B4g0lH.png)

## Implementing Conditional Rendering on Authentication

There are a few ways to do conditional rendering in React, and you'll learn about five of them in this article. You can follow the examples by setting up this [GitHub repository](https://github.com/Anshuman71/conditional-rendering-clerk) on your local drive.

### "If…else" Statements

You can use the good old `if…else` conditional statement in JavaScript. You can use the `if` condition to return a certain JSX if the user is signed in and something else if they aren't.

```tsx
// AppWithIf.jsx

function App() {
  const isLoggedIn = true
  if (isLoggedIn) {
    return <div className="App">Hello, logged in user!</div>
  } else {
    return <div>User not logged in!</div>
  }
}

export default App
```

### The Conditional (Ternary) Operator

The [conditional (ternary) operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) can also be used to check whether the user is signed in and return components accordingly.

The ternary operator is a good choice if you've abstracted your JSX into components:

```tsx
// AppWithTernary.jsx

function SignedIn() {
  return <div className="App">Hello, logged in user!</div>
}

function SignedOut() {
  return <div>User not logged in!</div>
}

function App() {
  const isLoggedIn = true
  return isLoggedIn ? <SignedIn /> : <SignedOut />
}

export default App
```

### The Switch Case

The switch case is useful when you want to conditionally render a component based on a range of choices—for example, if you're conditionally rendering the component based on the user's permission level, as shown below:

```tsx
// AppWithSwitch.jsx

function Viewer() {
  return <div className="App">Hello, logged in as Viewer!</div>
}

function SignedOut() {
  return <div>User not logged in!</div>
}

function Admin() {
  return <div className="App">Hello, logged in as Admin!</div>
}

function Editor() {
  return <div className="App">Hello, logged in as Editor!</div>
}

function App() {
  const userPermission = 'admin'
  switch (userPermission) {
    case 'viewer':
      return <Viewer />
    case 'editor':
      return <Editor />
    case 'admin':
      return <Admin />
    default:
      return <SignedOut />
  }
}

export default App
```

### Immediately Invoked Function Expressions (IIFE)

An IIFE is a good option if you want to use the conditional statement within the `return` statement. In this example, the anonymous function below the `h1` tag runs on every render and returns the JSX based on the user's login state:

```tsx
// AppWithIIFE.jsx

function App() {
  const isLoggedIn = true
  return (
    <div>
      <h1>Amazing application</h1>
      {(function () {
        if (isLoggedIn) {
          return <div className="App">Hello, logged in user!</div>
        } else {
          return <div>User not logged in!</div>
        }
      })()}
    </div>
  )
}

export default App
```

### Higher-Order Components

A [higher-order component](https://reactjs.org/docs/higher-order-components.html) (HOC) is a pattern for reusing component logic. You can use a HOC to abstract the authentication logic with multiple components. In this example, the `withAuth` function is a HOC that takes a component as input and returns another component with conditional rendering based on the user's login state:

```tsx
// AppWithHOC.jsx

import { useEffect, useState } from 'react'

async function getUserAuth() {
  // get Auth state from somewhere
  return true
}

function withAuth(Component) {
  return function ComponentWithAuth() {
    const [isLoggedIn, setLoggedIn] = useState(true)
    useEffect(() => {
      getUserAuth().then((auth) => setLoggedIn(auth))
    }, [])
    return isLoggedIn ? <Component /> : <div>Please log in to view this component.</div>
  }
}

function Dashboard({}) {
  return (
    <div>
      <h1>Amazing application</h1>
      <p>Best dashboard</p>
    </div>
  )
}

const DashboardWithAuth = withAuth(Dashboard)

function App() {
  return <DashboardWithAuth />
}

export default App
```

## Conditional Rendering with Clerk

You've now learned about different ways of using conditional rendering for authentication. You can see that dealing with authentication can get very messy: the more auth state you manage, the more complex the conditionals become. What if there was an authentication provider that takes care of all the conditional rendering for you?

Next you'll see how the Clerk frontend client can be used to implement conditional rendering based on the user's authentication state.

Run the following command in your terminal to create a new React project:

```shell
npx create-react-app clerk-react-conditionals
```

Navigate to the newly made project in your terminal by running the following:

```shell
cd clerk-react-conditionals
```

Now install the Clerk React client using the following command:

```shell
npm install @clerk/clerk-react
```

Log in to your Clerk dashboard and copy the frontend API key from the **API keys** page.

![Copy frontend API key from Clerk](./gCZCwfD.png)

Create the new file **.env.local** and securely save the frontend API key like so:

```bash
REACT_APP_CLERK_FRONTEND_API=<paste-the-key-from-clerk-dashboard>

```

*Note:* Don't commit the **.env.local** file to keep the key safe.

In the **App.js** file, add the `ClerkProvider` at the top level in the `App` component. Pass the `ClerkProvider` with the `frontendApi` prop from the environment variables. The `ClerkProvider` provides the authentication state and methods to all the child components:

```tsx
import React from 'react'
import {
  ClerkProvider,
  SignedIn,
  SignedOut,
  SignOutButton,
  SignInButton,
  useUser,
} from '@clerk/clerk-react'

const frontendApi = process.env.REACT_APP_CLERK_FRONTEND_API

function App() {
  return (
    <ClerkProvider frontendApi={frontendApi}>
      <SignedIn>
        <p style={{ padding: 20 }}>Welcome to the amazing dashboard!</p>
      </SignedIn>
      <SignedOut>
        <p style={{ padding: 20 }}>You must be signed in to use the dashboard.</p>
      </SignedOut>
    </ClerkProvider>
  )
}
```

The `SignedIn` and `SignedOut` components from Clerk conditionally render the children. The `SignedIn` component renders children if the user is signed in, and the `SignedOut` component renders children if they're not. This example renders different messages, but you can use any other component according to your application.

Run `npm start` in your terminal to start the application and open [http://localhost:3000](http://localhost:3000) in a web browser. You should see the following message.

![Signed-out user view](./FqK1818.png)

### Using the React Hook

The dashboard conditionally renders different messages based on a user's sign-in state, but the user still needs the option to sign in. As a good practice, you can put the **Sign in** and **Sign out** buttons at the top `NavBar` component:

```tsx
import React from 'react'
import {
  ClerkProvider,
  SignedIn,
  SignedOut,
  SignOutButton,
  SignInButton,
  useUser,
} from '@clerk/clerk-react'

function NavBar() {
  const { user, isSignedIn } = useUser()
  return (
    <nav
      style={{
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        padding: '10px 20px',
        backgroundColor: 'peachpuff',
      }}
    >
      <h2>Amazing dashboard</h2>
      {isSignedIn ? (
        <div style={{ display: 'flex', alignItems: 'center' }}>
          <p style={{ marginRight: 10 }}>Hello, {user.firstName}!</p>
          <SignOutButton />
        </div>
      ) : (
        <SignInButton />
      )}
    </nav>
  )
}
```

The `NavBar` component uses the `useUser` hook from Clerk to get the `user` object and `isSignedIn` Boolean flag. The component renders a navbar with an `h2` "Amazing dashboard" and, depending on the value of `isSignedIn`, displays either a greeting with the user's first name and a `SignOutButton` component or a `SignInButton` component.

Now use the `NavBar` component in the `App`. The final application code should look as shown below:

```tsx
import React from 'react'
import {
  ClerkProvider,
  SignedIn,
  SignedOut,
  SignOutButton,
  SignInButton,
  useUser,
} from '@clerk/clerk-react'

const frontendApi = process.env.REACT_APP_CLERK_FRONTEND_API

function App() {
  return (
    <ClerkProvider frontendApi={frontendApi}>
      <NavBar />
      <SignedIn>
        <p style={{ padding: 20 }}>Welcome to the amazing dashboard!</p>
      </SignedIn>
      <SignedOut>
        <p style={{ padding: 20 }}>You must be signed in to use the dashboard.</p>
      </SignedOut>
    </ClerkProvider>
  )
}

function NavBar() {
  const { user, isSignedIn } = useUser()
  return (
    <nav
      style={{
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        padding: '10px 20px',
        backgroundColor: 'peachpuff',
      }}
    >
      <h2>Amazing dashboard</h2>
      {isSignedIn ? (
        <div style={{ display: 'flex', alignItems: 'center' }}>
          <p style={{ marginRight: 10 }}>Hello, {user.firstName}!</p>
          <SignOutButton />
        </div>
      ) : (
        <SignInButton />
      )}
    </nav>
  )
}

export default App
```

Your secured dashboard application can be seen in action below.

## Conclusion

After completing this tutorial, you'll have successfully built a secured dashboard application that conditionally renders specific UIs according to the user's sign-in state. While doing so, you learned about different ways of conditionally rendering the UI in React. You also discovered various components and hooks that Clerk provides to render UIs conditionally depending on the user's authentication status.

[Clerk](/) is a complete user management solution with [pre-built components](/docs/component-reference/overview), hooks, and even a [user interface](/docs/users/user-profile) for user profile management. Clerk is an easy-to-integrate solution for your React applications with first-class support for all modern frameworks such as Next.js, Remix, and RedwoodJS. [Give Clerk a try](https://dashboard.clerk.com/sign-in) for free to explore a complete list of its [features](/docs).

---

# Next.js 13 Routes Part 2: Implementing Protected Routes
URL: https://clerk.com/blog/next13-api-routes-2.md
Date: 2023-01-25
Category: Guides
Description: Learn how to create protected routes using React Context as well as how using Clerk makes this process easier.

In part one of this series, you learned about Next.js API routes and how to protect API routes with JWT authentication. In this part, you'll learn how to create protected routes using React Context as well as how using [Clerk](/) makes this process easier.

## Exploring the Starter App

To get started, a starter app already has been made that you can clone from [GitHub](https://github.com/heraldofsolace/NextJS-protected-routes-demo):

```bash
git clone https://github.com/heraldofsolace/NextJS-protected-routes-demo.git
cd NextJS-protected-routes-demo
yarn install
yarn dev
```

The app will start running at `localhost:3000`.

The posts page can be found at `http://localhost:3000/posts`, which shows a list of all the posts.

![List of all posts](./d2kASE5.png)

This page has a companion API route that returns all the posts in JSON:

```bash
$ curl "http://localhost:3000/api/posts"
[{"id":1,"userId":1,"text":"Hello, World!"},{"id":2,"userId":2,"text":"Hello, NextJS"},{"id":3,"userId":1,"text":"Lorem ipsum dolor sit amet. "},{"id":4,"userId":3,"text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ut rhoncus neque. Sed lacinia magna a mi tincidunt, ac interdum."}]
```

The data for posts is stored in **data.js**.

The `/api/auth/login` route implements JWT authentication and returns a JWT when the correct username and password combination is supplied:

```bash
$ curl -X POST "http://localhost:3000/api/auth/login" -d '{"username": "john", "password": "password"}' -H 'Content-Type: application/json'
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjMsImxvY2F0aW9uIjoiRnJhbmNlIiwibmFtZSI6IkpvaG4iLCJpYXQiOjE2Njk0NDUzMDQsImV4cCI6MTY2OTUzMTcwNH0.mlShbJr6xG8TIOyY6B2gD0c-leoyw1T3Sr5EncTgl00"}
```

Finally, the `/api/users/me` route returns the currently authenticated user, provided a valid JWT is passed in the header:

```bash
$ curl http://localhost:3000/api/users/me -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjMsImxvY2F0aW9uIjoiRnJhbmNlIiwibmFtZSI6IkpvaG4iLCJpYXQiOjE2Njk0NDUzMDQsImV4cCI6MTY2OTUzMTcwNH0.mlShbJr6xG8TIOyY6B2gD0c-leoyw1T3Sr5EncTgl00"
{"id":3,"username":"john","name":"John","location":"France"}
```

The user profiles can also be found in **data.js**.

The goal of the article is to protect the `/api/posts` API route and the `/posts` page using the JWT authentication strategy. In part one, you saw how JWT authentication can be added to API routes using the `jwt.verify` method. However, it's resource intensive to manually verify and decode the JWT in every single API route. It's also tedious to manually include the authentication header in every request that you make from a page.

In this article, you'll learn how to "share" an authenticated session across all pages by using an `AuthContext`. You'll also refactor the JWT verification to a `withAuth` wrapper that will make it easy to protect API routes. Finally, you'll see how using Clerk makes this process smooth and seamless.

## Implementing AuthContext

`AuthContext` is simply a [React Context](https://reactjs.org/docs/context.html) that will make it easy to pass required authentication parameters throughout the app. To implement this, first install the required libraries:

```bash
yarn add js-cookie axios
```

`js-cookie` will be used to store the JWT in the browser's cookie. `axios` makes it easy to preconfigure a default API service with headers. You'll use this to include the token in the headers once the user logs in.

Create a file named **api.js** in the project root:

```javascript
import Axios from 'axios'

const api = Axios.create({
  baseURL: 'http://localhost:3000',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
})

export default api
```

Here, an instance of `axios` is created that will be used to make API calls later.

Create the file `auth_context.js`:

```javascript
import React, { createContext, useState, useContext, useEffect } from 'react'
import Cookies from 'js-cookie'
import api from './api'
import jwt from 'jsonwebtoken'

const JWT_KEY = process.env.JWT_SECRET_KEY
const AuthContext = createContext({})

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null)
  const [isLoading, setIsLoading] = useState(true)

  useEffect(() => {
    async function fetchUserFromCookie() {
      const token = Cookies.get('token')
      if (token) {
        api.defaults.headers.Authorization = `Bearer ${token}`
        const { data: user } = await api.get('api/users/me')
        if (user) setUser(user)
      }
      setIsLoading(false)
    }
    fetchUserFromCookie()
  }, [])

  const login = async (username, password) => {
    const {
      data: { token },
    } = await api.post('api/auth/login', { username, password })
    console.log('TOKEN ', token)
    if (token) {
      Cookies.set('token', token, { expires: 60 })
      api.defaults.headers.Authorization = `Bearer ${token}`
      const { data: user } = await api.get('api/users/me')
      setUser(user)
    }
  }

  const logout = () => {
    Cookies.remove('token')
    setUser(null)
    delete api.defaults.headers.Authorization
    window.location.pathname = '/login'
  }

  return (
    <AuthContext.Provider
      value={{
        isAuthenticated: !!user,
        user,
        login,
        loading: isLoading,
        logout,
      }}
    >
      {children}
    </AuthContext.Provider>
  )
}

export const useAuth = () => useContext(AuthContext)
```

The most important bits in the above Context are the `fetchUserFromCookie`, `login`, and `logout` functions. The `fetchUserFromCookie` function fetches the token from the cookie and sets the `authorization` header in the default `api` instance.

It then makes a call to `/api/users/me` to retrieve and store the authenticated user. The `login` function logs in the user through the `/api/auth/login` route and stores the token in the cookie. The `logout` function deletes the user, the cookie, and the `authorization` header.

Finally, create the `withAuth` function that'll protect the API routes by wrapping the handlers:

```javascript
export const withAuth = (handler) => {
  return (req, res) => {
    const { authorization } = req.headers
    if (!authorization)
      return res.status(401).json({ error: 'The authorization header is required' })
    const token = authorization.split(' ')[1]

    jwt.verify(token, JWT_KEY, (err, payload) => {
      if (err) return res.status(401).json({ error: 'Unauthorized' })
      req.auth = { user: payload }
      handler(req, res)
    })
  }
}
```

You can now modify `pages/api/posts.js` to include `withAuth`:

```javascript
import { withAuth } from '../../auth_context'
import { users, posts } from '../../data'

export default withAuth((req, res) => {
  const { userId } = req.auth.user

  const userPosts = posts.filter((post) => {
    return post.userId == userId
  })

  res.status(200).json(userPosts)
})
```

Note that only the posts by the logged in user are returned. The logged in user is found through `req.auth.user`.

Let's now create the login page. First, add [Formik](https://formik.org) and [Yup](https://www.npmjs.com/package/yup). These are not strictly required but will help in creating the login form.

```bash
yarn add formik yup
```

Create `pages/login.js`:

```javascript
import React from 'react'
import { Formik, ErrorMessage, Form, Field } from 'formik'
import * as Yup from 'yup'
import { useAuth } from '../auth_context'
import { useRouter } from 'next/router'
import api from '../api'

const LoginForm = () => {
  const { login } = useAuth()
  const router = useRouter()
  return (
    <Formik
      initialValues={{ username: '', password: '' }}
      validationSchema={Yup.object({
        username: Yup.string().required('Required'),
        password: Yup.string().required('Required'),
      })}
      onSubmit={async ({ username, password }, { setSubmitting, setErrors }) => {
        try {
          await login(username, password)
          setSubmitting(false)
          router.push('/posts')
        } catch (error) {
          const formikErrors = { password: error.response.data.error }
          setErrors(formikErrors)
          setSubmitting(false)
        }
      }}
    >
      {({ isSubmitting }) => (
        <Form>
          <div>
            <label>Username</label>
            <br />
            <Field name="username" type="text"></Field>
            <ErrorMessage name="username" component="p"></ErrorMessage>
          </div>
          <div>
            <label>Password</label>
            <br />
            <Field name="password" type="password"></Field>
            <ErrorMessage name="password" component="p"></ErrorMessage>
          </div>
          <button type="submit" disabled={isSubmitting}>
            Login
          </button>
        </Form>
      )}
    </Formik>
  )
}

export default LoginForm
```

This page uses the `login` function described above to log in the user.

Now update `pages/posts.js` to make use of `AuthContext`:

```javascript
import { useEffect, useState } from 'react'
import api from '../api'
import { useAuth } from '../auth_context'

export default function Posts() {
  const [posts, setPosts] = useState(null)
  const { user, logout } = useAuth()
  console.log(user)
  useEffect(() => {
    async function fetchPosts() {
      const { data: postsList } = await api.get('api/posts')
      setPosts(postsList)
      console.log(postsList)
    }
    if (user) fetchPosts()
  }, [user])

  return (
    <>
      <ul>
        {posts?.map((post) => {
          return <li key={post.id}>{post.text}</li>
        })}
      </ul>
      <button onClick={logout}>Logout</button>
    </>
  )
}
```

Finally, update `pages/_app.js` to wrap everything in `AuthProvider`:

```javascript
import '../styles/globals.css'
import { AuthProvider } from '../auth_context'

function MyApp({ Component, pageProps }) {
  return (
    <AuthProvider>
      <Component {...pageProps} />
    </AuthProvider>
  )
}

export default MyApp
```

Start the server with `yarn dev` and visit `http://localhost:3000/login`. Log in with the credentials (you can find the username in **data.js** and the password is "password") and you'll be redirected to the posts page. You can verify that you're only seeing posts from the logged in user.

The final app for this section can be found in the `manual` branch of the [GitHub repo](https://github.com/heraldofsolace/NextJS-protected-routes-demo.git).

## Authentication with Clerk

In this section, you'll replace the manual authentication with [Clerk](/). Before starting with Clerk, you should revert the changes you've made so far. You can simply run `git stash && git clean -fdx` to stash your changes.

First, [create an application](/docs/authentication/set-up-your-application) in Clerk. You can keep all the default options.

![Creating an application in Clerk](./vvJUUtJ.png)

Once the application is created, go to the **API keys** page and copy the frontend API key, the backend API key, and the JWT verification key. Paste these into `.env`:

```
NEXT_PUBLIC_CLERK_FRONTEND_API=your_frontend_api_key
CLERK_API_KEY=your_backend_api_key
CLERK_JWT_KEY=your_jwt_key
```

Install the required library:

```bash
yarn add @clerk/nextjs
```

Wrap `pages/_app.js` with `Clerkprovider`:

```javascript
import { ClerkProvider, SignedIn, SignedOut, RedirectToSignIn } from '@clerk/nextjs'
import { useRouter } from 'next/router'

const publicPages = ['/']

function MyApp({ Component, pageProps }) {
  const { pathname } = useRouter()
  const isPublicPage = publicPages.includes(pathname)

  return (
    <ClerkProvider {...pageProps}>
      {isPublicPage ? (
        <Component {...pageProps} />
      ) : (
        <>
          <SignedIn>
            <Component {...pageProps} />
          </SignedIn>
          <SignedOut>
            <RedirectToSignIn />
          </SignedOut>
        </>
      )}
    </ClerkProvider>
  )
}

export default MyApp
```

The `publicPages` array decides which pages will not be protected under authentication. For a protected page, if the user is not signed in, they will be redirected to the login page.

Create the file **middleware.js** in the project route:

```javascript
import { withClerkMiddleware } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'

export default withClerkMiddleware((req) => {
  return NextResponse.next()
})

// Stop Middleware running on static files
export const config = { matcher: '/((?!.*\\.).*)' }
```

Modify `pages/api/posts.js` to include the `getAuth` function that authenticates the user with Clerk:

```javascript
import { posts } from '../../data'
import { getAuth } from '@clerk/nextjs/server'

export default function handler(req, res) {
  const { userId } = getAuth(req)
  const userPosts = posts.filter((post) => {
    return post.userId == userId
  })

  res.status(200).json(userPosts)
}
```

In the Clerk dashboard, go to the **Users** page and create a test user.

![Creating a new user](./qKmIBQi.png)

After the user is created, open the record and copy the ID as shown below.

![Copying user ID](./a1f73gA.png)

Open **data.js** and replace the numeric `id` field of any one user and the `userId` field in the `posts` array:

```javascript
export const users = [
  {
    id: 'user_2IUxt1YsiCfebtlUwOe5dU91Det',
    username: 'bob',
    name: 'Bob',
    location: 'USA',
    password: '$2y$10$mj1OMFvVmGAR4gEEXZGtA.R5wYWBZTis72hSXzpxEs.QoXT3ifKSq',
  },
  // ...
]

export const posts = [
  {
    id: 1,
    userId: 'user_2IUxt1YsiCfebtlUwOe5dU91Det',
    text: 'Hello, World!',
  },
  // ...
  {
    id: 3,
    userId: 'user_2IUxt1YsiCfebtlUwOe5dU91Det',
    text: 'Lorem ipsum dolor sit amet. ',
  },
  // ...
]
```

Run the server again with `yarn dev`. Visit `http://localhost:3000/posts` and you should be redirected to Clerk's login page.

![Clerk's login page](./j8qJYJV.png)

After logging in, you'll be redirected back to the `/posts` page. Verify that you can see only the posts corresponding to the logged in user.

![The posts page](./IYQC9tp.png)

## Conclusion

Protecting Next.js routes with authentication is a vital part of developing any web app. However, manually creating authentication mechanisms can be tedious and time-consuming. A solution like Clerk’s [Next.js authentication](/nextjs-authentication) comes with all the bells and whistles so that you don't need to worry about auth and can focus on the core app instead.

---

# Next.js 13 Routes Part 1: Getting Started with Next.js API Routes
URL: https://clerk.com/blog/next13-api-routes-1.md
Date: 2023-01-25
Category: Guides
Description: API routes in Next.js provide a solution to build server-side API logic.

An API route creates a server-side bundle separate from the client-side bundle. As is usual for Next.js pages, file-based routing is used to create API routes, where files inside `pages/api` are mapped to `/api/*` routes.

Apart from building the backend logic, you can use API routes to run logic that depends on a secret you don't want to expose to the client—for example, connecting to a database through a database URL string. Since API routes are server-side only, you don't have to worry about exposing the database credentials to the client.

You can also use API routes to mask external service URLs. For example, if you call `https://some-service/foo`, you can route it through an API route such as `/api/foo` to hide the actual URL used.

In this article, you'll get hands-on experience in building API routes while learning about different types of API routes in Next.js.

## Implementing API Routes in Next.js

To follow this tutorial, make sure you have [Node.js 14.6.0](https://nodejs.org) or newer. This article uses [Yarn](https://yarnpkg.com) as the package manager, but you can also use npm. If you'd like to see the code of the finished application, you can find it in this [GitHub repo](https://github.com/heraldofsolace/nextjs-api-demo).

First, create a Next.js app:

```sh
yarn create next-app
```

Once you're prompted, choose a name for your app—for example, `api-routes-demo`. Select **No** when asked if you want to use TypeScript. You can keep the default answers to all the other questions. After the app is created, move into the app directory. You can delete the **pages/api/hello.js** file that was created by default.

To work with the app, you'll need some sample data. To keep things simple, you'll use a static data set, but in a real-world app, you'll likely use a database.

Create the file **data.js** in the project root:

```jsx
export const users = [
  {
    id: 1,
    username: 'bob',
    name: 'Bob',
    location: 'USA',
  },
  {
    id: 2,
    username: 'alice',
    name: 'Alice',
    location: 'Sweden',
  },
  {
    id: 3,
    username: 'john',
    name: 'John',
    location: 'France',
  },
]

export const posts = [
  {
    id: 1,
    userId: 1,
    text: 'Hello, World!',
  },
  {
    id: 2,
    userId: 2,
    text: 'Hello, NextJS',
  },
  {
    id: 3,
    userId: 1,
    text: 'Lorem ipsum dolor sit amet. ',
  },
  {
    id: 4,
    userId: 3,
    text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ut rhoncus neque. Sed lacinia magna a mi tincidunt, ac interdum.',
  },
]

export const comments = [
  {
    id: 1,
    postId: 1,
    userId: 2,
    text: 'Hi there!',
  },
  {
    id: 2,
    postId: 1,
    userId: 3,
    text: 'Lorem ipsum',
  },
  {
    id: 3,
    postId: 2,
    userId: 1,
    text: 'Nulla bibendum risus sed vestibulum lobortis. Fusce.',
  },
  {
    id: 4,
    postId: 2,
    userId: 1,
    text: 'In ut nulla vitae dolor scelerisque lacinia. ',
  },
  {
    id: 5,
    postId: 2,
    userId: 1,
    text: 'Praesent semper enim eu ligula rutrum finibus.',
  },
]
```

## Basics of API Routes

The heart of the API routes is the pages/api directory. Any file in this directory is mapped to a route of the form `/api/*`. So, the file `pages/api/foo.js` will get mapped to `/api/foo`. To make the API route work, you'll need to export a default function from the file, as shown below:

```jsx
export default function handler(req, res) {}
```

The function receives two arguments:

- `req`: An instance of [http.IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage), with some [pre-built middleware](https://nextjs.org/docs/api-routes/request-helpers)
- `res`: An instance of [http.ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse), with some [helper functions](https://nextjs.org/docs/api-routes/response-helpers)

Before proceeding, keep these two things in mind:

1. Next.js 13 introduced a new [app directory](https://beta.nextjs.org/docs/routing/fundamentals#the-app-directory) that offers an improved routing system over the traditional `pages` directory. However, *API routes should still be [defined in the pages/api directory](https://beta.nextjs.org/docs/data-fetching/api-routes)*. As this article is being written, the Next.js team hasn't decided yet how API routes will look like in the `app` directory. So this article will use the usual `pages/api` directory structure, but keep in mind it may change in the future.
2. Next.js offers a beta version of [Edge API routes](https://nextjs.org/docs/api-routes/edge-api-routes), which use the [Edge Runtime](https://nextjs.org/docs/api-reference/edge-runtime). These API routes are often faster than their Node.js runtime counterparts but come with limitations such as not having access to native Node.js APIs. This article will not discuss Edge API routes and will only deal with standard API routes.

### Static Routes

A static route is a fixed, predefined route that matches a single path verbatim. Next.js offers two equivalent ways of creating static routes. If you want a static route `/api/foo`, you can do one of the following:

1. Create the file **foo.js** in `pages/api`, or
2. Create the file **index.js** in a directory named `foo` in `pages/api`

Even though both approaches are equivalent, the second approach is much easier to work with if you have nested or dynamic routes under that particular route, as you'll see later.

Let's create two static routes—`/api/users` and `/api/posts`—and see both approaches in action. First, create a `users` directory in `pages/api` and create an **index.js** file in this directory with the following code:

```jsx
import { users } from '../../../data'

export default function handler(req, res) {
  res.status(200).json(users)
}
```

As you can see, the `handler` function returns the list of users with a `200` status. You can test this route by sending a GET request to `localhost:3000/api/users`:

```sh
$ curl <http://localhost:3000/api/users>
[{"id":1,"username":"bob","name":"Bob","location":"USA"},{"id":2,"username":"alice","name":"Alice","location":"Sweden"},{"id":3,"username":"john","name":"John","location":"France"}]

```

You'll take the second approach for the `/api/posts` route. Create the file `posts.js` in `pages/api`:

```jsx
import { posts } from '../../data'

export default function handler(req, res) {
  res.status(200).json(posts)
}
```

Similar to the previous route, this one returns the list of all posts. A similar `GET` request can be used to test this route:

```sh
$ curl <http://localhost:3000/api/posts>
[{"id":1,"userId":1,"text":"Hello, World!"},{"id":2,"userId":2,"text":"Hello, NextJS"},{"id":3,"userId":1,"text":"Lorem ipsum dolor sit amet. "},{"id":4,"userId":3,"text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ut rhoncus neque. Sed lacinia magna a mi tincidunt, ac interdum."}]

```

It's possible to pass query parameters to routes such as `/api/foo?bar=baz`. These query parameters can be accessed in the handler function through the `req.query` object. Let's see this by passing a `limit` query parameter to the `/api/posts` route. Modify `posts.js` with the following code:

```jsx
import { posts } from '../../data'

export default function handler(req, res) {
  const { limit } = req.query
  res.status(200).json(posts.slice(0, limit))
}
```

Now you can pass the `limit` parameter to limit the number of results:

```sh
$ curl "<http://localhost:3000/api/posts?limit=2>"
[{"id":1,"userId":1,"text":"Hello, World!"},{"id":2,"userId":2,"text":"Hello, NextJS"}]

```

### Dynamic Routes

Fixed static routes may not be always enough for complex routing needs. For example, if you have multiple users, it's not convenient to set up individual static routes for each user, such as `/api/users/1`, `/api/users/2`, and so on. To solve this, you need to use dynamic routes, where one or more segments work as parameters that the user can pass.

For example, a route like `/api/users/[id]` can match `/api/users/xxx`, where `xxx` can be any valid URL component. The actual parameter passed through the URL can be accessed by the name assigned in the route (`id` in this example), and the appropriate record can be fetched from the database.

To create a dynamic segment, you need to add square brackets (`[ ]`) around the name of the file. For example, **pages/api/users/\[id].js** will be mapped to the route `/api/users/[id]`. Just like in the case of static routes, you can also create a directory named `[id]` and create **index.js** inside it. Both approaches are precisely equivalent. The parameter `id` can be accessed in the handler function through the `req.query` object:

```jsx
const { id } = req.query
```

It's possible to have multiple dynamic segments by using a nested directory structure. For example, `pages/api/users/[id]/[postId].js` will be mapped to `/api/users/[id]/[postId]`, and both id and postId can be accessed via `req.query`:

```json
{ "id": "1", "param": "foo" }
```

Remember that a route parameter will override a query parameter with the same name. So in the route `/api/users/1?id=foo`, `req.query.id` will be `1` and not `foo`.

Create a directory `[id]` in `pages/api/users` and create `index.js` inside it, which will map to the `/api/users/[id]` route. Write the following code in `index.js`:

```jsx
import { users } from '../../../../data'

export default function handler(req, res) {
  const { id } = req.query
  const user = users.find((user) => {
    return user.id == id
  })
  if (typeof user !== 'undefined') return res.status(200).json(user)
  res.status(404).json({ error: 'Not found' })
}
```

This function finds the appropriate user from the array and returns it. If no user with the specified ID is found, a "Not found" error is returned instead. Test the route with the following request:

```sh
$ curl <http://localhost:3000/api/users/3>
{"id":3,"username":"john","name":"John","location":"France"}

```

### Nested Routes

It's possible to create nested routes in Next.js by simply nesting directories. A directory structure like `pages/api/foo/bar.js` or `pages/api/foo/bar/index.js` will be mapped to `/api/foo/bar`. Let's create a `posts` route under `/api/users/[id]`, which will return all posts by the specified user.

Create the file `posts.js` in `pages/api/users/[id]` with the following code:

```jsx
import { users, posts } from '../../../../data'

export default function handler(req, res) {
  const { id } = req.query
  const user = users.find((user) => {
    return user.id == id
  })
  if (typeof user === 'undefined') return res.status(404).json({ error: 'Not found' })

  const userPosts = posts.filter((post) => {
    return post.userId == id
  })

  res.status(200).json(userPosts)
}
```

This function first finds the appropriate user and then filters the posts array to find posts with the particular `userId`. Test that it works correctly:

```sh
$ curl <http://localhost:3000/api/users/1/posts>
[{"id":1,"userId":1,"text":"Hello, World!"},{"id":3,"userId":1,"text":"Lorem ipsum dolor sit amet. "}]
```

### Catch-All Routes

Catch-all routes are similar to dynamic routes, but whereas in a dynamic route, the dynamic segment matches only that particular part of the route, in a catch-all route, it matches all paths under that route. This can be created by adding three dots (`...`) inside the square brackets. So, a route like `/api/foo/[...bar]` will match `/api/foo/a`, `/api/foo/a/b`, `/api/foo/a/b/c`, and so on. However, it won't match `/api/foo`—i. e. , the path parameter cannot be omitted.

If you'd like the path parameter to be optional, you can convert it to an optional catch-all route by using two square brackets (`[[ ]]`). So, `/api/foo/[[...bar]]` matches `/api/foo/a`, `/api/foo/a/b`, `/api/foo/a/b/c`, and so on, as well as `/api/foo`. The path parameters can be accessed through `req.query` as before, but in this case, it will be an array of one or more elements if parameters are passed or an empty object if the parameter is omitted.

Let's create an optional catch-all route `/api/comments/[[...ids]]`, which will do the following:

- Return all comments if no parameter is passed
- Return all comments under post `xx` for a route like `/api/comments/xx`
- Return all comments by user `yy` under post `xx` for a route like `/api/comments/xx/yy`

Create the directory `comments` in `pages/api` and create the file **\[\[...ids]].js** inside:

```jsx
import { users, posts, comments } from '../../../data'

export default function handler(req, res) {
  const { ids } = req.query
  if (Array.isArray(ids)) {
    if (ids.length > 2) {
      return res.status(400).json({ error: 'There cannot be more than two parameters ' })
    }
    if (ids.length === 1) {
      const postId = ids[0]
      const postComments = comments.filter((comment) => {
        return comment.postId == postId
      })
      return res.status(200).json(postComments)
    }
    if (ids.length === 2) {
      const [postId, userId] = ids
      const postUserComments = comments.filter((comment) => {
        return comment.postId == postId && comment.userId == userId
      })
      return res.status(200).json(postUserComments)
    }
  }
  return res.status(200).json(comments)
}
```

You can test this route with zero or more parameters:

```sh
$ curl <http://localhost:3000/api/comments> # Returns all comments
[{"id":1,"postId":1,"userId":2,"text":"Hi there!"},{"id":2,"postId":1,"userId":3,"text":"Lorem ipsum"},{"id":3,"postId":2,"userId":1,"text":"Nulla bibendum risus sed vestibulum lobortis. Fusce."},{"id":4,"postId":2,"userId":1,"text":"In ut nulla vitae dolor scelerisque lacinia. "},{"id":5,"postId":2,"userId":1,"text":"Praesent semper enim eu ligula rutrum finibus."}]

$ curl <http://localhost:3000/api/comments/1> # All comments of post 1
[{"id":1,"postId":1,"userId":2,"text":"Hi there!"},{"id":2,"postId":1,"userId":3,"text":"Lorem ipsum"}]

$ curl <http://localhost:3000/api/comments/1/2> # All comments of post 1 and user 2
[{"id":1,"postId":1,"userId":2,"text":"Hi there!"}]

```

## Adding JWT Authentication

If you're working on a project where your API routes should be kept private, you'll need to protect them from unauthorized access. [JWT authentication](https://jwt.io/introduction) is one of the most commonly used authentication mechanisms for securing APIs. You'll now add JWT authentication to the `/api/users` route so that the users need to log in before accessing that route.

First, stop the server if it's running. Install the required dependencies with `yarn add bcryptjs jsonwebtoken`. The `bcrypt` library is used to hash and compare the passwords, and the `jsonwebtoken` library is used to create and verify the JWT. Create an ENV file with the following content:

```sh
JWT_SECRET_KEY = mysecret
```

This key will be used to sign the JWT, so in an actual application, this should be a random string and kept secret.

Next, open `data.js` and add a `password` key to all the users. For simplicity, add the same password to all the users:

```
password: '$2y$10$mj1OMFvVmGAR4gEEXZGtA.R5wYWBZTis72hSXzpxEs.QoXT3ifKSq' // Add this key to all users
```

The value in quotes is the hashed version of the string "password".

Next, create `auth.js` inside `pages/api`. This file will log the user in and generate the token. Start with the necessary imports:

```jsx
import { users } from '../../data'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'

const JWT_KEY = process.env.JWT_SECRET_KEY
```

Ensure that only the `POST` method is allowed:

```jsx
// ...
export default async function handler(req, res) {
  if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })
}
```

The next step is to extract the username and password from the body and ensure that a user with the username exists:

```jsx
const { username, password } = req.body

if (!username || !password)
  return res.status(400).json({ error: 'Username and password are required' })

const user = users.find((user) => {
  return user.username === username
})

if (!user) return res.status(404).json({ error: 'User not found ' })
```

Then, use `bcrypt` to compare the password in the request with the actual password:

```jsx
const { password: userPassword, id, location, name } = user
const match = await bcrypt.compare(password, userPassword)
if (!match) return res.status(401).json({ error: 'Wrong password' })
```

If the passwords are a match, sign and send the JWT:

```jsx
const payload = { userId: id, location, name }

jwt.sign(payload, JWT_KEY, { expiresIn: 24 * 3600 }, (err, token) => {
  res.status(200).json({ token })
})
```

The entire file should look like this:

```jsx
import { users } from '../../data'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'

const JWT_KEY = process.env.JWT_SECRET_KEY

export default async function handler(req, res) {
  if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })

  const { username, password } = req.body
  if (!username || !password)
    return res.status(400).json({ error: 'Username and password are required' })

  const user = users.find((user) => {
    return user.username === username
  })

  if (!user) return res.status(404).json({ error: 'User not found ' })

  const { password: userPassword, id, location, name } = user
  const match = await bcrypt.compare(password, userPassword)
  if (!match) return res.status(401).json({ error: 'Wrong password' })

  const payload = { userId: id, location, name }
  jwt.sign(payload, JWT_KEY, { expiresIn: 24 * 3600 }, (err, token) => {
    res.status(200).json({ token })
  })
}
```

Let's test this route. Start the server with yarn dev and send a request to `localhost:3000/api/auth`:

```sh
$ curl -X POST "<http://localhost:3000/api/auth>" -d '{"username": "bob", "password": "password"}' -H 'Content-Type: application/json'
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImxvY2F0aW9uIjoiVVNBIiwibmFtZSI6IkJvYiIsImlhdCI6MTY2OTEwMDI3OCwiZXhwIjoxNjY5MTg2Njc4fQ.0EFxEtqR2-rZij-PqD66bWatC_kiMl6QDpNlaqyjaLQ"}

```

Note that you'll likely get a different token.

You can now use this token to check the authenticity of the user. Let's protect the `/api/users` route with JWT. Replace the content in **pages/api/users/index.js** with the following:

```jsx
import { users } from '../../../data'
import jwt from 'jsonwebtoken'

const JWT_KEY = process.env.JWT_SECRET_KEY

export default function handler(req, res) {
  const { authorization } = req.headers

  if (!authorization) return res.status(401).json({ error: 'The authorization header is required' })
  const token = authorization.split(' ')[1]

  jwt.verify(token, JWT_KEY, (err, payload) => {
    if (err) return res.status(401).json({ error: 'Unauthorized' })
    return res.status(200).json(
      users.map((user) => {
        return { ...user, password: '' }
      }),
    )
  })
}
```

The above code checks the `Authorization` header for the JWT. If a token is passed, the `jwt.verify` function is invoked to check the token's authenticity. Once authenticated, the data is returned (with the password field stripped from the users—you wouldn't want to expose the passwords, would you?).

Test this route by passing the `Authorization` header to the request:

```sh
$ curl <http://localhost:3000/api/users> -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImxvY2F0aW9uIjoiVVNBIiwibmFtZSI6IkJvYiIsImlhdCI6MTY2OTEwMDI3OCwiZXhwIjoxNjY5MTg2Njc4fQ.0EFxEtqR2-rZij-PqD66bWatC_kiMl6QDpNlaqyjaLQ" # Replace with your token
[{"id":1,"username":"bob","name":"Bob","location":"USA","password":""},{"id":2,"username":"alice","name":"Alice","location":"Sweden","password":""},{"id":3,"username":"john","name":"John","location":"France","password":""}]

```

An invalid token will raise the following error:

```sh
$ curl <http://localhost:3000/api/users> -H "Authorization: Bearer: invalid"
{"error":"Unauthorized"}
```

As you can see, adding JWT authentication to API routes is an involved process that can be complicated. Using something like Clerk’s [Next.js authentication solution](/nextjs-authentication) makes the process much easier since it does the heavy lifting of authentication, taking the task off your plate.

With Clerk, authentication is as simple as importing the `getAuth` function:

```jsx
import { getAuth } from '@clerk/nextjs/server'
```

Calling it inside the handler function is also easy, which will automatically authenticate the user and return the user ID:

```jsx
const { userId } = getAuth(req)
```

You'll learn more about authentication with Clerk in part two of this series.

## Conclusion

Next.js API routes offer extreme flexibility in keeping your server-side logic close to the frontend and creating an API application. With the many different types of API routes available, it's critical to implement proper authentication to protect the routes from bad actors. However, adding authentication can be a complex and daunting task. This is why solutions like [Clerk](/) exist to make it as easy and seamless as possible.

---

# Clerk and Create T3 Turbo
URL: https://clerk.com/blog/clerk-t3-turbo.md
Date: 2022-12-28
Category: Guides
Description: This guide shows you how to integrate Clerk into T3-Turbo so you can have user management for everyone.

T3-Turbo is one of the easiest ways to get both Type safety while using Next.js and Expo. The biggest missing feature is the ability to share authentication between your applications.

This guide shows you how to integrate Clerk into T3-Turbo so you can have user management for everyone.

> For comprehensive Expo authentication without the T3 stack, [learn more about our Expo support](/expo-authentication).

If you don’t want to do this manually, use the [starter repo](https://github.com/clerkinc/t3-turbo-and-clerk). It is
open source and free.

## Assumptions

There are a few assumptions here when working through this guide.

- You understand TRPC and its functionality.
- You are familiar with Expo.
- You have a working knowledge of Turborepo

## Setup

### Create your free Clerk account

You need a free Clerk account to use everything in this guide, so head to [https://dashboard.clerk.com](https://dashboard.clerk.com) and sign up for your free account.

### Create a new application in the dashboard

You will need to create a new application, name it and select Discord as a social sign-in.

If you change any setting here, you may need to update your Expo code to handle any requirements you change.

![Clerk T3 Turbo guide illustration](./033608f71ab9631e79b9c3569e92bb808e6dc213-3918x1924.png)

###

![Clerk T3 Turbo guide illustration](./c00fd14484c9b3f888f03d00f543923351f66a34-3920x2244.png)

### Update .env to use your keys

Under the dashboard, you will need your API keys and create a copy of the `.env.example` as `.env`

![Clerk T3 Turbo guide illustration](./f244212d6116858dbef13ee31ecf14af91fd759e-3914x2182.png)

## Adding global env to Turbo

We want to have our env available in many parts of our application. You can add the following to our `turbo.json` .

```json {{ prettier: false }}
"globalEnv": [
  "DATABASE_URL",
  "NEXT_PUBLIC_CLERK_FRONTEND_API",
  "CLERK_API_KEY",
  "CLERK_JWT_KEY"
]
```

###

Update Next.js package.json

We need to be able to access the .env when working in development, so replace the dev script with the following:

```json {{ prettier: false }}
"with-env": "dotenv -e ../../.env --",
"dev": "pnpm with-env next dev",
```

##

## Updating our Next.js application

First, we will work on our Next.js application, whose only change is [adding Clerk](/nextjs-authentication), so we have powerful user authentication.

### Install

```bash
pnpm install @clerk/nextjs --filter @acme/nextjs
```

Now that the Clerk package has been installed in our Next.js application, we need to wrap our application in the `<ClerkProvider>`, which gives us access to the authentication state throughout our application.

Open up your `_app.tsx` file and modify the code.

```tsx
import '../styles/globals.css'
import type { AppType } from 'next/app'
import { ClerkProvider } from '@clerk/nextjs'
import { trpc } from '../utils/trpc'

const MyApp: AppType = ({ Component, pageProps: { ...pageProps } }) => {
  return (
    <ClerkProvider {...pageProps}>
      <Component {...pageProps} />
    </ClerkProvider>
  )
}

export default trpc.withTRPC(MyApp)
```

## Add Middleware.ts

Clerk uses Next.js middleware to allow your application to keep track of authentication behind the scenes.

```tsx
import { withClerkMiddleware } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export default withClerkMiddleware((_req: NextRequest) => {
  return NextResponse.next()
})

// Stop Middleware running on static files
export const config = {
  matcher: [
    /*
     * Match request paths except for the ones starting with:
     * - _next
     * - static (static files)
     * - favicon.ico (favicon file)
     *
     * This includes images, and requests from TRPC.
     */
    '/(.*?trpc.*?|(?!static|.*\\..*|_next|favicon.ico).*)',
  ],
}
```

You will notice the matcher at the bottom, which ensures that middleware doesn’t run on every request. This will scope it to TRPC + API routes leaving your images and static files alone.

## Embedding our UI components

Clerk provides highly customizable components from Sign-up to Organization management. They require zero form creation or state management, making them easy to implement. Each component will use the [Next.js optional catch all route](https://nextjs.org/docs/routing/dynamic-routes#optional-catch-all-routes). This allows you to redirect the user inside your application using OAuth providers.

### Sign in

```jsx
import { SignIn } from '@clerk/nextjs'

const SignInPage = () => (
  <main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
    <div className="flex flex-col items-center justify-center gap-4">
      <div className="container flex flex-col items-center justify-center gap-12 px-4 py-8">
        <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">Sign In</h1>
        <SignIn path="/sign-in" routing="path" signUpUrl="/sign-up" />
      </div>
    </div>
  </main>
)

export default SignInPage
```

### Sign up

```jsx
import { SignUp } from '@clerk/nextjs'

const SignUpPage = () => (
  <main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
    <div className="flex flex-col items-center justify-center gap-4">
      <div className="container flex flex-col items-center justify-center gap-12 px-4 py-8">
        <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">Sign In</h1>
        <SignUp path="/sign-up" routing="path" signInUrl="/sign-in" />
      </div>
    </div>
  </main>
)

export default SignUpPage
```

### Updating index.tsx

The final step for Next.js is to update our `index.tsx` to use Clerk. Once we update this page, users will have a way to sign in, sign out and see data from TRPC in the future.

We need to import a prebuilt component from Clerk and a hook that allow us to access the current auth state.

`import { useAuth, UserButton } from "@clerk/nextjs";`

### What is useAuth?

The `useAuth` hook is a convenient way to access the current auth state. This hook provides the minimal information needed for data-loading, such as the user id and helper methods to manage the current active session.

### What is UserButton?

Initially popularized by Google, users have come to expect that little photo of themselves in the top-right of the page – it’s the access point to manage their account, switch accounts, or sign out.

The `<UserButton/>` component renders this familiar user button UI. It renders a clickable user avatar - when clicked, the full UI opens as a popup. Here is an example

![Clerk T3 Turbo guide illustration](./12da04075590eb1282144bf1b8ede1a59a634988-942x1052.png)

### Updating AuthShowcase

The `AuthShowCase` component in the `index.tsx` file needs to be updated to use the `useAuth()` hook, allow the user to sign in, and show our UserButton if the user is signed in.

```tsx {{ prettier: false }}
const AuthShowcase: React.FC = () => {
  const { isSignedIn } = useAuth()
```

Now we can update our secret message from `{ enabled: !!session?.user }` to `{ enabled: isSignedIn }`

```tsx {{ prettier: false }}
const AuthShowcase: React.FC = () => {
  const { isSignedIn } = useAuth()
  const { data: secretMessage } = trpc.auth.getSecretMessage.useQuery(
    undefined,
    { enabled: isSignedIn },
  )
```

Now the final change is to use `isSignedIn` in our return statement to conditionally show the secret message and UserButton component or show a sign-in link. We can do that by replacing `{session?.user && (` with `isSignedIn` and underneath, providing the false statement using `!isSignedIn` this is where we can place a Link to our mounted `/sign-in page`.

```jsx
{
  isSignedIn && (
    <>
      <p className="text-center text-2xl text-white">
        {secretMessage && (
          <span>
            {' '}
            {secretMessage} click the user button!
            <br />
          </span>
        )}
      </p>
      <div className="flex items-center justify-center">
        <UserButton
          appearance={{
            elements: {
              userButtonAvatarBox: {
                width: '3rem',
                height: '3rem',
              },
            },
          }}
        />
      </div>
    </>
  )
}
```

The `UserButton` component allows users to manage their accounts, including signing out or updating their profile and password or linking a new account through OAuth providers. I added some customization to make the UserButton larger.

To learn more about customization, go to our documentation where we explain how to use the [appearance
prop](/docs/component-customization/appearance-prop)

The final step is to add a login text that pushes the user to the mounted sign-in page.

```jsx
{
  !isSignedIn && (
    <p className="text-center text-2xl text-white">
      <Link href="/sign-in">Sign In</Link>
    </p>
  )
}
```

Below is the final AuthShowcase.

```tsx
const AuthShowcase: React.FC = () => {
  const { isSignedIn } = useAuth()
  const { data: secretMessage } = trpc.auth.getSecretMessage.useQuery(undefined, {
    enabled: !!isSignedIn,
  })

  return (
    <div className="flex flex-col items-center justify-center gap-4">
      {isSignedIn && (
        <>
          <p className="text-center text-2xl text-white">
            {secretMessage && (
              <span>
                {' '}
                {secretMessage} click the user button!
                <br />
              </span>
            )}
          </p>
          <div className="flex items-center justify-center">
            <UserButton
              appearance={{
                elements: {
                  userButtonAvatarBox: {
                    width: '3rem',
                    height: '3rem',
                  },
                },
              }}
            />
          </div>
        </>
      )}
      {!isSignedIn && (
        <p className="text-center text-2xl text-white">
          <Link href="/sign-in">Sign In</Link>
        </p>
      )}
    </div>
  )
}
```

Now that the Next.js work is done, we should update our TRPC API to use Clerk instead of NextAuth, so we can test this work and get ready to update Expo.

## Updating API package to use Clerk

Currently, the API package has TRPC context, and middleware uses Auth.js (previously NextAuth). We can replace this with Clerk so we can use it both with Expo and Next.js.

You can delete the Auth package in the packages folder completely and update the Prisma schema to remove the user
data. None of this is needed to use Clerk makes sure you remove any references if you do this

### Updating TRPC context

The context is found at `packages/api/src/context.ts`. In this package, we will add the ability to detect the user being signed in and retrieve the full User object. First, we must remove the auth package import and add `getAuth` , `clerkClient`, `SignedInAuthObject` and `SignedOutAuthObject` as a type.

```tsx {{ del: [1], ins: [2, 3] }}
import { getServerSession, type Session } from '@acme/auth'
import { getAuth } from '@clerk/nextjs/server'
import type { SignedInAuthObject, SignedOutAuthObject } from '@clerk/nextjs/api'
```

### What is `getAuth` ?

The `getAuth()` helper retrieves the authentication state and can be used anywhere within a next.js server. It provides information needed for data-loading, such as the user id and can be used to protect your API routes.

### Updating `createContext` function

For the `createContext` function, we want to pass around the user object anywhere in our application. For this, we can create an async function called `getUser` that retrieves the `userId` and subsequently retrieves the user data.

```tsx
export const createContext = async (opts: CreateNextContextOptions) => {
  return await createContextInner({ auth: getAuth(opts.req) })
}
```

Now we can retrieve a user, and if not, we will return `null` we can pass this to our `createContextInner` in case you need it for testing without a request object.

```tsx
type AuthContextProps = {
  auth: SignedInAuthObject | SignedOutAuthObject
}
/** Use this helper for:
 *  - testing, where we dont have to Mock Next.js' req/res
 *  - trpc's `createSSGHelpers` where we don't have req/res
 * @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
 */
export const createContextInner = async ({ auth }: AuthContextProps) => {
  return {
    auth,
    prisma,
  }
}
```

## Updating TRPC middleware

The TRPC middleware found in `/packages/api/src/trpc.ts` needs a small update to the `isAuthed` function. The if statement becomes `!ctx.auth.userId`, and the return becomes `auth: ctx.auth`

```tsx
import { initTRPC, TRPCError } from '@trpc/server'
import { type Context } from './context'
import superjson from 'superjson'

const t = initTRPC.context<Context>().create({
  transformer: superjson,
  errorFormatter({ shape }) {
    return shape
  },
})

const isAuthed = t.middleware(({ next, ctx }) => {
  if (!ctx.auth.userId) {
    throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Not authenticated' })
  }
  return next({
    ctx: {
      auth: ctx.auth,
    },
  })
})

export const router = t.router
export const publicProcedure = t.procedure
export const protectedProcedure = t.procedure.use(isAuthed)
```

Our Next.js application can be tested with TRPC, including the secret message that uses protected routes. Give it a test.

## Updating our Expo application

The Expo application currently doesn’t support authentication; the good news is Clerk supports Expo with our `@clerk/expo` package.

### Install `@clerk/expo` package and secure-store

`pnpm install @clerk/clerk-expo expo-secure-store --filter @acme/expo`

### Create a Token Cache

We need a token cache here, which is why we installed `expo-secure-store` that allows you to store key pair values on the device. Create a new file under `/src/utils/` named `cache.ts` and paste in the following code:

```tsx
import * as SecureStore from 'expo-secure-store'
import { Platform } from 'react-native'

export async function saveToken(key: string, value: string) {
  // console.log("Save token", key, value);
  await SecureStore.setItemAsync(key, value)
}

export async function getToken(key: string) {
  const value = await SecureStore.getItemAsync(key)
  return value
}

// SecureStore is not supported on the web
// https://github.com/expo/expo/issues/7744#issuecomment-611093485
export const tokenCache =
  Platform.OS !== 'web'
    ? {
        getToken,
        saveToken,
      }
    : undefined
```

I won’t explain this code above as it’s an expo-specific package, but this allows us to store the JWT securely and not in memory.

### Add `<ClerkProvider>`

Similar to our Next.js application, we need to wrap up our `_app.tsx` in the `<ClerkProvider>` to allow access to auth state anywhere in the application. What is different here is we need use our newly created `TokenCache`, and we need to provide the Clerk frontend API directly to the `<ClerkProvider />`

```jsx
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { TRPCProvider } from './utils/trpc'

import { HomeScreen } from './screens/home'
import { ClerkProvider } from '@clerk/clerk-expo'
import { tokenCache } from './utils/cache'

// Find this in your Dashboard.
const clerk_frontend_api = 'FRONT_END_API'

export const App = () => {
  return (
    <ClerkProvider frontendApi={clerk_frontend_api} tokenCache={tokenCache}>
      <TRPCProvider>
        <SafeAreaProvider>
          <HomeScreen />
          <StatusBar />
        </SafeAreaProvider>
      </TRPCProvider>
    </ClerkProvider>
  )
}
```

### Protecting pages

Our Expo package provides an easy way to gate content using `SignedIn` and `SignedOut`, which will gate the content depending on the user's current state.

```jsx
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { TRPCProvider } from './utils/trpc'

import { HomeScreen } from './screens/home'
import { ClerkProvider, SignedIn, SignedOut } from '@clerk/clerk-expo'
import { tokenCache } from './utils/cache'

// Find this in your Dashboard.
const clerk_frontend_api = 'FRONT_END_API'

export const App = () => {
  return (
    <ClerkProvider frontendApi={clerk_frontend_api} tokenCache={tokenCache}>
      <SignedIn>
        <TRPCProvider>
          <SafeAreaProvider>
            <HomeScreen />
            <StatusBar />
          </SafeAreaProvider>
        </TRPCProvider>
      </SignedIn>
      <SignedOut></SignedOut>
    </ClerkProvider>
  )
}
```

## Implementing a way to sign in.

With Clerk Expo, you must implement your pages to sign in or sign up as a user. We will use Discord, but you can use any social or standard sign-in you want. First, we need to install `expo-auth-session` to handle sessions.

`pnpm install expo-auth-sessions --filter @acme/expo`

### Creating a Sign In component

Create a folder called `components` and then create a file called `SignInWithOAuth.tsx`. This will be our component that you can easily extend to use more providers or swap out Discord for something else.

```jsx
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'
import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()
}
```

Here we are using another helper, which allows you to sign in as a user and set the session after the fact. We need to make sure Clerk is fully loaded before we attempt a sign in so we can use the `isLoaded` as part of the `useSignIn` helper.

```jsx
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null
}
```

Now we need to create our function that will run when a user taps the button to sign in:

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
```

Next we need to tell where to redirect to after a successful or unsuccessful login attempt via Discord,`expo-auth-session` provides a helper to make a redirect, which is called `makeRedirectUri`, and set it to `/oauth-native-callback`

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })
```

At this point, we can start our sign in attempt using `signIn.create` passing in our strategy, which is `oauth_discord`, and our newly created `redirectUrl`

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })
```

The `SignIn` object holds all the state of the current sign in and provides helper methods to navigate and complete the sign in process. You can read about this in our [documentation](/docs/reference/clerkjs/signin), as you may want to use the different sign in methods in the future.

The next part of the sign in is to retrieve the external redirect URL and use AuthSession. This will give us the ability to know if the OAuth was successful or not.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL?.toString() || '',
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }
```

You may notice that we have an eslint to disable the checks on the next line. There is an assumption in this example that it will always be successful, but you can use the following [AuthSession](https://docs.expo.dev/versions/latest/sdk/auth-session/#returns-7) documentation to implement anything you may want to handle.

We now need to retrieve `rotatingTokenNonce` and reload our `signIn` object. This will allow us to get the `sessionId` and sign the user in.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL.toString(),
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      console.log
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })
```

Finally we can retrieve the `createdSessionId` from the `signIn` object and set that to our current session. This will let us know that the user is signed in with a valid session.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL?.toString() || '',
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })

      const { createdSessionId } = signIn

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign in OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)
      return
    }
```

Finally we can add a catch for anything that might go wrong that we aren’t handling and return the error.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL?.toString() || '',
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })

      const { createdSessionId } = signIn

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign in OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)
      return
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing in', err)
    }
  }
```

Our sign in method is now complete, so we can create a simple UI that, on touch, will attempt a sign in.

```jsx
return (
  <View className="rounded-lg border-2 border-gray-500 p-4">
    <Button title="Sign in with Discord" onPress={handleSignInWithDiscordPress} />
  </View>
)
```

Our Sign In component is now complete below is the full code. We will use this for a Sign Up component for anyone who doesn’t have an account yet for our application.

```jsx
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL.toString(),
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      console.log
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })

      const { createdSessionId } = signIn

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign in OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)

      return
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing in', err)
    }
  }

  return (
    <View className="rounded-lg border-2 border-gray-500 p-4">
      <Button title="Sign in with Discord" onPress={handleSignInWithDiscordPress} />
    </View>
  )
}

export default SignInWithOAuth
```

## Create a Sign Up component

The good news is that the sign in component and the sign up component is very similar and 99% of the code we created can be reused and swapped for `useSignUp` hook. To save you from reading more content, here is the code.

```tsx
import { useSignUp } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignUpWithOAuth = () => {
  const { isLoaded, signUp, setSession } = useSignUp()

  if (!isLoaded) return null

  const handleSignUpWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signUp.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        verifications: {
          externalAccount: { externalVerificationRedirectURL },
        },
      } = signUp

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL!.toString(),
        returnUrl: redirectUrl,
      })
      console.log(result)
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      console.log
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signUp.reload({ rotatingTokenNonce })
      const { createdSessionId } = signUp

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign up OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)

      return
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing up', err)
    }
  }

  return (
    <View className="my-8 rounded-lg border-2 border-gray-500 p-4">
      <Button title="Sign Up with Discord" onPress={handleSignUpWithDiscordPress} />
    </View>
  )
}

export default SignUpWithOAuth
```

### Creating a Sign in, Sign Up screen

We now need to use our components in our application. Under the screens folder, create a new file called `signInSignUp.tsx` and paste the following code. We are displaying the components we created so the code below is generic React Native code.

```jsx
import React from 'react'

import { View, SafeAreaView } from 'react-native'

import SignInWithOAuth from '../components/SignInWithOAuth'
import SignUpWithOAuth from '../components/SignUpWithOAuth'

export const SignInSignUpScreen = () => {
  return (
    <SafeAreaView className="bg-[#2e026d] bg-gradient-to-b from-[#2e026d] to-[#15162c]">
      <View className="h-full w-full p-4">
        <SignUpWithOAuth />
        <SignInWithOAuth />
      </View>
    </SafeAreaView>
  )
}
```

### Updating \_app.tsx

We can now update our `SignedOut` control component to use the `SignInSignUpScreen` so if a user doesn’t have a valid session and is not signed in, they will be able to sign in.

```jsx
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { TRPCProvider } from './utils/trpc'

import { HomeScreen } from './screens/home'
import { SignInSignUpScreen } from './screens/signInSignUp'
import { ClerkProvider, SignedIn, SignedOut } from '@clerk/clerk-expo'
import { tokenCache } from './utils/cache'

// Find this in your Dashboard.
const clerk_frontend_api = 'YOUR_API_KEY'

export const App = () => {
  return (
    <ClerkProvider frontendApi={clerk_frontend_api} tokenCache={tokenCache}>
      <SignedIn>
        <TRPCProvider>
          <SafeAreaProvider>
            <HomeScreen />
            <StatusBar />
          </SafeAreaProvider>
        </TRPCProvider>
      </SignedIn>
      <SignedOut>
        <SignInSignUpScreen />
      </SignedOut>
    </ClerkProvider>
  )
}
```

### Updating TRPC client

The TRPC client found under `utils/trpc` needs a very small update. As part of TRPC, you can provide headers as part of `httpBatchLink` . We can get the JWT token by using `getToken`, which is part of the `useAuth` hook.

First, add the import `import { useAuth } from "@clerk/clerk-expo";` , then, inside our TRPCProvider, add the `getToken` code before the client.

```tsx {{ prettier: false }}
export const TRPCProvider: React.FC<{
  children: React.ReactNode
}> = ({ children }) => {
  const { getToken } = useAuth()
  const [queryClient] = React.useState(() => new QueryClient())
......

```

Then finally, add the Authorization header to our `httpBatchLink`

```jsx {{ prettier: false }}
async headers() {
  const authToken = await getToken()
  return {
    Authorization: authToken,
  }
},
```

This will allow you to send a valid token with your requests to the TRPC backend. Below is the full code:

```tsx
import { createTRPCReact } from '@trpc/react-query'
import type { AppRouter } from '@acme/api'
/**
 * Extend this function when going to production by
 * setting the baseUrl to your production API URL.
 */
import Constants from 'expo-constants'
/**
 * A wrapper for your app that provides the TRPC context.
 * Use only in _app.tsx
 */
import React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { httpBatchLink } from '@trpc/client'
import { transformer } from '@acme/api/transformer'
import { useAuth } from '@clerk/clerk-expo'

/**
 * A set of typesafe hooks for consuming your API.
 */
export const trpc = createTRPCReact<AppRouter>()

const getBaseUrl = () => {
  /**
   * Gets the IP address of your host-machine. If it cannot automatically find it,
   * you'll have to manually set it. NOTE: Port 3000 should work for most but confirm
   * you don't have anything else running on it, or you'd have to change it.
   */
  const localhost = Constants.manifest?.debuggerHost?.split(':')[0]
  if (!localhost) throw new Error('failed to get localhost, configure it manually')
  return `http://${localhost}:3000`
}

export const TRPCProvider: React.FC<{
  children: React.ReactNode
}> = ({ children }) => {
  const { getToken } = useAuth()
  const [queryClient] = React.useState(() => new QueryClient())
  const [trpcClient] = React.useState(() =>
    trpc.createClient({
      transformer,
      links: [
        httpBatchLink({
          async headers() {
            const authToken = await getToken()
            return {
              Authorization: authToken,
            }
          },
          url: `${getBaseUrl()}/api/trpc`,
        }),
      ],
    }),
  )

  return (
    <trpc.Provider client={trpcClient} queryClient={queryClient}>
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    </trpc.Provider>
  )
}
```

Go ahead and test everything. At this point, you have a working application that uses TRPC

## Final Updates to our TRPC API

The final update here is to update the `post` router to use a `protectedProcedure` for creation so that when a user uses the Expo application, they will need to be logged in to create a new post. Open the `post.ts` under `/packages/api/src/router` and update the `create` to use `protectedProcedure` .

```jsx
import { router, publicProcedure, protectedProcedure } from '../trpc'
import { z } from 'zod'

export const postRouter = router({
  all: publicProcedure.query(({ ctx }) => {
    return ctx.prisma.post.findMany()
  }),
  byId: publicProcedure.input(z.string()).query(({ ctx, input }) => {
    return ctx.prisma.post.findFirst({ where: { id: input } })
  }),
  create: protectedProcedure
    .input(z.object({ title: z.string(), content: z.string() }))
    .mutation(({ ctx, input }) => {
      return ctx.prisma.post.create({ data: input })
    }),
})
```

## Next Steps

Now you have a working T3 Turbo application that has authentication both in Next.js and Expo with protected routes. Here are some next steps you might want to implement:

- Additional login methods for Expo ( more social logins or email and password screen)
- Use one of our [integrations](/docs/guides/development/integrations/overview) to use a database, such as Neon, Supabase, or Firebase.
- Join our [Discord](https://clerk.com/discord)

---

# Building a Custom User Profile with Clerk
URL: https://clerk.com/blog/building-custom-user-profile-with-clerk.md
Date: 2022-08-03
Category: Guides
Description: Authentication is one of the most critical functions of securing your applications; however, it's also one of the most challenging functions to implement.

Failing to implement a proper authentication system can make your application vulnerable and your users' information open to potential hackers.

If you don't want to get into the technicalities of implementing an authentication system from scratch, [Clerk](/) is your solution. Clerk provides built-in components for your application that can be easily integrated into your frontend application, and it supports most of the popular frameworks, like [React](https://reactjs.org), [Next.js](https://nextjs.org), and [Gatsby](https://www.gatsbyjs.com).

Clerk can be beneficial for your customer identity management. You can easily manage your user sessions, devices, and profiles from the Clerk dashboard. Moreover, you can easily integrate Clerk with services like [Firebase](https://firebase.google.com) or [Google Analytics](https://marketingplatform.google.com/about/analytics).

In addition, Clerk makes integrating authentication to your existing application simple since it provides built-in hooks for adding authentication. You can implement social sign-in, password-based authentication, or Web3 logins easily using Clerk. You can also extend your functionalities and create custom components and user profiles using their SDK and APIs.

In this article, you'll see how Clerk authentication can be implemented in your Next.js application and how you can implement the Clerk built-in components for user profiles. You'll also learn how to create custom user profiles for your users and update users' profiles using your custom components.

## What Is Clerk?

Clerk is an all-in-one solution for your authentication and user management needs. It provides features like password-based or social sign-in, [passwordless login using magic links](/blog/magic-links) or email, and SMS passcodes. It also provides a user management dashboard, user analytics, allow/block list, rate limiting, and [more](/#home-features).

With Clerk, you can set up a complete [user management system within ten minutes](https://www.youtube.com/watch?v=mywtHZcrYfE\&feature=emb_imp_woyt). Clerk can seamlessly integrate with popular technologies, including React, Next.js, Gatsby, [RedwoodJS](https://redwoodjs.com), [Remix](https://remix.run), [Node.js](https://nodejs.org/en), and [Go](https://go.dev).

For popular frontend frameworks, like React, Remix, RedwoodJS, or Gatsby, Clerk has created well-designed components for login, sign-up, the user profile, and the user button. However, it's not limited to built-in components. You can always create custom components with the help of hooks provided by the Clerk SDK.

Because Clerk provides you with frontend SDK, API, and backend APIs for developing custom pages for your users, building a customer user profile is easy.

## Building a Custom User Profile Using Clerk

This article aims to show how you can create custom user profiles for your Next.js applications and how to implement the built-in components. To do this, you'll use the [Clerk SDK for Next.js](/nextjs-authentication).

The basic flow of the application is shown in the following GIF:

### Prerequisites

Before you build your custom user profiles with Clerk, you need to satisfy a few prerequisites, including the following:

- Create a Clerk [account](https://dashboard.clerk.com/sign-up).
- Have a basic understanding of Next.js. To learn more about Next.js, you can check out their [documentation](https://nextjs.org/docs).
- Have a basic understanding of [Tailwind CSS](https://tailwindcss.com) (optional)

You can create a free account for Clerk from [the Clerk sign-up page](https://dashboard.clerk.com/sign-up). After creating your account, you'll be redirected to the Clerk dashboard. There, you will be asked to create a new application. Add an application with the name of your choice. This is what the setup for this tutorial looks like:

![Clerk app creation page](./VfxvgIu.png)

After successfully creating the application, you'll be able to visit the application's dashboard:

![Clerk application dashboard](./Y2FoQtw.png)

You can find your API keys in the menu under the **Developers** section. Click on **API Keys** and copy the frontend API key. You'll need this later in the project.

In addition to your Clerk account, Node.js and [npm](https://www.npmjs.com) must be installed on your local computer to create and run the application.

If you want to copy the code and follow along, you can use this [GitHub repo](https://github.com/nemo0/nextjs-clerkdev-custom-profile).

### Creating a Next.js Application

The first step in building this application is to create a Next.js application. To scaffold a Next.js application, run the following command in the terminal:

```bash
npx create-next-app@latest
```

Once the installation is complete, you can run the application using `npm run dev` in the terminal, and the application will start on port `3000`. Next.js will render the `index.jsx` file inside the `pages` folder. You can delete the contents of the `index.jsx` file as it will be customized.

The second step is to integrate Tailwind CSS with your Next.js application. You can follow [this Tailwind CSS installation guide](https://tailwindcss.com/docs/guides/nextjs) to do so.

Then install the [Clerk SDK for the Next.js plug-in](/docs/quickstarts/get-started-with-nextjs). To install the SDK, run the following command in the terminal:

```bash
npm install @clerk/nextjs
```

For using forms effortlessly, you can also integrate the [`react-hook-form`](https://react-hook-form.com) plug-in by running the following command:

```bash
npm install react-hook-form
```

Another plug-in called `react-icons` is used for adding icons to the application. You can install `react-icons` by simply running the following command in your terminal:

```bash
npm install react-icons
```

These previous plug-ins are the only ones that will be used in this application.

## Integrating User Profile in Your Next.js App

To add a user profile to your Next.js app using Clerk, you need to obtain the frontend API key, create a new `.env.local` file, and paste the frontend API key to a variable called `NEXT_PUBLIC_CLERK_FRONTEND_API`. The `.env.local` file should look similar to this:

```bash
NEXT_PUBLIC_CLERK_FRONTEND_API=clerk.noice.bjsdn-81.lcl.dev
```

Then you need to wrap your Next.js application with the `ClerkProvider` component. The `ClerkProvider` wrapper can be found in the `@clerk/nextjs` SDK. The SDK also has methods called `SignedIn`, `SignedOut`, and `RedirectToSignIn`. These components can be used to secure your application. For example, the components wrapped inside the `SignedIn` will require the user to sign in. You can read about the different components [in the official docs](/docs/quickstarts/get-started-with-nextjs).

The `_app.js` file for this application should look like this:

```jsx
import '../styles/globals.css'
import { ClerkProvider, SignedIn, SignedOut, RedirectToSignIn } from '@clerk/nextjs'

import { useRouter } from 'next/router'

import Header from '../components/Header'

const publicPages = []

function MyApp({ Component, pageProps }) {
  const { pathname } = useRouter()
  const isPublicPage = publicPages.includes(pathname)

  return (
    <ClerkProvider frontendApi={process.env.NEXT_PUBLIC_CLERK_FRONTEND_API}>
      {isPublicPage ? (
        <Component {...pageProps} />
      ) : (
        <>
          <SignedIn>
            <Header />
            <Component {...pageProps} />
          </SignedIn>
          <SignedOut>
            <RedirectToSignIn />
          </SignedOut>
        </>
      )}
    </ClerkProvider>
  )
}

export default MyApp
```

You must pass the API key in the `ClerkProvider` through the `frontendApi` prop. The `publicPages` array can store the pages that are available to everyone. But for this article, all the pages will be secured.

The `SignedIn` wrapper holds all the components. That means, if you are signed in, you'll only be able to access the pages. You'll be redirected to the sign-in page if you are not signed in. You'll be redirected to the login screen if you are not logged in using the `RedirectToSignIn` component.

### Header and User Profile

The `Header` component is a very basic header. The code for the `Header` component looks like this in the `Header.jsx` file:

```jsx
import { GiAstronautHelmet } from 'react-icons/gi'
import { CgProfile } from 'react-icons/cg'
import { UserButton } from '@clerk/clerk-react'

import Link from 'next/link'

const Header = (props) => {
  return (
    <div className="w-full bg-purple-600 py-4">
      <div className="mx-auto flex w-10/12 items-center justify-between">
        <Link href={'/'}>
          <a>
            <h4 className="flex items-center text-2xl font-bold text-white">
              <GiAstronautHelmet className="mr-4" />
              Clerk is Awesome
            </h4>
          </a>
        </Link>
        <div>
          <UserButton userProfileUrl="/profile" />
        </div>
      </div>
    </div>
  )
}

export default Header
```

You can see that the `Header` component is using a component called `UserButton`. Clerk provides this component, and the button renders a toggle menu for accessing the user profile:

![UserButton demo](./Fn25xiX.png)

The `userProfileUrl` prop holds the location of the **Manage account** page. Here, the location is `/profile`.

Now, create a new page called `profile.jsx` inside the `pages` folder. You only need to render a single component to generate the user profile:

```jsx
import { UserProfile } from '@clerk/nextjs'

const Profile = () => {
  return <UserProfile />
}
export default Profile
```

The `UserProfile` component provided by Clerk does everything for you and generates an aesthetically pleasing user profile.

If you try to visit the `/profile` route now, you'll need to sign in or create a new account. Clerk already handles the authorization for accessing specific pages. After successfully logging in, you'll be able to visit the user profile page:

![Clerk UserProfile component](./pto9t8C.jpg)

You can also update your profile from here, which you'll learn about in the next section.

### Implementing Custom User Profile

To implement a custom user profile, create a new page called `view.jsx` inside your `pages` directory. This page will render a custom user profile. As this article focuses more on the technicalities of implementing a custom user profile, the design and Tailwind classes will not be discussed.

To help the user access the custom user profile, update your `index.jsx` file like this:

```jsx
import Head from 'next/head'
import styles from '../styles/Home.module.css'

import Link from 'next/dist/client/link'

const Home = () => {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <div className="flex h-screen w-full flex-col items-center justify-center">
        <h1 className="text-6xl font-bold text-purple-600">Clerk is Awesome</h1>
        <Link href={'/view'}>
          <a>
            <button className="mt-4 bg-purple-600 px-4 py-2 font-bold text-white transition-all hover:bg-purple-800">
              View Profile
            </button>
          </a>
        </Link>
      </div>
      <div></div>
    </div>
  )
}

export default Home
```

The previous code shows a centered text, "Clerk is Awesome," and a button for accessing the custom user profile with a link of `/view`.

The final design of the custom profile page will look like this:

![Custom user profile screen](./UXNgz7K.png)

You'll have to use the `useUser` hook available in the Clerk SDK to get the necessary information from the backend. The `useUser` hook returns the values of the current user along with other important information, like the user creation date and external connected accounts if two-factor authentication is connected:

![useUser returned data](./S4YNb0g.jpg)

If you look at the returned data closely, you'll find that the data contains an object `unsafeMetadata`. The `unsafeMetadata` object can hold custom values stored for custom user profile information:

![unsafeMetadata object](./g4Ik4K7.png)

For this article, you can see there are two custom fields: `customBio` and `customName`.

Clerk has three types of metadata for storing additional user information: public, private, and unsafe. Both public and private metadata can be updated or added from the backend, and you can access or view only the public metadata from the frontend. The unsafe metadata can be read or written from the frontend:

![Comparison of metadata types](./WyBBEUz.png)

Because of the ability to write from the frontend, this article will use unsafe metadata for custom user information. You can read more about metadata [in Clerk's documentation](/docs/users/metadata).

Look at the `view.jsx` file:

```jsx
import { useUser } from '@clerk/nextjs'

import Image from 'next/image'

import Link from 'next/link'

const ViewProfile = () => {
  const { isLoaded, isSignedIn, user } = useUser()
  if (!isLoaded || !isSignedIn) {
    return null
  }

  console.log(user)

  return (
    <div className="container mx-auto">
      <div className="flex">
        <div className="mx-4">
          <Image
            src={user.profileImageUrl}
            width={'250px'}
            height={'250px'}
            alt={user.fullName}
            className="rounded-lg"
          />
        </div>
        <div className="ml-4">
          <div className="-mx-4 overflow-x-auto px-4 py-4 sm:-mx-8 sm:px-8">
            <div className="inline-block w-full overflow-hidden rounded-lg shadow-md">
              <table className="w-full leading-normal">
                <tbody>
                  {/* Firstname */}
                  <tr>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      First Name
                    </td>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      {user.firstName}
                    </td>
                  </tr>
                  {/* Last Name */}
                  <tr>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      Last Name
                    </td>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      {user.lastName}
                    </td>
                  </tr>
                  {/* Emails */}
                  <tr>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      Emails
                    </td>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      {user.emailAddresses.map((email) => (
                        <div key={email.emailAddress}>{email.emailAddress}, </div>
                      ))}
                    </td>
                  </tr>
                  {/* Unsafe Metadata Example */}
                  <tr>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      Custom Name
                    </td>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      {user.unsafeMetadata.customName}
                    </td>
                  </tr>
                  <tr>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      Custom Bio
                    </td>
                    <td className="whitespace-no-wrap border-b border-gray-200 bg-white px-5 py-5 text-sm text-gray-900">
                      {user.unsafeMetadata.customBio}
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
          <div className="flex justify-center">
            <Link href={'/additional'}>
              <button className="mt-4 bg-purple-600 px-4 py-2 font-bold text-white transition-all hover:bg-purple-800">
                Update Additional Information
              </button>
            </Link>
          </div>
        </div>
      </div>
    </div>
  )
}

export default ViewProfile
```

Don't get overwhelmed. The code can look complicated, but it's not. Now, break down the essential components. Begin by importing the `useUser` hook from the Clerk SDK. Then the `Image` and `Link` components are imported from Next.js.

The `ViewProfile` component renders the user profile. The initial step of using `useUser` is to destructure its essential functions:

```jsx
const { isLoaded, isSignedIn, user } = useUser()
if (!isLoaded || !isSignedIn) {
  return null
}
```

In the previous code, the functions check if the page is not loaded or the user is not signed in. If not, then nothing is rendered. You can console the `user` object here:

```jsx
console.log(user)
```

This will return all the information available to Clerk for the particular user. Now that you have access to the `user` object, you can use it to render the profile values. For example, you can generate the user's profile image by simply accessing the `user.profileImageUrl` key. The first name of the user is stored inside the `user.firstName` key.

The template here only uses these keys: `user.profileImageUrl`, `user.firstName`, `user.lastName`, `user.fullName`, `user.emailAddresses`, and `user.unsafeMetadata`. The custom user profile can be implemented using the `user` object.

### Updating Current User Profile

If you look at the previous code, you'll find that it also contains a link to another page for updating the profile information. Look at how you can edit user information from a custom profile update page.

Create a new page with the name `additional.jsx` file inside the `pages` directory. The `react-hook-form` plug-in will be used here, though it's not necessary for a simple form like this. If your form is large and complex, `react-hook-form` is a great solution. This plug-in makes the binding of the input fields simple. You can look at React Hook Form's "Get Started" [example](https://react-hook-form.com/get-started) to get a basic idea of how it works.

Now take a look at the complete code and then break it into parts:

```jsx
import { useForm } from 'react-hook-form'
import { useUser } from '@clerk/nextjs/dist/client'

import { useRouter } from 'next/router'

const AdditionalUpdate = () => {
  const router = useRouter()

  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm()

  const { isLoaded, isSignedIn, user } = useUser()

  const onSubmit = (data) => {
    try {
      user.update({
        firstName: data.firstName,
        lastName: data.lastName,
        unsafeMetadata: {
          customName: data.customName,
          customBio: data.customBio,
        },
      })

      router.push('/view')
    } catch (error) {
      console.log(error)
    }
  }

  if (!isLoaded || !isSignedIn) {
    return null
  }

  return (
    <div className="mx-10">
      <h1 className="py-4 text-2xl font-bold">Update Additional Information</h1>
      <form onSubmit={handleSubmit(onSubmit)}>
        <div>
          <label className="mb-2 block text-sm font-bold text-gray-700" htmlFor="firstName">
            First Name
          </label>
          <input
            defaultValue={user.firstName}
            {...register('firstName', {
              required: true,
            })}
            className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow focus:outline-none"
          />
          {errors.firstName && <span className="text-sm text-red-600">This field is required</span>}
        </div>
        <div>
          <label className="mb-2 block text-sm font-bold text-gray-700" htmlFor="lastName">
            Last Name
          </label>
          <input
            defaultValue={user.lastName}
            {...register('lastName', {
              required: true,
            })}
            className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow focus:outline-none"
          />
          {errors.lastName && <span className="text-sm text-red-600">This field is required</span>}
        </div>
        <div>
          <label className="mb-2 block text-sm font-bold text-gray-700" htmlFor="customName">
            Custom Name
          </label>
          <input
            defaultValue={user.unsafeMetadata.customName}
            {...register('customName', {
              required: true,
            })}
            className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow focus:outline-none"
          />
          {errors.customName && (
            <span className="text-sm text-red-600">This field is required</span>
          )}
        </div>
        <div className="mt-4">
          <label className="mb-2 block text-sm font-bold text-gray-700" htmlFor="customBio">
            Custom Bio
          </label>
          <textarea
            rows={6}
            defaultValue={user.unsafeMetadata.customBio}
            {...register('customBio', {
              required: true,
            })}
            className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow focus:outline-none"
          ></textarea>
          {errors.customBio && <span className="text-sm text-red-600">This field is required</span>}
        </div>

        <button
          type="submit"
          className="my-4 bg-purple-500 px-8 py-2 text-lg font-semibold text-white transition-all hover:bg-purple-700"
        >
          Update
        </button>
      </form>
    </div>
  )
}

export default AdditionalUpdate
```

The `onSubmit` function is used for saving the updated information to the server. The `user.update` function is used for updating the values. A new object with the updated values is passed into this function:

```jsx
user.update({
  firstName: data.firstName,
  lastName: data.lastName,
  unsafeMetadata: {
    customName: data.customName,
    customBio: data.customBio,
  },
})
```

As you can see from the previous object, the `firstName`, `lastName`, and two custom fields are being updated. The custom fields can be updated by updating the keys inside `unsafeMetadata`.

The `user.update` function is wrapped inside a `try…catch` block. The page will be redirected to the custom user profile if the object is successfully updated.

But how do you render the already existing values of the user? It's implemented using a similar approach to building a custom user profile. The `defaultValue` of the input field is filled with the corresponding `user` object value:

```jsx
<input
  defaultValue={user.firstName}
  {...register('firstName', {
    required: true,
  })}
/>
```

The `register` method is a `react-hook-form` method that registers the input field with the value passed. For example, the previous code registers the value with `firstName`. You can access this value by accessing the `data.firstName` object.

Finally, the complete template is placed inside `form` tags, where the `onSubmit` function looks like this: `onSubmit={handleSubmit(onSubmit)}`. The `handleSubmit` function is a `react-hook-form` function that handles submissions. It takes in another function as a parameter, and the `onSubmit` function is passed here.

The last thing you need to do is add `www.gravatar.com` to your `next.config.js` file. When there is no profile picture set by the user for their profile, a Gravatar is shown. The image component in Next.js requires the hostnames to be added to the `next.config.js`. Your `next.config.js` file should look like this:

```js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  images: {
    domains: ['images.clerk.com', 'www.gravatar.com'],
  },
}

module.exports = nextConfig
```

Your user profile update page is now ready.

You can access and check the page by visiting the localhost URL, `http://localhost:3000/additional`. You can also check this [GitHub repo](https://github.com/nemo0/nextjs-clerkdev-custom-profile) for all the code from this tutorial.

The functionalities discussed earlier can also be implemented using the Clerk frontend API. The frontend API has endpoints like `https://clerk.example.com/v1/me` for updating the user profile from the frontend. You can check the [frontend API documentation](https://clerk.com/docs/reference/frontend-api) to learn more.

## Conclusion

[Clerk](/) is a great solution for quickly integrating authentication and custom user profiles into your application. It provides more than authentication; you can manage users, sessions, APIs, and more right from the Clerk dashboard.

This article aims to show you how custom user profiles can be built using the Next.js Clerk SDK. You also saw how Clerk components could be used for rapid development.

You can get started with Clerk for free for up to 500 monthly active users in your application. To create a Clerk account, [visit their sign-up page](https://dashboard.clerk.com/sign-up).

---

# Build an App with Clerk, Prisma Cloud, and Next.js
URL: https://clerk.com/blog/build-app-with-clerk-prisma-nextjs.md
Date: 2022-07-27
Category: Guides
Description: Clerk is an easy-to-use, customizable, and secure customer identity platform that provides you with multiple authentication strategies for your application. 

This platform helps developers handle user management processes for their applications, allowing them to avoid re-inventing the wheel in user authentication strategies and focus on developing the core of their business.

[Clerk](/) can be used to add customer identity management to your application and handle authentication for your application by adding custom sign-in methods. It can also help users track the devices signed in to their accounts on the user profile page, and provide leaked passwords protection by comparing the password entered by the user with the passwords found in major data breaches, as well as many more [features](/#home-features).

In this article, you will learn how to build an app using Clerk, [Prisma Cloud](https://cloud.prisma.io), and [Next.js](https://nextjs.org). This will be a simple application that helps you understand how to implement authentication in your Next.js application using Clerk. The finished application will only show the data from the database to the authenticated users.

## The Tech Stack

The following technologies will be used to create the app:

- [Next.js](https://nextjs.org) is a framework built on top of [React](https://reactjs.org). Next.js is optimized for developer experience, and provides all the features required to build powerful and highly interactive applications with no configuration required.

- [Clerk](/) is a customer identity platform compatible with popular stacks such as JavaScript, React, Next.js, Ruby, and Firebase. It allows you to implement a strong authentication system in your application by providing pre-built components such as `<SignIn />`, `<SignUp />`, and `<UserProfile />`. Clerk supports multiple authentication strategies, including passwords, [magic links](/blog/magic-links), social logins, Web3, multifactor authentication and email or SMS passcodes, and allows you to easily implement them in your application.

- [Prisma Cloud](https://cloud.prisma.io) is a cloud-based collaborative environment that provides support to developers using [Prisma](https://www.prisma.io), an object-relational mapper (ORM) that helps you model data in a human-readable format. Prisma Cloud provides you with an online data browser that allows you to easily view and edit data collaboratively online. It also offers a query console and ability to integrate with your Prisma databases and schema.

- [Heroku](https://www.heroku.com) is a cloud platform that allows developers to build, run, and operate applications.

- [PostgreSQL](https://www.postgresql.org) is an advanced open source relational database management system.

## Building an App with Clerk, Prisma Cloud, and Next.js

To follow along in building this app, you need to have the following set up:

- A code editor of your choice
- [Node.js](https://nodejs.org/en/download) and [Yarn](https://classic.yarnpkg.com/lang/en/docs/install) installed on your development machine
- A [Clerk](https://dashboard.clerk.com/sign-up) account
- A [Prisma Cloud](https://cloud.prisma.io) account
- A [Heroku](https://signup.heroku.com) account

You can see all the code for this application in one place in this [GitHub repository](https://github.com/kimanikevin254/clerk-next-prismacloud).

### Creating a Next.js Application

The easiest way to create a Next.js application is by using `create-next-app`, which sets up everything for you automatically. To create the application, run the following command in the terminal:

```bash
yarn create next-app clerk-prisma
```

The command above creates a folder with the name `clerk-prisma`. This application will only contain a navigation bar and a content area. Open `pages/index.js` in the project root folder and replace the existing code with the following:

```js
import styles from '../styles/Home.module.css'

export default function Home() {
  return (
    <div className={styles.container}>
      <nav className={styles.nav}>
        <h2>My Tasks</h2>
      </nav>

      <div>
        <p>Sign in to view your tasks!</p>
      </div>
    </div>
  )
}
```

To provide some styling for the application, open `styles/Home.module.css` and replace the existing code with the following:

```css
.container {
  margin: 1rem auto;
  max-width: 760px;
  text-align: center;
}

.nav {
  background: gray;
  padding: 0.2rem;
}
```

Run the following command in the terminal to start a development server:

```bash
yarn dev
```

Open `http://localhost:3000/` in your browser and you should see the following:

![A website created with Next.js](./TGmz18s.jpeg)

### Adding Clerk

To add Clerk for user authentication in the application, open the [Clerk dashboard](https://dashboard.clerk.com) in your browser and create a new application by providing the required details.

![An image showing the creation of a new app on the Clerk dashboard](./bCq95OT.jpeg)

Provide the application name, and accept the default settings, which will allow the user to sign in using their email address and a password or to use their Google account. Click the **FINISH** button and you will be navigated to your application details page.

> Creating a new application in Clerk automatically creates a new development instance optimized for local application development.

#### Adding Sign-Up and Sign-In Functionality to the Application Using Clerk

In this section, you will add sign-up and sign-in forms, and build a page that is only visible to authenticated users.

Run the following command in your terminal to install Clerk's Next.js SDK, which gives you access to prebuilt components, hooks, and other features provided by Clerk:

```bash
yarn add @clerk/nextjs
```

You now need to link your local development with the Clerk instance created when you initialized your new app in Clerk. On your Clerk dashboard [API Keys page](https://dashboard.clerk.com/last-active?path=api-keys), copy the `Frontend API key`, create a `.env.local` file in the project root folder and paste in the key in the file as shown below:

```env
NEXT_PUBLIC_CLERK_FRONTEND_API={your_frontend_api_key}
```

Open the terminal to kill the running application by pressing `CTRL+C` or `CMD+C`, and relaunch the application with the command below to load the environment variables:

```bash
yarn dev
```

To use the Clerk context in the application, the entire application needs to be wrapped in the `<ClerkProvider />` component. To achieve this, open the `pages/_app.js` file and replace the existing content with the following:

```js
import '../styles/globals.css'
import { ClerkProvider } from '@clerk/nextjs'

function MyApp({ Component, pageProps }) {
  return (
    <ClerkProvider {...pageProps}>
      <Component {...pageProps} />
    </ClerkProvider>
  )
}

export default MyApp
```

It's time to add a sign-in button and some content for authenticated users. You'll achieve this with some pre-built components and a hook provided by Clerk. These are:

- `useUser()`: This is a hook used to access the current user and user state—whether they're logged in or not.
- `<SignInButton />`: This will display a sign-in button on the webpage.
- `<SignUpButton />`: This will display a sign-up button on the webpage.
- `<UserButton />`: This component displays a button for the current user to access their profile details.

You can learn more about Clerk's components, hooks, and helper functions in the [official documentation](/docs/component-reference/overview).

Open `pages/index.js` file and replace it with the following code:

```js
import styles from '../styles/Home.module.css'

import { useUser, UserButton, SignInButton, SignUpButton } from '@clerk/nextjs'

export default function Home() {
  const { isSignedIn, isLoading, user } = useUser()
  return (
    <div className={styles.container}>
      <nav className={styles.nav}>
        <h2>My Tasks</h2>
        {isSignedIn ? (
          <UserButton />
        ) : (
          <div>
            <SignInButton />
            <SignUpButton />
          </div>
        )}
      </nav>

      <div>
        {isLoading ? (
          <></>
        ) : (
          <div>
            {isSignedIn ? (
              <div>
                <p>Welcome {user.firstName}!</p>
              </div>
            ) : (
              <p>Sign in to view your tasks!</p>
            )}
          </div>
        )}
      </div>
    </div>
  )
}
```

Once you've implemented the preceding code, there will be a different view for users who are signed in and users who are not.

Signed Out Users:
![The view for users who have not signed in](./sIsmqeu.jpeg)

Signed In Users:
![The view for users who have signed in](./66NjqYF.jpeg)

### Adding Prisma to the Application

To add Prisma to the application, run the following commands in your terminal:

```bash
yarn add -D prisma

yarn add @prisma/client

npx prisma init
```

The first command installs Prisma as a `dev` dependency and gives you access to the Prisma CLI. The second command installs the Prisma client, which is a query builder, and the last command initializes Prisma in your application. Initializing Prisma creates a `prisma` folder with a `schema.prisma` file. It also creates a `.env` file in the project root folder with the `DATABASE_URL` variable.

To connect to Prisma Cloud, open [https://cloud.prisma.io](https://cloud.prisma.io) in your browser and create a new project. On the "Configure project" page, provide a project name, connect your GitHub account and click the **Create a repository** option. Click **Next** and go to the next page.

![The project configuration page](./ayaapkW.jpeg)

On the "Select template" page, select the **Empty** template option and click **Next**.

![The select template page](./klvxVYV.jpeg)

On the "Configure environment" page, click on **Provision a new database**, select **Heroku PostgreSQL** as the database provider, and click **Sign in with Heroku** to connect your Heroku account. After signing with Heroku, provide a name for your application. Click on the **Create project** button.

![The configure environment page](./j8CclCr.jpeg)

On the "Deploy project page", copy the `DATABASE_URL` and `DATABASE_MIGRATE_URL`, and insert them at the appropriate points in your local `.env` file, then click **DONE**.

![The deploy project page](./8tTSAON.jpeg)

Your local `.env` file should now have the following:

```bash
DATABASE_URL={YOUR_DATABASE_URL_VALUE}

MIGRATE_DATABASE_URL={YOUR_MIGRATE_DATABASE_URL_VALUE}
```

#### Creating a Shadow Database Manually

Some Prisma commands that are used only in development, such as `prisma migrate`, need a temporary second database that is automatically created and deleted every time these commands are run. Because Heroku PostgreSQL is hosted on the cloud, you need to create a shadow database manually and copy the connection string.

While this tutorial will walk you through the relevant steps, if you'd like to learn more about Prisma shadow databases, you can do so [here](https://www.prisma.io/docs/concepts/components/prisma-migrate/shadow-database).

To create the shadow database, open your [Heroku dashboard](https://dashboard.heroku.com/apps), and locate and open the newly created project. Under the **Resources** tab, click on the **Add-ons** search bar and type "Heroku Postgres". Click on the first result to add the database.

![The deploy project page](./8tTSAON.jpeg)

Please note that you will now have two databases, as shown below:

![Two databases on Heroku](./jxDQo5T.jpeg)

Click on the one on top (the one you created manually) to open its details. On the **Settings** tab under **Database Credentials**, click on **View Credentials** and copy the database `URI`. You will add this to your local `.env` file to allow you to connect to the database.

![The shadow DB details page](./V2PggEC.jpeg)

Add the `URI` to the local `.env` file with the key `SHADOW_DATABASE_URL`.

Your local `.env` file should now have the following details:

```env
DATABASE_URL={YOUR DATABASE URL}

MIGRATE_DATABASE_URL={YOUR DATABASE MIGRATE URL}

SHADOW_DATABASE_URL={YOUR SHADOW DATABASE URL}
```

#### Defining a Schema for Your Model

To define a schema for your tasks model, open the `prisma/schema.prisma` file, and replace the existing content with the following:

```prisma
datasource db {
  provider = "postgres"
  url      = env("MIGRATE_DATABASE_URL")
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
  referentialIntegrity = "prisma"
}

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

model Tasks {
  id  String  @id @default(cuid())
  task String
}
```

The `datasource db` provides details for connecting to the database for running migrations and querying. When querying the database after running the migrations, the value for `url` in `database db` will be switched to `env("DATABASE_URL")`. This is because at the time of writing, one of the limitations of the data proxy is that it can only used to [query the database with Prisma Client](https://www.prisma.io/docs/data-platform/data-proxy#important-considerations-about-the-data-proxy). The `DATABASE_MIGRATE_URL` contains a direct connection string to the database that will be used to run migrations.

The tasks model will only contain two fields:

- **`id`:** The task id
- **`task`:** The task name

#### Running the Migrations and Adding Some Data with Prisma

To run the migrations and add the `tasks` table to the database, run the following command in your terminal, and provide a name for the new migration:

```bash
npx prisma migrate dev
```

When the migration runs successfully, you should see this message on the terminal:

![A successful prisma migration](./CwMw0jY.jpeg)

Now that your database is in sync with your schema, you can add some data with Prisma. To do this, run the following command in your terminal to open Prisma Studio in your browser:

```bash
npx prisma studio
```

After Prisma Studio loads, select your model to add some data. Click on the **Add record** button, add three tasks, and click on the **Save 3 changes** button to save the tasks.

![Prisma Studio interface](./8ce8zc6.jpeg)

#### Showing the Data to Authenticated Users

Open the `prisma/schema.prisma` file and change the `url` value in the `datasource db` to `env("DATABASE_URL")`. The `prisma/schema.prisma` file should now look like this:

```prisma
datasource db {
  provider = "postgres"
  url      = env("DATABASE_URL")
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
  referentialIntegrity = "prisma"
}

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

model Tasks {
  id  String  @id @default(cuid())
  task String
}
```

Next, you need to fetch the data from the database. This can be achieved by modifying the `pages/index.js` file as shown below:

```js
import styles from '../styles/Home.module.css'

import { useUser, UserButton, SignInButton, SignUpButton } from '@clerk/nextjs'
import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

export default function Home({ tasks }) {
  const { isSignedIn, isLoading, user } = useUser()
  return (
    <div className={styles.container}>
      <nav className={styles.nav}>
        <h2>My Tasks</h2>
        {isSignedIn ? (
          <UserButton />
        ) : (
          <div>
            <SignInButton />
            <SignUpButton />
          </div>
        )}
      </nav>

      <div>
        {isLoading ? (
          <></>
        ) : (
          <div>
            {isSignedIn ? (
              <div>
                <p>Welcome {user.firstName}!</p>
                {tasks ? tasks.map((task) => <p>{task.task}</p>) : <div></div>}
              </div>
            ) : (
              <p>Sign in to view your tasks!</p>
            )}
          </div>
        )}
      </div>
    </div>
  )
}

export async function getServerSideProps() {
  const tasks = await prisma.tasks.findMany()
  return {
    props: {
      tasks: tasks,
    },
  }
}
```

Open `http://localhost:3000/` in your browser, and once you've logged in, you should be able to see the tasks you just added.

![The added tasks after logging in](./NTxO8tD.jpeg)

## Conclusion

In this article, you have learned about [Clerk](/), a powerful service that can handle user identity management for you. You have also learned about the various use cases of Clerk, a few of its components and hooks, and how you can [integrate it into your Next.js application](/nextjs-authentication) to easily handle user authentication. Finally, you have learned how to integrate Prisma into the application, use Prisma Cloud, and add data to your cloud-hosted database on Heroku.

---

# Quickly Build a User Switcher, Just Like Gmail
URL: https://clerk.com/blog/build-a-user-switcher-just-like-gmail.md
Date: 2022-06-03
Category: Guides
Description: Build an app with complete authentication and a user switcher just like gmail has.

Developing an authentication system from scratch can be time-consuming, and the process can be prone to bugs. If you're looking for a customer identity platform that provides user management features like authentication, authorization, and management of user profiles, roles, and permissions, check out [Clerk](/). Clerk can save you time when it comes to building and testing your authentication flow. It also provides multi-session authentication, which allows users to seamlessly log in and switch between different accounts.

In this tutorial, you'll learn how to easily implement your own user profile switcher using Clerk and [Next.js](https://nextjs.org). You can follow along with this tutorial using [this GitHub repository](https://github.com/Anshuman71/clerk-user-switcher).

## What Is Clerk

Clerk is a one-stop solution for authentication and customer identity management. It helps you build a flawless user authentication flow that supports logging in with a password, multifactor authentication, or social logins with providers like [Google](/blog/nextjs-google-authentication), LinkedIn, Facebook, and GitHub. Clerk provides components like `<SignUp/>` and `<SignIn/>` that you can plug into your application right away to quickly build an authentication flow.

It's common for users to have multiple accounts for different purposes. For instance, you may have a personal YouTube channel for your friends and family, and another one specifically intended for your audience in your work as a developer. With Clerk’s multisession feature, you can seamlessly and intuitively switch between both accounts as needed.

## Building a User Switcher

Before you begin building a user switcher, you'll need a code editor like [Visual Studio Code](https://code.visualstudio.com/download). You'll also need [Node.js](https://nodejs.org/en) (version 14 or newer) and [npm](https://www.npmjs.com) installed.

[Create your Clerk account](https://dashboard.clerk.com/sign-up) by following the steps on their website. Once registered, navigate to the Clerk dashboard, where you'll begin this tutorial:

![Clerk dashboard home for starting the tutorial](./0bc55bf7d729c611963f855cae53cafe5d8acb63-3840x2160.png)

### Set Up the Project

To set up the project, run `npx create-next-app clerk-app` in your terminal. This will initialize a Next.js project. Then you need to run `npm install @clerk/nextjs` inside the project and open your [Clerk dashboard](https://dashboard.clerk.com) in a web browser. In the left navigation, click on **API Keys** and copy the **Frontend API key**, **Backend API keys** and **JWT verification key**:

![Clerk API keys page showing frontend and backend keys](./03c567841a526a3410b52ba746eab23708ac9990-3840x2160.png)

Save the keys copied above in a `.env.local` file inside your project:

```text {{ title: '.env.local' }}
NEXT_PUBLIC_CLERK_FRONTEND_API=<frontend-key>
CLERK_API_KEY=<backend-api-key>
CLERK_JWT_KEY=<jwt-verification-key>
```

### Set Up the Authentication Flow

The authentication flow of your application dictates how the users access different parts of your application. In this example, the user authentication flow works like this:

![User switcher flow diagram](./f2858db3eadd7bb4ff6eae2859b578e8a5ee217f-2264x1272.png)

To begin, implement the authentication flow in the `pages/_app.js`:

```jsx {{ title: 'pages/_app.js' }}
import { ClerkProvider, SignedIn, SignedOut } from '@clerk/nextjs'

import { useRouter } from 'next/router'

import Head from 'next/head'

import Link from 'next/link'

// pages that can be accessed without an active user session.

const publicPages = ['/', '/sign-in/[[...index]]', '/sign-up/[[...index]]']

const MyApp = ({ Component, pageProps }) => {
  const router = useRouter()

  return (
    <ClerkProvider {...pageProps}>
      <Head>
        <title>Clerk app</title>

        <link rel="icon" href="/favicon.ico" />

        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      </Head>

      {/*If the route is for the home, sign-in and sign-up pages: show them without checks.*/}

      {publicPages.includes(router.pathname) ? (
        <Component {...pageProps} />
      ) : (
        <>
          {/*Show all pages if the user is signed in*/}

          <SignedIn>
            <Component {...pageProps} />
          </SignedIn>

          {/*Ask to sign in if the user isn't signed in*/}

          <SignedOut>
            <main>
              <p>
                Please{' '}
                <Link href="/sign-in">
                  <a>sign in</a>
                </Link>{' '}
                to access this page.
              </p>
            </main>
          </SignedOut>
        </>
      )}
    </ClerkProvider>
  )
}

export default MyApp
```

### Create the Sign-Up and Sign-In Pages

Next.js uses file-system-based routing, which makes it easy to create new pages. To learn more about Next.js routing check out their [official documentation](https://nextjs.org/docs/routing/introduction).

To create the sign-up and sign-in pages, navigate to the `pages/` folder in your project and create two new folders: `sign-up/` and `sign-in/`. Then create a new `[[...index]].js` file inside both of these folders. These routes will catch all the paths, including `/sign-up` and `/sign-in`.  You can read more about dynamic routing in the [Next.js documentation](https://nextjs.org/docs/routing/dynamic-routes#optional-catch-all-routes).

Use the prebuilt components for `<SignIn/>` and `<SignUp/>` to populate the pages:

```jsx {{ title: 'pages/sign-up/[[...index]].js' }}
import { SignUp } from '@clerk/nextjs'

const SignUpPage = () => <SignUp path="/sign-up" routing="path" signInUrl="/sign-in" />

export default SignUpPage
```

![Clerk SignUp component page screenshot](./baf4da4192af228f95122e38d5bb1c1cdef75f38-3840x2160.png)

```jsx {{ title: 'pages/sign-in/[[...index]].js' }}
import { SignIn } from '@clerk/nextjs'

const SignInPage = () => <SignIn path="/sign-in" routing="path" signUpUrl="/sign-up" />

export default SignInPage
```

![Clerk SignIn component page screenshot](./23a3986bedc299e0b5bd24170b1b10cb97c538e9-3840x2160.png)

### Create the Home Page

Now, the home page should display the greeting "Welcome to your new app." at the top of the page. If the user is signed in, it will show them their profile page. Otherwise, it will ask them to sign up or sign in:

![Home page with UserButton in navigation](./c911b489b95a6551e04b58ac4f8c1f59f6aec94b-1848x1080.png)

Update the `pages/index.js` file to use the `<SignedIn/>` component to conditionally render the child components if the user is signed in and use the `<SignedOut/>` component to render the child components if the user isn't signed in.

Inside the `<SignedIn/>` component, use the `<UserProfile/>` component provided by Clerk to show the user's profile details and allow them to edit their information.

You can also use the `<UserButton />` component in the top `<nav />` to allow users to manage their accounts and sign out of the application. The `<UserButton />` will render as a button with the user's avatar.

Inside the `<SignedOut/>`, render two `<Link />` components to send the user to the sign-in or sign-up page:

```jsx {{ title: 'pages/index.js' }}
import { SignedOut, SignedIn, UserProfile, UserButton } from '@clerk/nextjs'

import React from 'react'

import Link from 'next/link'

const Home = () => {
  return (
    <div
      style={{
        display: 'flex',

        justifyContent: 'center',

        alignItems: 'center',
      }}
    >
      <main>
        <nav
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
          }}
        >
          <h1>Welcome to your new app.</h1>

          <UserButton />
        </nav>

        <div>
          <SignedIn>
            <UserProfile />
          </SignedIn>

          <SignedOut>
            <Link href="/sign-up">
              <a>Sign up </a>
            </Link>
            or
            <Link href="/sign-in">
              <a> Sign in </a>
            </Link>
            to get started.
          </SignedOut>
        </div>
      </main>
    </div>
  )
}

export default Home
```

If the user isn't signed in, the page will look like this:

![Signed-out state prompting sign-in](./c182a98f893cb71730e3ef707c27115f02b0e773-3840x2160.png)

Or if the user is signed in, it will look like this:

![Signed-in state with profile visible](./4c14e59c88acddeea0c8f6456b78f5816ddcac40-3840x2160.png)

When you click the user avatar at the top-right of your screen, a pop-up will appear containing buttons for **Manage account** and **Sign out**:

![User menu with Manage account and Sign out](./de1410f96d3edfc362d2a6cb29a1189dc80ff242-800x780.png)

### Implementing the User Switcher

Before moving on with this tutorial, you need to navigate to your [Clerk dashboard](https://dashboard.clerk.com) and enable the **Multi-session handling** feature inside the **Sessions** settings:

![Enable multi-session handling in Clerk dashboard](./c8b7ca26cacdedf785d37d16fa473ab7593f9b42-3840x2160.png)

After enabling multisession handling, go back to your application window and click on the user avatar again. Now you'll see that a new option, **Add account**, is available:

![Add account option shown in user menu](./103957875f33abe0dbf86e25a23739c7773a9468-914x1018.png)

Clicking on the **Add account** button will redirect users to the sign-in page, where they can sign in or sign up for a new account.

After signing in, Clerk will redirect the user back to the application with the new session, and the avatar pop-up menu will show all active sessions. The user can now switch between accounts by selecting them from the list:

![Multiple active sessions list in user switcher](./2b2198763b20ac5321eb634010ae6b3b907b7223-892x1310.png)

### Authenticating API Endpoints

To prevent malicious requests from coming through, it's essential to authenticate your API endpoints. With Clerk, you can access the user's authentication status in the Next.js API handlers. To do that, you must wrap your API handler function inside Clerk's `withAuth` higher-order function to access the `auth` property on the request object.

The following example uses the `request.auth` property to check if the `sessionId` is available and then sends the `userId` in the response. Otherwise, it returns a `401: Unauthorized` response code:

```jsx {{ title: 'pages/api/getUserId.js' }}
import { withAuth } from '@clerk/nextjs/api'

export default withAuth((request, response) => {
  const { sessionId, userId } = request.auth

  if (!sessionId) {
    return response.status(401).json({ id: null, message: 'No user signed in!' })
  }

  return response.status(200).json({ id: userId })
})
```

On the home page, add a button to request the API endpoint and show the user ID in an alert:

```jsx {{ title: 'pages/index.js' }}
import { SignedOut, SignedIn, UserProfile, SignOutButton, UserButton, useAuth } from '@clerk/nextjs'

import React from 'react'

import Link from 'next/link'

const Home = () => {
  function showUserId() {
    fetch('/api/getUserId')
      .then((res) => res.json())

      .then(({ id }) => {
        alert(`User id: ${id}`)
      })
  }

  return (
    <div
      style={{
        display: 'flex',

        justifyContent: 'center',

        alignItems: 'center',
      }}
    >
      <main>
        <nav
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
          }}
        >
          <h1>Welcome to your new app.</h1>

          <UserButton />
        </nav>

        <div>
          <SignedIn>
            <button onClick={showUserId}>Show user ID</button>

            <UserProfile />

            <SignOutButton />
          </SignedIn>

          <SignedOut>
            <Link href="/sign-up">
              <a>Sign up </a>
            </Link>
            or
            <Link href="/sign-in">
              <a> Sign in </a>
            </Link>
            to get started.
          </SignedOut>
        </div>
      </main>
    </div>
  )
}

export default Home
```

After you've added this button, your user switcher is ready:

## Conclusion

After completing this tutorial, you will have successfully built a Next.js application that supports multisessions. While doing so, you learned about creating a new Next.js application, setting up a Clerk account, and integrating the Clerk SDK with your Next.js application.

You used the UI components provided by Clerk to create an authentication flow and user profile page. You also learned about the importance of multisession support in your application and how easy you can implement it with Clerk. Lastly, you created an API route in Next.js and secured it with Clerk.

Using the Clerk SDK, you can expand on the example above to add social logins and multifactor authentication to your application.

---

# Add authentication to your Gatsby app
URL: https://clerk.com/blog/add-authentication-to-your-gatsby-app.md
Date: 2021-09-15
Category: Guides
Description: Learn how to add authentication and user management to your Gatsby app with Clerk. 

At Clerk, our mission is to empower every developer to easily add authentication and user management to their apps.

We know it's hard to keep up with all the exciting new options out there, so we strive to create more tools and integrations, so you, the developer, can spend more time building what really matters: your app.

With that in mind, we're happy to announce our `gatsby-plugin-clerk`.

## What it does

The plugin wraps our `ClerkProvider` component around the entire Gatsby app.

This has two benefits: keeping the layout component cleaner while grouping all the configuration in `gatsby-config.js`, alongside other plugins.

## How to use it

First and foremost, install the necessary packages:

```sh
yarn add gatsby-plugin-clerk @clerk/clerk-react

# or

npm install gatsby-plugin-clerk @clerk/clerk-react
```

Now, let's configure the plugin on `gatsby-config.js.`

For this step, you'll need the `frontendApi` key of your Clerk application. To find it, go to your [dashboard](https://dashboard.clerk.com), choose the application and the instance you're working on, and locate the key on the **Home** tab.

```javascript
// gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-clerk',
      options: {
        // OBS: Don't push your frontend API key to version control.
        // A safer approach is to set it as an environment variable for each environment your app will run in.
        frontendApi: 'YOUR_FRONTEND_API_KEY',
      },
    },
  ],
}
```

From here onwards, everything should work just the same. You can start using components like `SignedIn` and `SignedOut` from the root of your app.

```jsx
// src/pages/index.js

import React from 'react'
import { SignIn, SignedIn, SignedOut, UserButton } from '@clerk/clerk-react'

function IndexPage() {
  return (
    <>
      <SignedIn>
        <UserButton />
      </SignedIn>

      <SignedOut>
        <SignIn />
      </SignedOut>
    </>
  )
}

export default IndexPage
```

And that's it, in just a few steps, we added easy and secure authentication with beautiful and complete user management to your Gatsby app.

## Bonus: Clerk + Gatsby starter

To make it even easier for you, we went ahead and created a [Clerk + Gatsby starter repository](https://github.com/clerkinc/clerk-gatsby-starter). It has Clerk integrated with [Gatsby's default starter](https://github.com/gatsbyjs/gatsby-starter-default).

Inside `src/api` you can also find the new Gatsby Functions in action. We added a couple of examples there, so you know how to use Gatsby's serverless functions with Clerk's backend API.

Fork it, clone it and build it!

## Bonus 2: Deploy the starter on Gatsby Cloud

Ok, we owe this one to the Gatsby team. They did a great job in building a super easy deployment flow.

So, if you want to deploy the [Clerk + Gatsby starter](https://github.com/clerkinc/clerk-gatsby-starter) on Gatsby Cloud, just click [here](https://www.gatsbyjs.com/dashboard/deploynow?url=https://github.com/clerkinc/clerk-gatsby-starter).

Once there, you can configure a number of things, like the Gatsby Cloud workspace the project should live in, the repository name that will be created in your GitHub account, and even add more integrations.

But here's the one thing you can't forget: your need to add your environment variables, like in the image below. If you don't know where to find them, check the [README](https://github.com/clerkinc/clerk-gatsby-starter/blob/main/README.md) file of this starter.

![Add Authentication To Your Gatsby App guide illustration](./37292ec19825df500deddefc4a6d70f7c3a52a72-1782x928.png)

Once you're done, head over to your GitHub account, find the newly created repository, clone it and start building.

And just like this, you can use all the benefits and performance that Gatsby Cloud provides to Gatsby apps.

*If you encounter a permissions error while doing the steps above, here's what's happening: Gatsby Cloud requires permissions to create and manage future repositories on your GitHub account in order to create a new repository for you.*

*To fix it, go to your [GitHub installations page](https://github.com/settings/installations), and configure Gatsby Cloud as such:*

![Add Authentication To Your Gatsby App guide illustration](./12c63a17a9f99acbc4fa4a623c613da79efac314-1498x546.png)

## Need help?

If you're unfamiliar with how our prebuilt UI components or other details described in the guide work, you can always go to our [documentation](/docs) to find out more or reach out to us on our [Discord](https://clerk.com/discord) server.

Happy coding!