# Clerk Blog — Page 10

# Stable Support for the Next.js App Router, plus a Middleware Update!
URL: https://clerk.com/blog/nextjs-13-4.md
Date: 2023-05-04
Category: Engineering
Description: App Router support is out of beta, plus we've launched a major middleware update.

## @clerk/nextjs\@4.17.0 is released

Clerk has updated our SDK to support Next.js version 13.4.0. We've added stable support for the App Router, which is the default for new applications. We've also improved the ergonomics of our middleware helper for more composability and to mitigate common pitfalls.

[See the updates in our new Next.js documentation](/docs/nextjs/get-started-with-nextjs), or read on for more details.

### Stable App Router Support

Next.js version 13.4.0 launched today and the App Router is now stable. In turn, Clerk's support for the App Router is also now stable in `@clerk/nextjs` version 4.17.0.

If you previously adopted `@clerk/nextjs/app-beta`, there have been very few changes:

- The `auth()` and `currentUser()` helpers have been moved to a permanent home in `@clerk/nextjs`
- React imports from `@clerk/nextjs/app-beta/client` are no longer necessary, and you can import from `@clerk/nextjs` intstead. The package now automatically detects if components are being used from a client component or a server component, and loads the proper form.

That's all! Our documentation has been updated to [reflect the changes](/docs/nextjs/get-started-with-nextjs).

### Middleware Update

Along with today's launch, we've also released a new middleware helper to make things a little easier and more composable.

In its simplest form, these few lines are all you need to [integrate Clerk](/nextjs-authentication):

```typescript
import { authMiddleware } from '@clerk/nextjs'

export default authMiddleware()

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)'],
}
```

This sets your application in a protected mode – if users are signed out the will be automatically redirected to a sign in. Unprotected pages need to be explicitly listed in the `publicRoutes` argument:

```typescript
export default authMiddleware({
  // Make the homepage accessible while signed out
  publicRoutes: ['/'],
})
```

This new helper also has `beforeAuth` and `afterAuth` arguments to enable more composability with libraries like `next-intl`. For more details, checkout the updated [middleware documentation](/docs/nextjs/middleware).

---

# Generating and Using UUIDs in React
URL: https://clerk.com/blog/generating-and-using-uuids-in-react.md
Date: 2023-04-20
Category: Guides
Description: Learn the significance of UUIDs in full-stack apps, their optimal usage, and how to implement them in React apps.

When working with full-stack apps, you will often come across identifiers. Also known as IDs, identifiers are used to identify data records related to apps. Based on the sensitivity and scope of the data in question, the identifier can be set as locally or globally unique. A popular globally unique identifier is UUID, which stands for *universally unique identifier*.

In this article, you will learn what UUIDs are, when to use them, and how to get started with implementing them in your React app.

## What Are UUIDs and When Are They Used?

UUIDs are a popular and safe method of generating globally unique identifiers for data records. It's said that there's a [one-in-a-billion chance of two randomly generated UUIDs matching exactly](https://en.wikipedia.org/wiki/Universally_unique_identifier#:~:text=Thus%2C%20the%20probability%20to%20find,is%20one%20in%20a%20billion) in a set of 103 trillion UUIDs, which is small enough to say that UUIDs are practically unique.

UUIDs are also better than sequential identifiers when it comes to parallel data insertion in databases as you don't need to adhere to a sequence to create keys and insert records.

A UUID is formatted like this: `2a6db6e1-8967-4511-9839-a7cb3c895710`.

There are a total of thirty-two hexadecimal characters separated into sets of 8-4-4-4-12 characters, which are themselves separated by hyphens. However, these thirty-two characters cannot be randomly generated and put together to create a UUID. In order for an ID to be universally unique—and therefore be called a UUID—it needs to be [compliant with the RFC 4122 protocol](https://www.cryptosys.net/pki/uuid-rfc4122.html).

UUIDs have multiple use cases, the most prominent of which include the following:

- To identify records uniquely across tables
- When two tables are merged, as UUIDs remain unique to avoid confusion
- When parallel insertion is needed, as sequential IDs can be created in parallel

A number of third-party libraries and functions are available to make it simpler for developers to implement UUIDs in apps. In the following section, you'll see multiple ways to implement UUIDs in a React app.

## Generating UUIDs in Your React Application

Now that you understand what UUIDs are (and when you might use them), let's move on to how you can implement them in your React apps. First, you will create a boilerplate form, then learn how to set up a UUID on that form in four different ways.

Each of these methods will use the same protocol to generate UUIDs that are globally unique. Which one you use, however, will depend on your use case and preferences.

The first two will require external dependencies that may make developer experience better but add a performance overhead and/or weight to the app size. The third method will use an inbuilt function from the `crypto` package (which may or may not be available depending on the JavaScript environment), and the last method will use a raw algorithm to create UUIDs manually in app, adding no weight or performance overhead to your app but requiring manual setup and maintenance.

You can find the complete source code of the demo app in this [GitHub repo](https://github.com/krharsh17/react-uuid-demo).

### Prerequisites

To proceed with this tutorial, you need to have [npm installed](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) on your system.

Next, you'll need to set up a new React project. Run the following command:

```sh
npx create-react-app react-uuid-demo
```

Once the new React project is created, run the following commands to start the development server:

```sh
cd react-uuid-demo
npm start
```

This is what the output should look like.

![Generating And Using Uuids In React guide illustration](./cb0f1846dd3b84dbe27c108ff7ed6c7420992d7a-2000x1310.png)

You will install the dependencies as required later on.

### Create a Simple Page with User Information

To ease your familiarity with the concepts, you'll create a basic boilerplate form that asks for a username and email and allows users to generate a UUID for themselves. Here's what the form will look like.

![Generating And Using Uuids In React guide illustration](./5878f82d4a51af6fbbd163e2b42d20f13fd7b8fc-2000x1089.png)

The **Generate UUID** button will be enabled once the user fills in the form data.

To set it up, you'll need to paste the following code snippet into your **App.js** file:

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

export default function App() {
  // define state containers
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
  const [id, setId] = useState('')

  // Define listener for button click event. You will use this function to generate UUIDs later
  const onGenerateButtonClick = () => {
    console.log('Button clicked')
  }

  return (
    <div className={'mainContainer'}>
      <div className={'titleContainer'}>
        <div>Create your profile</div>
      </div>

      {/* Name input field */}
      <div className={'inputContainer'}>
        <input
          value={name}
          placeholder="Enter your full name"
          onChange={(ev) => setName(ev.target.value)}
          className={'inputBox'}
        />
        <br />
      </div>

      {/* Email input field */}
      <div className={'inputContainer'}>
        <input
          value={email}
          placeholder="Enter your email"
          onChange={(ev) => setEmail(ev.target.value)}
          className={'inputBox'}
        />
        <br />
      </div>

      {/* Button to generate UUIDs */}
      <div className={'buttonContainer'}>
        <input
          type={'button'}
          disabled={!(name !== '' && email !== '')}
          value={'Generate UUID'}
          onClick={onGenerateButtonClick}
          className={'inputBox'}
        />
        <br />
      </div>

      {/* UUID box */}
      <div className={'inputContainer'}>
        <input
          value={id}
          placeholder="UUID"
          disabled={true}
          onChange={(ev) => setId(ev.target.value)}
          className={'inputBox'}
        />
        <br />
      </div>
    </div>
  )
}
```

To add some basic styling so that the form looks like the one shown in the image above, you'll need to paste the following code snippet into your `App.css` file:

```css
.mainContainer {
  flex-direction: column;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.titleContainer {
  display: flex;
  flex-direction: column;
  font-size: 64px;
  margin-bottom: 32px;
  font-weight: bolder;
  align-items: center;
  justify-content: center;
}

.inputContainer {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.buttonContainer {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-bottom: 40px;
}

.inputBox {
  height: 48px;
  width: 400px;
  font-size: large;
  border-radius: 8px;
  border: 1px solid grey;
  padding-left: 8px;
}
```

You'll also need to update the styles in `index.css` with the following code to complete the styling of the app:

```css
html,
body {
  padding: 0;
  margin: 0;
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    Segoe UI,
    Roboto,
    Oxygen,
    Ubuntu,
    Cantarell,
    Fira Sans,
    Droid Sans,
    Helvetica Neue,
    sans-serif;
}

* {
  box-sizing: border-box;
}

main {
  padding: 5rem 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

code {
  background: #fafafa;
  border-radius: 5px;
  padding: 0.75rem;
  font-family:
    Menlo,
    Monaco,
    Lucida Console,
    Courier New,
    monospace;
}

input[type='button'] {
  border: none;
  background: cornflowerblue;
  color: white;
  padding: 4px 12px;
  border-radius: 12px;
  cursor: pointer;
}

input[type='button']:disabled,
input[type='button'][disabled] {
  border: 1px solid #999999;
  background-color: #cccccc;
  color: #666666;
}
```

If you run the app now, it should look like the one in the image shared above.

### Create UUIDs Using Different Methods

Now that your base app is ready, you'll see how to create UUIDs using `uuidv4`, `react-uuid`, `crypto.randomUUID()`, and finally, through code.

### Using uuidv4

The first and quite popular method of generating UUIDs in JavaScript-based apps is with the [uuid](https://www.npmjs.com/package/uuid) npm package. You can install it in your React app by running the following command:

```sh
npm i uuid
```

You'll need to import it into your app by adding the following line of code below the existing imports in your `App.js` file:

```jsx
import { v4 as uuid } from 'uuid'
```

You can now use the following function to generate UUIDs using this package:

```jsx
const uuidFromUuidV4 = () => {
  const newUuid = uuid()
  setId(newUuid)
}
```

*Note:* You'll need to paste this function in your `App` component right below the `onGenerateButtonClick()` function.

Finally, you'll need to replace the `onGenerateButtonClick` function in your `App` component with the code below to call this method when the **Generate UUID** button is clicked:

```jsx
const onGenerateButtonClick = () => {
  uuidFromUuidV4()
}
```

Once you've done this, you can see it in action by going to `http://localhost:3000` and filling out the form.

### Using react-uuid

Another popular method for React apps to implement UUID is by using the npm package [react-uuid](https://www.npmjs.com/package/react-uuid). Both the `react-uuid` and `uuidv4` packages can be implemented seamlessly in React; their main difference is that `react-uuid` was designed specifically for React apps while `uuidv4` was primarily meant for Node.js apps.

You can install the package in your project by running the following command:

```sh
npm i react-uuid
```

Next, you'll need to import the package in your source code by adding the following import line at the top of your `App.js `file (below the existing imports):

```jsx
import uuid from 'react-uuid'
```

You can now use the following function to generate UUIDs using this package:

```jsx
const uuidFromReactUUID = () => {
  const newUuid = uuid()
  setId(newUuid)
}
```

*Note:* You'll need to paste this function in your `App` component.

To call this function when **Generate UUID** is clicked, you'll need to update the code for the `onGenerateButtonClick` function with the following:

```jsx
const onGenerateButtonClick = () => {
  uuidFromReactUUID()
}
```

Once you're done with the steps above, you can see this function in action.

### Using crypto.randomUUID()

The inbuilt `crypto` package in JavaScript runtimes can be used to generate UUIDs. Here's a function that uses `crypto.randomUUID()` to generate a UUID:

```jsx
const uuidFromCrypto = () => {
  const newUuid = crypto.randomUUID()
  setId(newUuid)
}
```

You don't need to include any imports for this to work. However, this method only works over secure contexts ([local or HTTPS](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)). Here's how you can update your `onGenerateButtonClick` function to use this method in your app:

```jsx
const onGenerateButtonClick = () => {
  uuidFromCrypto()
}
```

The result is similar to the other methods seen so far.

### Through Code

Perhaps you prefer not to install any third-party libraries to implement UUID and the `crypto.randomUUID()` doesn't suit your use case. If so, you can use a method that relies on another function from the `crypto` package to generate RFC 4122–compliant UUIDs in your source code:

```javascript
const uuidFromCode = () => {
  const newUuid = ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
    (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16),
  )
  setId(newUuid)
}
```

Based on a [Stack Overflow answer](https://stackoverflow.com/a/2117523), this method fits most UUID-related use cases perfectly. Since it uses `crypto.getRandomValues()` instead of `Math.random()`, you can rest assured that the UUIDs generated using this method will be practically globally unique.

Here's how your `onGenerateButtonClick` function should look like using this method:

```javascript
const onGenerateButtonClick = () => {
  uuidFromCode()
}
```

The result will again look similar to the methods discussed above. Once you've filled in the form, you can keep clicking **Generate UUID** in order to generate new UUIDs.

As mentioned, you can find the complete source code of the demo app used in the tutorial [here](https://github.com/krharsh17/react-uuid-demo).

## Conclusion

UUIDs are handy when it comes to identifying records uniquely across tables globally. With an infinitesimal chance of collision, UUIDs present you with a robust solution to the global identification problem. In this article, you saw four different methods of implementing a UUID in your React app.

UUIDs are used in many third-party tools internally too. It's essential that the third-party dependencies you include in your app create UUIDs reliably to ensure the proper functioning of your app.

[Clerk](/) is an auth provider that makes it easy to add authentication and user management to your application. As for its data, Clerk uses [K-Sortable Globally Unique IDs, or KSUIDs,](https://github.com/segmentio/ksuid) for generating unique identifiers. These extend UUIDs to add time-based ordering and friendlier representation formats for simplicity. If you're looking for an auth solution for your app, make sure to [check out Clerk](https://dashboard.clerk.com/sign-up)!

---

# Setting and Using Cookies in React
URL: https://clerk.com/blog/setting-and-using-cookies-in-react.md
Date: 2023-04-14
Category: Guides
Description: Learn how to set up cookies in React with this guide! You'll create a login page and store user information using cookies.

Web cookies consist of data generated by a server and sent to a user's web browser (such as Chrome or Firefox). These small pieces of information are then stored by the website on the user's device. Cookies can be used to keep track of things like items in a shopping cart. If the user leaves the website and comes back later, the items will still be there waiting for them.

They can also be used for security purposes, such as user authentication, and for tracking a user's behavior, which allows websites to personalize the user's experience. For instance, if a user logs out of your site, they can simply log back in without needing to enter their username and password again. It's important to note, however, that cookies can be stolen by hackers who can use them to impersonate the user on your website.

In this article, you'll explore how to set up cookies in a ReactJS application. You'll create a [simple login page](/blog/building-a-react-login-page-template) and use cookies to store information about the user's logged-in session.

> For secure cookie management and session handling, [learn more about our React support](/react-authentication).

## What Are Web Cookies?

As mentioned, web cookies are small pieces of data that are stored on a user's computer by a website. They're typically used to store information about the user, such as their preferences, login information, and other data. Cookies are created and stored by the website when the user visits the site. The website can then retrieve the cookies from the user's computer when they visit the site again, allowing the website to "remember" the user and their preferences.

Cookies are typically stored in plain text, which means that they can be read and modified by anyone who has access to the user's computer. Therefore, it's important to use cookies carefully and securely to protect the user's data.

Before you start the tutorial below, make sure you have [npm and Node.js installed](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) on your machine. Once this is done, you can begin working on your React application.

## Set Up Your React Application

Open a terminal and create a new React application using the following command: `npx create-react-app my-app`. Once the application is created, open the directory with your favorite code editor (such as VS Code) and start working on your application. You'll see a bunch of files and folders that look like the image below.

![Setting And Using Cookies In React guide illustration](./d8c90582f6e552dc9d106a689e443d62fa2ad78a-2000x1140.png)

To test that your React application is properly set up, open a terminal and navigate to the `my-app` project folder. Start the server by running `npm start`; open your web browser and enter the specified port in the terminal (`3000`) to view your React application.

By completing these steps, you can verify that your React application is running as expected. You can then proceed with writing code and building your application without any issues. You should see a web page like the image below.

![Setting And Using Cookies In React guide illustration](./8670f2974e4e75421a43abce7a396b50109abe56-2000x917.png)

## Create a Simple Welcome Page

In your React project, create a new file called `WelcomePage.js` inside the `src` folder and add the following code inside:

```jsx
import React from 'react'

export default function WelcomePage() {
  return <div>WelcomePage</div>
}
```

To render the welcome page, first navigate to the `App.js` file inside the `src` folder. Import the `WelcomePage.js` file using the following code:

```jsx
import WelcomePage from './WelcomePage.js'
```

Then, inside the return statement, remove everything and add this code:

```jsx
<WelcomePage />
```

In the above instructions, you imported the `WelcomePage.js` file and used the `<WelcomePage />` tag inside the return statement of the `App.js` file. This allows the `App.js` file to render the welcome page in a web browser. When the page is rendered, you should see a white page with the word "WelcomePage" on it.

## Create a Login Page

Create another file inside the src folder called `LoginPage.js` and add the following block of code:

```jsx
import React, { useState } from 'react'

function LoginPage({ onLogin }) {
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')

  function handleSubmit(event) {
    event.preventDefault()
    onLogin({ username, password })
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Username:
        <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} />
      </label>
      <br />
      <label>
        Password:
        <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
      </label>
      <br />
      <input type="submit" value="Submit" />
    </form>
  )
}

export default LoginPage
```

This `LoginPage` component has fields for a username and a password as well as a submit button. When the user fills out the form and clicks Submit, the `onLogin` callback function is called with their username and password. The parent component (`App` in this case) can then use this information to set the user cookie and render the `WelcomePage` component.

## Set Up Cookie Handling

To use cookies in your app, you'll need to import the react-cookie library from the React library. This library allows you to set, get, and delete cookies in your app.

First, install the library by running the command `npm install react-cookie` in the root folder of your app in the terminal.

Now change your **App.js** file to match the following code:

```jsx
import React from 'react'
import WelcomePage from './WelcomePage.js'
import LoginPage from './LoginPage.js'
import { CookiesProvider, useCookies } from 'react-cookie'

function App() {
  const [cookies, setCookie] = useCookies(['user'])

  function handleLogin(user) {
    setCookie('user', user, { path: '/' })
  }

  return (
    <CookiesProvider>
      <div>
        {cookies.user ? <WelcomePage user={cookies.user} /> : <LoginPage onLogin={handleLogin} />}
      </div>
    </CookiesProvider>
  )
}

export default App
```

In the code above, the `App` component uses the `useCookies` hook to manage cookies. The `handleLogin` function is called when a user logs in, and it sets a cookie named "user" with the user's information.

The `LoginPage` and `WelcomePage` components are wrapped in the `CookiesProvider` component, which provides a global context for cookies. This allows the `WelcomePage` component to access the user cookie and display the user's information.

The `App` component uses a ternary operator to decide which component to render based on the presence of the user cookie. If the cookie exists, the `WelcomePage` component is rendered. If the cookie does not exist, the `LoginPage` component is rendered instead.

Now, if you check your page on your browser, you should see a login form that looks like the image below.

![Setting And Using Cookies In React guide illustration](./c4cf9f020742bf3b2413a6b041d8a5f11e5ff057-2000x929.png)

Before you test your application, first change the `WelcomePage.js` file to match the following block of code:

```jsx
import React from 'react'

function WelcomePage({ user }) {
  return <h1>Welcome, {user.username}!</h1>
}

export default WelcomePage
```

This `WelcomePage` component simply displays a welcome message with the user's username. It receives the user object as a prop, which contains the user's username and password. The parent component (`App` in this case) passes the user object to the `WelcomePage` component when `WelcomePage` is rendered.

## Test Your Application

To test your application, go to the browser and fill in the login form with your username and password. When you click **Submit**, the welcome page should be displayed with the words "Welcome" followed by your username. This indicates that the login was successful and the `WelcomePage` component was rendered. It should look like the image below.

![Setting And Using Cookies In React guide illustration](./d5d11e71535fcdefecf7fc0c2a5e362a4cbfcade-2000x654.png)

To check if a cookie has been set in your Chrome browser, you can use the developer tools. Open your browser, and if you're on Chrome, go to the page where the cookie is set by pressing F12 on your keyboard to open the developer tools.

Click on the **Application** tab in the developer tools. In the left panel, expand the **Cookies** section and click on the domain where the cookie is set—in this case, it's `http://localhost:3000`. In the right panel, you should see a cookie that has been set for the domain like in the image above.

You can find the complete code for this tutorial on [GitHub](https://github.com/gitnyasha/using-cookies-in-react).

## Conclusion

In this tutorial, you learned how to create a login page and a welcome page in a React app and how to store the user's login information in a cookie. You also learned how to only display the welcome page if the user is logged in and how to check if a cookie has been set in the Chrome browser.

Using cookies in a React app can make the login process more user-friendly as it allows users to access the welcome page without having to enter their login information every time they visit the page.

Clerk provides an easy way to add authentication and user management to your application. Clerk handles session management, including setting cookies on your behalf, saving you time and effort. This allows you to focus on building the features of your app without having to worry about implementing the authentication and session management features from scratch. [Give Clerk a try by signing up today](https://dashboard.clerk.com/sign-up).

---

# Adding JWT Authentication to React
URL: https://clerk.com/blog/adding-jwt-authentication-to-react.md
Date: 2023-04-14
Category: Guides
Description: Learn how to implement JSON Web Token (JWT) authentication in a React app using a standard flow, and how Clerk can make the process even easier.

JSON Web Token (JWT) authentication is a method of securely authenticating users and allowing them to access protected resources on a website or application. It's a popular and widely used method of web authentication as it allows for easy and secure user authentication without the need for the server to maintain a session state.

In this process, the server generates a signed JWT and sends it to the client. The client then includes this token in subsequent requests to the server to authenticate themselves. The JWT is usually stored in the browser's localStorage and sent as part of the request's headers.

However, the JWT mechanism can be arduous and error-prone, especially if you're building it from scratch. In this article, you'll learn how to implement JWT in a React application using a standard flow, and then you'll see how much easier it gets when repeating the exercise using [Clerk's React authentication](/react-authentication).

## What Is JWT Authentication?

Before we discuss how a user is authenticated with JWT, let's take a closer look at what it contains:

1. `The header:` consists of two parts—the token type, which is JWT, and a signing algorithm, such as HMAC-SHA256 or RSA
2. `The payload:` contains the claims—in other words, the statements about an entity (typically, the user) and additional data
3. `The signature:` used to verify the JWT's integrity

To authenticate a client using JWT, the server first generates a signed JWT and sends it to the client. The client then includes the JWT in the header (usually the [authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization)) of subsequent requests to the server.

The server then decodes the JWT and verifies the signature to ensure that a trusted party sent it. If the signature is valid, the server can then use the information contained in the JWT to authenticate the client and authorize their access to specific resources. The diagram below shows a standard JWT authentication flow.

![JWT authentication flow](./ce92a5f67e79db690f9dffa38d625decebf8da3e-2025x1178.png)

### Advantages and Downsides of Using JWT

Using JWT authentication offers the following advantages:

1. `JWT authentication is stateless:` A JWT contains all the information regarding the user's identity and authentication, including the claims. This can be more efficient than storing session information on the server as it reduces the amount of data that needs to be stored and retrieved for each request.

2. `Create anywhere:` Another advantage of JWT authentication is that the token can be generated from anywhere, including external services or third-party applications. This allows for flexibility in terms of where and how the token is generated, which can be useful in a microservices architecture where different services may need to authenticate users.

3. `Fine-grained access control:` JWT can contain information about the user's role and permissions in the form of claims. This gives the application developers a lot of control over what actions a user is allowed to take.

However, there are also some disadvantages to using JWT authentication:

1. `Hard to invalidate:` Invalidating JWTs is only possible if you maintain a list on a shared database, which introduces additional overhead. The database is necessary because if you need to revoke a token or if a user's permissions change, the server won't otherwise be able to determine the status of the token and might give access when it shouldn't. If the JWTs you're using are long-lived—in other words, they have a very long (or no) expiration time specified—it becomes even more important that they're stored in an accessible database.

2. `Size and security concerns:` JWTs can sometimes contain unnecessary information that might be useless for the application and, at the same time, make the token larger and more cumbersome to work with. If the JWT is unencrypted, it can also end up revealing too much about the user.

Given these challenges, some would say that using cookies over JWT works better in some instances as a method of authentication; for example, when the application needs to keep track of the user's activity across multiple pages, as cookies can be easily read and written on the server side. Let's compare the two in detail.

### Are Cookies Better Than JWT?

To start with, you can create session-based cookies, which automatically expire after the user session is closed, or you can easily set an expiration time for a cookie, which gives more control over session invalidation. You can also use HttpOnly cookies to prevent JavaScript from accessing the cookie information.

However, it's important to note that cookies come with their own flaws. Specifically, as the cookie data is stored on the server and the cookie identifier is stored on the client, they're not entirely stateless like JWTs. This means that the server needs to store and retrieve the cookie data for each request, which would be additional overhead to the authentication process and slow down the application's performance, especially if the number of concurrent users increases.

They're also not ideal for non-browser-based applications, such as mobile and desktop applications. Additionally, cookies can be more vulnerable to certain attacks, such as [cross-site scripting (XSS)](https://owasp.org/www-community/attacks/xss) and [cross-site request forgery (CSRF)](https://owasp.org/www-community/attacks/csrf).

Now that we've covered the advantages and some of the potential challenges of JWT authentication, let's see the process in action. In the following section, you'll see how to implement JWT authentication in your React application.

## Implementing JWT Authentication in Your React Application

In this tutorial, you'll build a simple full-stack application with [authentication in Next.js](/nextjs-authentication). Next.js allows you to implement frontend applications using React and a backend API server without setting up another Node.js project. You'll also understand the pitfalls of creating a JWT authentication from scratch and learn to overcome those limitations using the Clerk SDK.

> For pure React applications (without Next.js), check out our [React authentication solution](/react-authentication) which handles JWT and other auth methods seamlessly.

The application stores the key to the user's safehouse (a protected resource) and uses JWT authentication to verify their identity. The application shows the user a welcome page, where they can sign in with a username and password. It generates a JWT for the user, which they can use to verify their identity. Once signed in, users will see their safehouse's secret key by exchanging the JWT with the server.

Before you begin, you'll need a code editor like [Visual Studio Code](https://code.visualstudio.com/download). You'll also need Node.js (version 16 or newer) and npm installed. If you want to check out the completed application, you can clone this [GitHub repository](https://github.com/Anshuman71/clerk-jwt-example).

### Setting Up the Project

To set up a Next.js project, run the following command:

```bash
npx create-next-app clerk-jwt-example
```

You'll be prompted on whether you'd like to use TypeScript and ESLint. For simplicity, choose `No` for TypeScript and then `Yes` for ESLint.

After you complete the npm installation, open the project in your code editor and change the directory to the project by running `cd clerk-jwt-example` in your terminal.

To use the browser's default styling, remove all existing styles from `styles/globals.css` and `styles/Home.module.css`.

### JWT Authentication Using a Standard Flow

In this example, you'll create two pages: `/jwt-home` and `jwt-safehouse`. The former will be the [login page](/blog/building-a-react-login-page-template) to collect credentials, and the latter will be the secured page showing secret information.

More specifically, the `/jwt-home` page accepts the user credentials and requests the `/api/auth` API endpoint to generate the signed JWT. The application stores the returned JWT in localStorage as the `jwt-token` key. The `/jwt-safehouse` acts as the secured page and requests the secret information from the `/api/safehouse` API endpoint in exchange for the signed JWT. The `/jwt-safehouse` page then displays the secret information to the signed-in user.

In Next.js, you can create a new application route by creating a new file with the route name under the `pages/` folder. Similarly, to create a new API endpoint, you need to create a new file under the `pages/api/` folder.

#### Update the Application Home Page

To access different parts of your application, update the application home page (`pages/index.js`) to show links to other pages in the application. The code below uses the `Link` component from `next/link`, which is the Next.js version of the `<a>` tag:

```jsx
import Link from 'next/link'

export default function Home() {
  return (
    <div>
      Home
      <br />
      <ol>
        <li>
          <Link href={'/jwt-home'}>JWT Home</Link>
        </li>
        <li>
          <Link href={'/jwt-safehouse'}>JWT Safe house</Link>
        </li>
      </ol>
    </div>
  )
}
```

Now start the application by running `npm run dev` in the terminal. Open `http://localhost:3000` in a web browser to see the application. You'll see the page, as shown below.

![Initial layout](./16fed00772a7f2c1491216696a6e9303ee7a7121-1606x900.png)

#### Create a Signed JWT

To create a signed JWT, you first need to install the `jsonwebtoken` package. `jsonwebtoken` provides utilities to sign and verify JWTs. Run `npm i jsonwebtoken` to install the package in your project.

You'll need a JWT signing secret to use with `jsonwebtoken`. For this, create a new file, `.env.local`, to store the application's secret credentials. In this file, add a new environment variable, `DIY_JWT_SECRET`, with a random hash string as a value:

```txt
DIY_JWT_SECRET=2182312c81187ab82bbe053df6b7aa55
```

To generate the signed JWT with the user's `signInTime` and `username`, create an API route `/api/auth` by creating the new file `pages/api/auth.js`. The API route accepts the user credentials, and if the provided password is `pikachu`, it returns a `200` response with the signed JWT. Otherwise, it returns a `401` response with an error message:

```js
import jwt from 'jsonwebtoken'

export default function handler(req, res) {
  const jwtSecretKey = process.env.DIY_JWT_SECRET
  const { username, password } = req.body
  // confirm if password is valid
  if (password !== 'pikachu') {
    return res.status(401).json({ message: 'Invalid password' })
  }
  let data = {
    signInTime: Date.now(),
    username,
  }

  const token = jwt.sign(data, jwtSecretKey)
  res.status(200).json({ message: 'success', token })
}
```

#### Create a Login with JWT

Now that the `/api/auth` API endpoint is ready, create the new file `pages/jwt-home.jsx` and implement a login form component to send user credentials to `/api/auth`.

The code below implements a React component, `Home`, that displays a form to collect the user credentials and, on form submission, makes an HTTP POST request to the `/api/auth` endpoint with the collected credentials.

If the response message is `success`, it saves the received JWT in localStorage under the `jwt-token` key. Otherwise, it shows a browser alert with the response message:

```jsx
import { useState } from 'react'
import { useRouter } from 'next/router'

export default function Home() {
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const router = useRouter()

  function submitUser(event) {
    event.preventDefault()
    fetch('/api/auth', {
      method: 'POST',
      headers: {
        'content-type': 'application/json',
      },
      body: JSON.stringify({ username, password }),
    })
      .then((res) => res.json())
      .then((data) => {
        if (data.message === 'success') {
          localStorage.setItem('jwt-token', data.token)
          setUsername('')
          setPassword('')
          router.push('/jwt-safehouse')
        } else {
          alert(data.message)
        }
      })
  }
  return (
    <>
      <main style={{ padding: '50px' }}>
        <h1>Login </h1>
        <br />

        <form onSubmit={submitUser}>
          <input
            value={username}
            type="text"
            placeholder="Username"
            onChange={(e) => setUsername(e.target.value)}
          />
          <br />
          <br />

          <input
            value={password}
            type="password"
            placeholder="Password"
            onChange={(e) => setPassword(e.target.value)}
          />
          <br />
          <br />

          <button type="submit">Login</button>
        </form>
      </main>
    </>
  )
}
```

![JWT flow login page](./63ecc4b12a117163fbd6f89f7b2eaba5c5cd44e9-1604x900.png)

#### Exchange the JWT for the Secret Data

The next step is to implement an API endpoint to verify the JWT from the incoming request header. If it's valid, the endpoint should return a `200` response with the secret data; otherwise, it will return a `401` response with an error message.

Create a new file, `pages/api/safehouse.js`. In this file, copy and paste the following code to verify the incoming JWT from the `jwt-token` request header:

```js
import jwt from 'jsonwebtoken'

export default function handler(req, res) {
  const tokenHeaderKey = 'jwt-token'
  const jwtSecretKey = process.env.DIY_JWT_SECRET
  const token = req.headers[tokenHeaderKey]
  try {
    const verified = jwt.verify(token, jwtSecretKey)
    if (verified) {
      return res.status(200).json({ safehouseKey: 'under-the-doormat', message: 'success' })
    } else {
      // Access Denied
      return res.status(401).json({ message: 'error' })
    }
  } catch (error) {
    // Access Denied
    return res.status(401).json({ message: 'error' })
  }
}
```

#### Display the Safehouse Secret Data

The final step in the flow is to request the secret data from the `/api/safehouse` API endpoint and display it if the JWT is valid.

To show the secret safehouse data, create the new file `pages/jwt-safehouse.jsx` with the following code:

```jsx
import { useEffect, useState } from 'react'
import Link from 'next/link'

export default function SafeHouse() {
  const [token, setToken] = useState('')
  const [userData, setUserData] = useState({})

  useEffect(() => {
    const token = localStorage.getItem('jwt-token')
    setToken(token)
    fetch('/api/safehouse', {
      headers: {
        'jwt-token': token,
      },
    })
      .then((res) => res.json())
      .then((data) => setUserData(data))
  }, [])

  function logout() {
    setToken('')
    localStorage.removeItem('jwt-token')
  }

  if (!token) {
    return (
      <>
        <main style={{ padding: '50px' }}>
          <p>You&apos;re not logged in.</p>
          <Link href={'/jwt-home'}>Home</Link>
        </main>
      </>
    )
  }

  return (
    <>
      <main style={{ padding: '50px' }}>
        <h1>Safehouse </h1>
        <p>
          You Safehouse key is <strong>{userData?.safehouseKey || 'Loading...'}</strong>
        </p>
        <button onClick={logout}>Logout</button>
      </main>
    </>
  )
}
```

The above code implements a `SafeHouse` component that renders the secret data if the JWT is available in localStorage. Otherwise, it prompts the user to log in with a link to the `/jwt-home` page.

The component gets the `jwt-token` from localStorage and makes a `fetch` request to the `/api/safehouse` in the `useEffect` hook that runs on the initial render in the browser.

The `Logout` button triggers the `logout()` function that clears the `token` state variable and removes the localStorage item.

The standard JWT authentication flow is ready.

Note that the solution you implemented above is very naive for a number of reasons. First, to make this system work, you'll need to implement and maintain additional code to track any updates to the JWT and pass the JWT in the request headers.

Next, you can't invalidate the stored JWT from outside the user's browser, which is a critical security issue—if a user's account is suspended or deleted, a JWT issued before that action would still be valid and could be used to authenticate as that user.

Further, if a user's password is changed, a JWT that was issued before the password change would still be valid and could be used to authenticate as the user with the old password.

### Authentication Using Clerk

By using the [Clerk](/) SDK, you can overcome the limitations discussed above. In the following section, you'll find the steps to implement a more secure and scalable solution for your JWT authentication while retaining the same functionality.

#### Set Up the Clerk SDK

Below are the steps to setting up the Clerk SDK:

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

2. On your [Clerk dashboard](https://dashboard.clerk.com), click `Add application` to create a new application.

3. In the Application name field, type in "JWT Example" and click `Finish`.

   ![Create new Clerk application](./9bc39e68dcb1236d17db7bf4602b43485385313c-2520x1816.png)

4. On the application dashboard, click on `API Keys` in the left navigation. Then copy the `Frontend API key`, `Backend API key`, and `JWT verification key`.

   ![Copy Clerk credentials](./5eb8d5a378ea0897a7c10b8581d0b9b8a4d7db8b-3154x1628.png)

5. Save the keys in the file `.env.local` inside your project:

   ```
   NEXT_PUBLIC_CLERK_FRONTEND_API=<frontend-key>
   CLERK_API_KEY=<backend-api-key>
   CLERK_JWT_KEY=<jwt-verification-key>
   ```

6. Install the Clerk SDK by running `npm i @clerk/nextjs` inside your project.

7. Add the `ClerkProvider` in the `pages/_app.js` file to use the authentication state throughout the application:

   ```jsx
   import { ClerkProvider } from '@clerk/nextjs'

   export default function App({ Component, pageProps }) {
     return (
       <ClerkProvider {...pageProps}>
         <Component {...pageProps} />
       </ClerkProvider>
     )
   }
   ```

#### Implement Sign In and Sign Up

With the Clerk SDK installed, you can easily set up your sign-in and sign-up pages.

*Note:* In Next.js, files named `pages/sign-in/[[...<anything>]].jsx` create a catch-all route that will match /sign-in, /sign-in/a, /sign-in/a/b, and so on.

For the sign-in page, create the new file `pages/sign-in/[[...index]].jsx` and use the prebuilt `<SignIn>` component from `@clerk/nextjs`:

```jsx
import { SignIn } from '@clerk/nextjs'

export default function SignInPage() {
  return <SignIn path="/sign-in" routing="path" signUpUrl="/sign-up" />
}
```

For the sign-up page, create the new file `pages/sign-up/[[...index]].jsx` and use the prebuilt `<SignUp>` component from `@clerk/nextjs`:

```jsx
import { SignUp } from '@clerk/nextjs'

export default function SignUpPage() {
  return <SignUp path="/sign-up" routing="path" signInUrl="/sign-in" />
}
```

#### Fetch the Secret Data from the API

To use the Clerk SDK with the API endpoints, you must create the file `middleware.js` at the project root with the following code:

```js
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: '/((?!.*\\.).*)' }
```

To create the API endpoint `/api/clerk-safehouse`, create a new file, `pages/api/clerk-safehouse.js`. If the user is signed in, the API handler returns a `200` response with the `safehouseKey`. Otherwise, it returns a `401` response with an error message.

This API handler function uses the `getAuth` utility function from `@clerk/nextjs/server` to get the user's authentication state on the server:

```jsx
import { getAuth } from '@clerk/nextjs/server'

export default async function handler(req, res) {
  try {
    const { userId } = getAuth(req)
    if (!userId) {
      return res.status(401).json({ message: 'error' })
    }
    return res.status(200).json({ safehouseKey: 'under-the-doormat', message: 'success' })
  } catch (err) {
    return res.status(401).json({ message: 'error' })
  }
}
```

#### Display the Secret Data

To display the data from the `/api/clerk-safehouse` API endpoint, create the new file `pages/safehouse.jsx`.

In this file, create a `SafeHouse` component that uses the `useUser` hook from `@clerk/nextjs` to get the authentication state. If the user isn't signed in, it returns the prebuilt component `<RedirectToSignIn>` from `@clerk/nextjs` that redirects the user to the `/sign-in` page.

However, if the user is signed in, it'll display the `safehouseKey` fetched from the API call to the `/api/clerk-safehouse` endpoint. It also returns the `<SignOutButton>` that the user can click to sign out of the application:

```jsx
import { useEffect, useState } from 'react'

import { SignOutButton, RedirectToSignIn, useUser } from '@clerk/nextjs'

export default function SafeHouse() {
  const { isSignedIn } = useUser()
  const [userData, setUserData] = useState({})

  useEffect(() => {
    fetch('/api/clerk-safehouse')
      .then((res) => res.json())
      .then((data) => setUserData(data))
  }, [])

  if (!isSignedIn) {
    return <RedirectToSignIn />
  }

  return (
    <>
      <main style={{ padding: '50px' }}>
        <h1>Safehouse </h1>
        <p>
          You Safehouse key is <strong>{userData?.safehouseKey || 'Loading...'}</strong>
        </p>
        <SignOutButton />
      </main>
    </>
  )
}
```

#### Update Application Home Page

Finally, update the application home page (`pages/index.js`) to include the new `/safehouse` link in the list:

```jsx
import Link from 'next/link'

export default function Home() {
  return (
    <div>
      Home
      <br />
      <ol>
        <li>
          <Link href={'/jwt-home'}>JWT Home</Link>
        </li>
        <li>
          <Link href={'/jwt-safehouse'}>JWT Safe house</Link>
        </li>
        <li>
          <Link href={'/safehouse'}>Clerk Safe house</Link>
        </li>
      </ol>
    </div>
  )
}
```

Your React application is ready with end-to-end authentication.

### Traditional JWT Authentication vs. Clerk

Now that you've implemented authentication in your React application using the traditional JWT flow and with Clerk, you can see how easy it is to implement a full-fledged authentication using the latter approach.

In the do-it-yourself JWT approach, all responsibilities regarding authentication—such as storing the password, verifying user identity, and crafting a beautiful user experience—fall on your shoulders.

Clerk lifts this burden by offering a full-stack solution for managing user authentication. It not only provides easy integrations on the frontend with prebuilt components but also authentication utilities for the backend API routes. With Clerk, you don't have to worry about password management, user session management, or signing and storing the JWT. It's all managed for you automatically.

Apart from its simplicity, the Clerk SDK also uses short-lived JWTs and HttpOnly cookies to provide an additional layer of security for your application. While short-lived JWTs help to protect against replay attacks and limit the window of opportunity for an attacker to use a compromised token, HttpOnly cookies help to protect against XSS attacks.

## Conclusion

In this article, you've successfully set up JWT authentication in a React application. While doing so, you learned more about JWT authentication and how to overcome some of its challenges. In particular, you saw how using a solution like Clerk can tremendously simplify JWT authentication in React and make the process more secure at the same time.

Clerk is a one-stop solution for authentication and customer identity management. It can help you build a flawless user authentication flow that supports login with password, multifactor authentication, and social logins with providers like Google, LinkedIn, Facebook, GitHub, and many more.

Clerk provides beautiful components ready to plug into your application and build the authentication flow in no time. Sign up to try [Clerk](https://dashboard.clerk.com/sign-up) today.

---

# 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).

---

# Clerk raises $15m Series A led by Madrona
URL: https://clerk.com/blog/series-a.md
Date: 2023-03-22
Category: Company
Description: Clerk surpasses a million managed users and taps into executive experience from Auth0 and Vercel

Today, we're excited to announce that Clerk has raised a $15 million Series A led by Madrona, just a few months after [our seed](/blog/a16z-seed). We're especially thrilled that [Karan Mehandru](https://www.madrona.com/team-profiles/mehandru-karan) has joined our board, who has tremendous experience in our industry from his time on Auth0's board.

More exciting than fundraising, though, is that Clerk is growing – **and fast:**

![Thumbnail: Clerk raises $15m Series A led by Madrona guide](./5715c0ca9de562c76bb02376aa303bbccc6aee99-1902x702.png)

Our growth accelerated in the new year as word-of-mouth and referrals became our #1 source of new customers. Here is some of the incredible enthusiasm developers are sharing on X:

![Thumbnail: Clerk raises $15m Series A led by Madrona guide](./8bb2940b16b1d504e1be0486ac3aa316d178acca-2358x924.png)

We're so grateful for our early adopters who helped hone Clerk into a streamlined solution – **and then told their friends!** Without them, we simply wouldn't be here today.

Of course, our work is far from done. Throughout the year we'll continue launching new authentication features, like SAML SSO, passkeys, and support for more frameworks.

We're also eager to begin helping developers with *authorization*. We'll expand customer profiles to include information about Roles and Permissions, as well as Billing and Entitlements. We'll solve authorization through components and hooks, same as we did authentication.

As always, if there's anything in particular you'd like to see from Clerk, or if you have feedback or suggestions, we'd love to hear from you. Join our [community discord](https://clerk.com/discord) or tweet at [@clerk](https://x.com/clerk) – we're listening and eager to improve.

### Press Release

**Clerk raises $15 million for React authentication and user management**

Clerk, the drop-in authentication and user management solution for React, today announced a $15 million Series A led by Madrona, with managing director Karan Mehandru joining its board. Mehandru brings a deep understanding of the space from his years on the board of Auth0. Other new investors include Vercel's CEO Guillermo Rauch, Mango Capital, and Auth0's former CRO Dave Wilner. Existing investors Andreessen Horowitz, S28 Capital, and Fathom Capital also participated.

*"The response from React and Next.js developers has been incredible. Monthly active users have grown 500% in the past 5 months, and we've crossed a million managed users,"* said co-founder and CEO, Colin Sidoti. *"When we met Karan, we were excited to tap into his experience in identity and in scaling go-to-market as we target the next generation of application development."*

React and frameworks like Next.js have sparked an architecture shift that will propagate across all application development, and this new architecture requires a tailored suite of developer tools. Hosting and database technologies have already evolved, but before Clerk, authentication was left to be solved in-house.

*“Clerk is the Stripe Checkout of authentication and user management, except it’s built for React,"* said Rauch, who also authors Next.js. *"The best practices built-in to their `<SignIn/>` and `<UserProfile/>` components would take months to implement in-house, yet no sacrifice is made in terms of Enterprise extensibility or customization to your brand.”*

With this new funding, Clerk will accelerate its roadmap beyond authentication. It aims to help developers with authorization, which requires knowledge of a user's role and permissions, as well as their billing plan and entitlements. Clerk will provide the glue that binds these systems together, while also empowering React developers to build authorization controls for their end-users.

*"Clerk is a foundational technology company dedicated entirely to serving the needs of the next generation of application developers as the authentication industry migrates from back-end APIs to front-end componentized modules,"* said Mehandru. *"As this market evolves, Clerk is extremely well positioned to be the "system of action" and the "system of record" for customer identities, much like what Auth0 accomplished in the last decade. I am excited to partner with Colin, his brother and cofounder Braden, and the Clerk team as they empower the developers of the future and build an enduring and exciting company over the next decade and beyond."*

Clerk is actively hiring across product and engineering roles. Please visit [clerk.com/careers](/careers) for more information.

---

# Refactoring our frontend API key: Familiar DX is the best DX
URL: https://clerk.com/blog/refactoring-our-api-keys.md
Date: 2023-01-27
Category: Engineering
Description: We switched to the familiar Publishable Key, but we changed less than you'd think

Like most other developer tools, Clerk's SDKs are configured with two "keys," one for the backend and one for the frontend.

And we share the same core requirements:

- The backend key must have significantly random so it cannot be guessed
- The frontend key is public, so it only needs to be a unique identifier

Although there's no security benefit in doing so, many tools have their frontend key mirror the format and length of their backend key. Take Stripe, for example:

!\[Although there's no security benefit in doing so, many tools have their frontend key mirror the format and length of their backend key. Take Stripe, for example: screenshot]\(./995856b7b27f199531ec648ab53d2866eaeae372-814x332.png '(Don't worry, the secret key has been rolled.)

But as an authentication company, Clerk has an extra requirement for our frontend key, and it meant that mirroring our secret key would cause *performance* issues.

Wait, what? How could a key cause performance issues?

The purpose of a frontend key is to be a unique identifier when interacting with a frontend-facing API. Here's an example of how Stripe's SDK uses the publishable key:

![The purpose of a frontend key is to be a unique identifier when interacting with a frontend-facing API. Here's an example of how Stripe's SDK uses the publishable key: screenshot](./6de4356a8cc28037f37729a941cdfb6e483ce6ef-689x175.png "That's the same publishable key as above!")

Notice how this request is being sent to a **stripe.com** domain? Stripe SDKs always make requests to **stripe.com**, even if you're embedding their elements into your own website.

But since Clerk runs an authentication API and since we're responsible for maintaining sessions, we can't securely do the same. We need to set [HttpOnly cookies](https://owasp.org/www-community/HttpOnly) from a first-party context, which means our API needs to be accessible through our customers' domains. *(Developers configure this by setting a CNAME in their DNS records.)*

When we launched, our frontend key was simply the hostname where our frontend API is hosted. Developers configured it like this in their React apps:

```jsx {{ prettier: false }}
<ClerkProvider frontendApi="clerk.example.com">
```

By passing the API hostname directly, we avoided making an extra, waterfalled API request to exchange a traditional random key with the hostname. This led to faster overall loading speeds.

But we hit an unexpected problem with this strategy: it *really* confused developers. It was a common complaint in friction logs, and when we watched developers integrate Clerk we could see the confusion wash over their face.

A hostname as a frontend key is completely unfamiliar, and no matter what we tried with design and naming, we couldn't get over the hurdle.

So this week, we finally threw in the towel. Our new frontend API keys look just like Stripes:

![So this week, we finally threw in the towel. Our new frontend API keys look just like Stripes: screenshot](./483632fdf53ea7aa1f455e10d9ca7faa463384e5-1006x197.png "Clerk's new publishable key")

But we refuse to exchange developer experience for performance, so there's a not-so-secret subtlety to our new publishable key. Take a closer look:

`pk_test_Y2xlcmsuZXhhbXBsZS5jb20k`

Now, base64-decode the part after `pk_test_`:

`clerk.example.com$`

Indeed, we just base64-encoded the old value and started calling it a publishable key. We added a $ as a simple stop character so we can detect when keys are malformed.

As a final step, we changed the prop name for React:

```jsx {{ prettier: false }}
<ClerkProvider publishableKey="pk_test_Y2xlcmsuZXhhbXBsZS5jb20k">
```

Quick, dirty, and a little silly – but it works! We haven't sacrificed performance and our new publishable key feels much more familiar. Developers have stopped raising their eyebrows and breeze through initial setup.

---

# 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.