# Clerk Blog — Page 11

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

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

## Exploring the Starter App

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## Implementing AuthContext

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

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

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

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

```javascript
import Axios from 'axios'

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

export default api
```

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

Create the file `auth_context.js`:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

```bash
yarn add formik yup
```

Create `pages/login.js`:

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

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

export default LoginForm
```

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

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

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

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

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

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

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

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

export default MyApp
```

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

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

## Authentication with Clerk

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

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

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

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

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

Install the required library:

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

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

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

const publicPages = ['/']

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

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

export default MyApp
```

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## Conclusion

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

---

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

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

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

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

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

## Implementing API Routes in Next.js

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

First, create a Next.js app:

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

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

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

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

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

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

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

## Basics of API Routes

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

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

The function receives two arguments:

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

Before proceeding, keep these two things in mind:

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

### Static Routes

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

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

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

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

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

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

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

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

```

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

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

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

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

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

```

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

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

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

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

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

```

### Dynamic Routes

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

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

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

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

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

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

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

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

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

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

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

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

```

### Nested Routes

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

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

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

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

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

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

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

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

### Catch-All Routes

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

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

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

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

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

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

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

You can test this route with zero or more parameters:

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

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

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

```

## Adding JWT Authentication

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

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

```sh
JWT_SECRET_KEY = mysecret
```

This key will be used to sign the JWT, so in an actual application, this should be a random string and kept secret.

Next, open `data.js` and add a `password` key to all the users. For simplicity, add the same password to all the users:

```
password: '$2y$10$mj1OMFvVmGAR4gEEXZGtA.R5wYWBZTis72hSXzpxEs.QoXT3ifKSq' // Add this key to all users
```

The value in quotes is the hashed version of the string "password".

Next, create `auth.js` inside `pages/api`. This file will log the user in and generate the token. Start with the necessary imports:

```jsx
import { users } from '../../data'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'

const JWT_KEY = process.env.JWT_SECRET_KEY
```

Ensure that only the `POST` method is allowed:

```jsx
// ...
export default async function handler(req, res) {
  if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })
}
```

The next step is to extract the username and password from the body and ensure that a user with the username exists:

```jsx
const { username, password } = req.body

if (!username || !password)
  return res.status(400).json({ error: 'Username and password are required' })

const user = users.find((user) => {
  return user.username === username
})

if (!user) return res.status(404).json({ error: 'User not found ' })
```

Then, use `bcrypt` to compare the password in the request with the actual password:

```jsx
const { password: userPassword, id, location, name } = user
const match = await bcrypt.compare(password, userPassword)
if (!match) return res.status(401).json({ error: 'Wrong password' })
```

If the passwords are a match, sign and send the JWT:

```jsx
const payload = { userId: id, location, name }

jwt.sign(payload, JWT_KEY, { expiresIn: 24 * 3600 }, (err, token) => {
  res.status(200).json({ token })
})
```

The entire file should look like this:

```jsx
import { users } from '../../data'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'

const JWT_KEY = process.env.JWT_SECRET_KEY

export default async function handler(req, res) {
  if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })

  const { username, password } = req.body
  if (!username || !password)
    return res.status(400).json({ error: 'Username and password are required' })

  const user = users.find((user) => {
    return user.username === username
  })

  if (!user) return res.status(404).json({ error: 'User not found ' })

  const { password: userPassword, id, location, name } = user
  const match = await bcrypt.compare(password, userPassword)
  if (!match) return res.status(401).json({ error: 'Wrong password' })

  const payload = { userId: id, location, name }
  jwt.sign(payload, JWT_KEY, { expiresIn: 24 * 3600 }, (err, token) => {
    res.status(200).json({ token })
  })
}
```

Let's test this route. Start the server with yarn dev and send a request to `localhost:3000/api/auth`:

```sh
$ curl -X POST "<http://localhost:3000/api/auth>" -d '{"username": "bob", "password": "password"}' -H 'Content-Type: application/json'
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImxvY2F0aW9uIjoiVVNBIiwibmFtZSI6IkJvYiIsImlhdCI6MTY2OTEwMDI3OCwiZXhwIjoxNjY5MTg2Njc4fQ.0EFxEtqR2-rZij-PqD66bWatC_kiMl6QDpNlaqyjaLQ"}

```

Note that you'll likely get a different token.

You can now use this token to check the authenticity of the user. Let's protect the `/api/users` route with JWT. Replace the content in **pages/api/users/index.js** with the following:

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

const JWT_KEY = process.env.JWT_SECRET_KEY

export default function handler(req, res) {
  const { authorization } = req.headers

  if (!authorization) return res.status(401).json({ error: 'The authorization header is required' })
  const token = authorization.split(' ')[1]

  jwt.verify(token, JWT_KEY, (err, payload) => {
    if (err) return res.status(401).json({ error: 'Unauthorized' })
    return res.status(200).json(
      users.map((user) => {
        return { ...user, password: '' }
      }),
    )
  })
}
```

The above code checks the `Authorization` header for the JWT. If a token is passed, the `jwt.verify` function is invoked to check the token's authenticity. Once authenticated, the data is returned (with the password field stripped from the users—you wouldn't want to expose the passwords, would you?).

Test this route by passing the `Authorization` header to the request:

```sh
$ curl <http://localhost:3000/api/users> -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImxvY2F0aW9uIjoiVVNBIiwibmFtZSI6IkJvYiIsImlhdCI6MTY2OTEwMDI3OCwiZXhwIjoxNjY5MTg2Njc4fQ.0EFxEtqR2-rZij-PqD66bWatC_kiMl6QDpNlaqyjaLQ" # Replace with your token
[{"id":1,"username":"bob","name":"Bob","location":"USA","password":""},{"id":2,"username":"alice","name":"Alice","location":"Sweden","password":""},{"id":3,"username":"john","name":"John","location":"France","password":""}]

```

An invalid token will raise the following error:

```sh
$ curl <http://localhost:3000/api/users> -H "Authorization: Bearer: invalid"
{"error":"Unauthorized"}
```

As you can see, adding JWT authentication to API routes is an involved process that can be complicated. Using something like Clerk’s [Next.js authentication solution](/nextjs-authentication) makes the process much easier since it does the heavy lifting of authentication, taking the task off your plate.

With Clerk, authentication is as simple as importing the `getAuth` function:

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

Calling it inside the handler function is also easy, which will automatically authenticate the user and return the user ID:

```jsx
const { userId } = getAuth(req)
```

You'll learn more about authentication with Clerk in part two of this series.

## Conclusion

Next.js API routes offer extreme flexibility in keeping your server-side logic close to the frontend and creating an API application. With the many different types of API routes available, it's critical to implement proper authentication to protect the routes from bad actors. However, adding authentication can be a complex and daunting task. This is why solutions like [Clerk](/) exist to make it as easy and seamless as possible.

---

# Clerk and Create T3 Turbo
URL: https://clerk.com/blog/clerk-t3-turbo.md
Date: 2022-12-28
Category: Guides
Description: This guide shows you how to integrate Clerk into T3-Turbo so you can have user management for everyone.

T3-Turbo is one of the easiest ways to get both Type safety while using Next.js and Expo. The biggest missing feature is the ability to share authentication between your applications.

This guide shows you how to integrate Clerk into T3-Turbo so you can have user management for everyone.

> For comprehensive Expo authentication without the T3 stack, [learn more about our Expo support](/expo-authentication).

If you don’t want to do this manually, use the [starter repo](https://github.com/clerkinc/t3-turbo-and-clerk). It is
open source and free.

## Assumptions

There are a few assumptions here when working through this guide.

- You understand TRPC and its functionality.
- You are familiar with Expo.
- You have a working knowledge of Turborepo

## Setup

### Create your free Clerk account

You need a free Clerk account to use everything in this guide, so head to [https://dashboard.clerk.com](https://dashboard.clerk.com) and sign up for your free account.

### Create a new application in the dashboard

You will need to create a new application, name it and select Discord as a social sign-in.

If you change any setting here, you may need to update your Expo code to handle any requirements you change.

![Clerk T3 Turbo guide illustration](./033608f71ab9631e79b9c3569e92bb808e6dc213-3918x1924.png)

###

![Clerk T3 Turbo guide illustration](./c00fd14484c9b3f888f03d00f543923351f66a34-3920x2244.png)

### Update .env to use your keys

Under the dashboard, you will need your API keys and create a copy of the `.env.example` as `.env`

![Clerk T3 Turbo guide illustration](./f244212d6116858dbef13ee31ecf14af91fd759e-3914x2182.png)

## Adding global env to Turbo

We want to have our env available in many parts of our application. You can add the following to our `turbo.json` .

```json {{ prettier: false }}
"globalEnv": [
  "DATABASE_URL",
  "NEXT_PUBLIC_CLERK_FRONTEND_API",
  "CLERK_API_KEY",
  "CLERK_JWT_KEY"
]
```

###

Update Next.js package.json

We need to be able to access the .env when working in development, so replace the dev script with the following:

```json {{ prettier: false }}
"with-env": "dotenv -e ../../.env --",
"dev": "pnpm with-env next dev",
```

##

## Updating our Next.js application

First, we will work on our Next.js application, whose only change is [adding Clerk](/nextjs-authentication), so we have powerful user authentication.

### Install

```bash
pnpm install @clerk/nextjs --filter @acme/nextjs
```

Now that the Clerk package has been installed in our Next.js application, we need to wrap our application in the `<ClerkProvider>`, which gives us access to the authentication state throughout our application.

Open up your `_app.tsx` file and modify the code.

```tsx
import '../styles/globals.css'
import type { AppType } from 'next/app'
import { ClerkProvider } from '@clerk/nextjs'
import { trpc } from '../utils/trpc'

const MyApp: AppType = ({ Component, pageProps: { ...pageProps } }) => {
  return (
    <ClerkProvider {...pageProps}>
      <Component {...pageProps} />
    </ClerkProvider>
  )
}

export default trpc.withTRPC(MyApp)
```

## Add Middleware.ts

Clerk uses Next.js middleware to allow your application to keep track of authentication behind the scenes.

```tsx
import { withClerkMiddleware } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export default withClerkMiddleware((_req: NextRequest) => {
  return NextResponse.next()
})

// Stop Middleware running on static files
export const config = {
  matcher: [
    /*
     * Match request paths except for the ones starting with:
     * - _next
     * - static (static files)
     * - favicon.ico (favicon file)
     *
     * This includes images, and requests from TRPC.
     */
    '/(.*?trpc.*?|(?!static|.*\\..*|_next|favicon.ico).*)',
  ],
}
```

You will notice the matcher at the bottom, which ensures that middleware doesn’t run on every request. This will scope it to TRPC + API routes leaving your images and static files alone.

## Embedding our UI components

Clerk provides highly customizable components from Sign-up to Organization management. They require zero form creation or state management, making them easy to implement. Each component will use the [Next.js optional catch all route](https://nextjs.org/docs/routing/dynamic-routes#optional-catch-all-routes). This allows you to redirect the user inside your application using OAuth providers.

### Sign in

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

const SignInPage = () => (
  <main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
    <div className="flex flex-col items-center justify-center gap-4">
      <div className="container flex flex-col items-center justify-center gap-12 px-4 py-8">
        <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">Sign In</h1>
        <SignIn path="/sign-in" routing="path" signUpUrl="/sign-up" />
      </div>
    </div>
  </main>
)

export default SignInPage
```

### Sign up

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

const SignUpPage = () => (
  <main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
    <div className="flex flex-col items-center justify-center gap-4">
      <div className="container flex flex-col items-center justify-center gap-12 px-4 py-8">
        <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">Sign In</h1>
        <SignUp path="/sign-up" routing="path" signInUrl="/sign-in" />
      </div>
    </div>
  </main>
)

export default SignUpPage
```

### Updating index.tsx

The final step for Next.js is to update our `index.tsx` to use Clerk. Once we update this page, users will have a way to sign in, sign out and see data from TRPC in the future.

We need to import a prebuilt component from Clerk and a hook that allow us to access the current auth state.

`import { useAuth, UserButton } from "@clerk/nextjs";`

### What is useAuth?

The `useAuth` hook is a convenient way to access the current auth state. This hook provides the minimal information needed for data-loading, such as the user id and helper methods to manage the current active session.

### What is UserButton?

Initially popularized by Google, users have come to expect that little photo of themselves in the top-right of the page – it’s the access point to manage their account, switch accounts, or sign out.

The `<UserButton/>` component renders this familiar user button UI. It renders a clickable user avatar - when clicked, the full UI opens as a popup. Here is an example

![Clerk T3 Turbo guide illustration](./12da04075590eb1282144bf1b8ede1a59a634988-942x1052.png)

### Updating AuthShowcase

The `AuthShowCase` component in the `index.tsx` file needs to be updated to use the `useAuth()` hook, allow the user to sign in, and show our UserButton if the user is signed in.

```tsx {{ prettier: false }}
const AuthShowcase: React.FC = () => {
  const { isSignedIn } = useAuth()
```

Now we can update our secret message from `{ enabled: !!session?.user }` to `{ enabled: isSignedIn }`

```tsx {{ prettier: false }}
const AuthShowcase: React.FC = () => {
  const { isSignedIn } = useAuth()
  const { data: secretMessage } = trpc.auth.getSecretMessage.useQuery(
    undefined,
    { enabled: isSignedIn },
  )
```

Now the final change is to use `isSignedIn` in our return statement to conditionally show the secret message and UserButton component or show a sign-in link. We can do that by replacing `{session?.user && (` with `isSignedIn` and underneath, providing the false statement using `!isSignedIn` this is where we can place a Link to our mounted `/sign-in page`.

```jsx
{
  isSignedIn && (
    <>
      <p className="text-center text-2xl text-white">
        {secretMessage && (
          <span>
            {' '}
            {secretMessage} click the user button!
            <br />
          </span>
        )}
      </p>
      <div className="flex items-center justify-center">
        <UserButton
          appearance={{
            elements: {
              userButtonAvatarBox: {
                width: '3rem',
                height: '3rem',
              },
            },
          }}
        />
      </div>
    </>
  )
}
```

The `UserButton` component allows users to manage their accounts, including signing out or updating their profile and password or linking a new account through OAuth providers. I added some customization to make the UserButton larger.

To learn more about customization, go to our documentation where we explain how to use the [appearance
prop](/docs/component-customization/appearance-prop)

The final step is to add a login text that pushes the user to the mounted sign-in page.

```jsx
{
  !isSignedIn && (
    <p className="text-center text-2xl text-white">
      <Link href="/sign-in">Sign In</Link>
    </p>
  )
}
```

Below is the final AuthShowcase.

```tsx
const AuthShowcase: React.FC = () => {
  const { isSignedIn } = useAuth()
  const { data: secretMessage } = trpc.auth.getSecretMessage.useQuery(undefined, {
    enabled: !!isSignedIn,
  })

  return (
    <div className="flex flex-col items-center justify-center gap-4">
      {isSignedIn && (
        <>
          <p className="text-center text-2xl text-white">
            {secretMessage && (
              <span>
                {' '}
                {secretMessage} click the user button!
                <br />
              </span>
            )}
          </p>
          <div className="flex items-center justify-center">
            <UserButton
              appearance={{
                elements: {
                  userButtonAvatarBox: {
                    width: '3rem',
                    height: '3rem',
                  },
                },
              }}
            />
          </div>
        </>
      )}
      {!isSignedIn && (
        <p className="text-center text-2xl text-white">
          <Link href="/sign-in">Sign In</Link>
        </p>
      )}
    </div>
  )
}
```

Now that the Next.js work is done, we should update our TRPC API to use Clerk instead of NextAuth, so we can test this work and get ready to update Expo.

## Updating API package to use Clerk

Currently, the API package has TRPC context, and middleware uses Auth.js (previously NextAuth). We can replace this with Clerk so we can use it both with Expo and Next.js.

You can delete the Auth package in the packages folder completely and update the Prisma schema to remove the user
data. None of this is needed to use Clerk makes sure you remove any references if you do this

### Updating TRPC context

The context is found at `packages/api/src/context.ts`. In this package, we will add the ability to detect the user being signed in and retrieve the full User object. First, we must remove the auth package import and add `getAuth` , `clerkClient`, `SignedInAuthObject` and `SignedOutAuthObject` as a type.

```tsx {{ del: [1], ins: [2, 3] }}
import { getServerSession, type Session } from '@acme/auth'
import { getAuth } from '@clerk/nextjs/server'
import type { SignedInAuthObject, SignedOutAuthObject } from '@clerk/nextjs/api'
```

### What is `getAuth` ?

The `getAuth()` helper retrieves the authentication state and can be used anywhere within a next.js server. It provides information needed for data-loading, such as the user id and can be used to protect your API routes.

### Updating `createContext` function

For the `createContext` function, we want to pass around the user object anywhere in our application. For this, we can create an async function called `getUser` that retrieves the `userId` and subsequently retrieves the user data.

```tsx
export const createContext = async (opts: CreateNextContextOptions) => {
  return await createContextInner({ auth: getAuth(opts.req) })
}
```

Now we can retrieve a user, and if not, we will return `null` we can pass this to our `createContextInner` in case you need it for testing without a request object.

```tsx
type AuthContextProps = {
  auth: SignedInAuthObject | SignedOutAuthObject
}
/** Use this helper for:
 *  - testing, where we dont have to Mock Next.js' req/res
 *  - trpc's `createSSGHelpers` where we don't have req/res
 * @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
 */
export const createContextInner = async ({ auth }: AuthContextProps) => {
  return {
    auth,
    prisma,
  }
}
```

## Updating TRPC middleware

The TRPC middleware found in `/packages/api/src/trpc.ts` needs a small update to the `isAuthed` function. The if statement becomes `!ctx.auth.userId`, and the return becomes `auth: ctx.auth`

```tsx
import { initTRPC, TRPCError } from '@trpc/server'
import { type Context } from './context'
import superjson from 'superjson'

const t = initTRPC.context<Context>().create({
  transformer: superjson,
  errorFormatter({ shape }) {
    return shape
  },
})

const isAuthed = t.middleware(({ next, ctx }) => {
  if (!ctx.auth.userId) {
    throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Not authenticated' })
  }
  return next({
    ctx: {
      auth: ctx.auth,
    },
  })
})

export const router = t.router
export const publicProcedure = t.procedure
export const protectedProcedure = t.procedure.use(isAuthed)
```

Our Next.js application can be tested with TRPC, including the secret message that uses protected routes. Give it a test.

## Updating our Expo application

The Expo application currently doesn’t support authentication; the good news is Clerk supports Expo with our `@clerk/expo` package.

### Install `@clerk/expo` package and secure-store

`pnpm install @clerk/clerk-expo expo-secure-store --filter @acme/expo`

### Create a Token Cache

We need a token cache here, which is why we installed `expo-secure-store` that allows you to store key pair values on the device. Create a new file under `/src/utils/` named `cache.ts` and paste in the following code:

```tsx
import * as SecureStore from 'expo-secure-store'
import { Platform } from 'react-native'

export async function saveToken(key: string, value: string) {
  // console.log("Save token", key, value);
  await SecureStore.setItemAsync(key, value)
}

export async function getToken(key: string) {
  const value = await SecureStore.getItemAsync(key)
  return value
}

// SecureStore is not supported on the web
// https://github.com/expo/expo/issues/7744#issuecomment-611093485
export const tokenCache =
  Platform.OS !== 'web'
    ? {
        getToken,
        saveToken,
      }
    : undefined
```

I won’t explain this code above as it’s an expo-specific package, but this allows us to store the JWT securely and not in memory.

### Add `<ClerkProvider>`

Similar to our Next.js application, we need to wrap up our `_app.tsx` in the `<ClerkProvider>` to allow access to auth state anywhere in the application. What is different here is we need use our newly created `TokenCache`, and we need to provide the Clerk frontend API directly to the `<ClerkProvider />`

```jsx
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { TRPCProvider } from './utils/trpc'

import { HomeScreen } from './screens/home'
import { ClerkProvider } from '@clerk/clerk-expo'
import { tokenCache } from './utils/cache'

// Find this in your Dashboard.
const clerk_frontend_api = 'FRONT_END_API'

export const App = () => {
  return (
    <ClerkProvider frontendApi={clerk_frontend_api} tokenCache={tokenCache}>
      <TRPCProvider>
        <SafeAreaProvider>
          <HomeScreen />
          <StatusBar />
        </SafeAreaProvider>
      </TRPCProvider>
    </ClerkProvider>
  )
}
```

### Protecting pages

Our Expo package provides an easy way to gate content using `SignedIn` and `SignedOut`, which will gate the content depending on the user's current state.

```jsx
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { TRPCProvider } from './utils/trpc'

import { HomeScreen } from './screens/home'
import { ClerkProvider, SignedIn, SignedOut } from '@clerk/clerk-expo'
import { tokenCache } from './utils/cache'

// Find this in your Dashboard.
const clerk_frontend_api = 'FRONT_END_API'

export const App = () => {
  return (
    <ClerkProvider frontendApi={clerk_frontend_api} tokenCache={tokenCache}>
      <SignedIn>
        <TRPCProvider>
          <SafeAreaProvider>
            <HomeScreen />
            <StatusBar />
          </SafeAreaProvider>
        </TRPCProvider>
      </SignedIn>
      <SignedOut></SignedOut>
    </ClerkProvider>
  )
}
```

## Implementing a way to sign in.

With Clerk Expo, you must implement your pages to sign in or sign up as a user. We will use Discord, but you can use any social or standard sign-in you want. First, we need to install `expo-auth-session` to handle sessions.

`pnpm install expo-auth-sessions --filter @acme/expo`

### Creating a Sign In component

Create a folder called `components` and then create a file called `SignInWithOAuth.tsx`. This will be our component that you can easily extend to use more providers or swap out Discord for something else.

```jsx
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'
import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()
}
```

Here we are using another helper, which allows you to sign in as a user and set the session after the fact. We need to make sure Clerk is fully loaded before we attempt a sign in so we can use the `isLoaded` as part of the `useSignIn` helper.

```jsx
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null
}
```

Now we need to create our function that will run when a user taps the button to sign in:

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
```

Next we need to tell where to redirect to after a successful or unsuccessful login attempt via Discord,`expo-auth-session` provides a helper to make a redirect, which is called `makeRedirectUri`, and set it to `/oauth-native-callback`

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })
```

At this point, we can start our sign in attempt using `signIn.create` passing in our strategy, which is `oauth_discord`, and our newly created `redirectUrl`

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })
```

The `SignIn` object holds all the state of the current sign in and provides helper methods to navigate and complete the sign in process. You can read about this in our [documentation](/docs/reference/clerkjs/signin), as you may want to use the different sign in methods in the future.

The next part of the sign in is to retrieve the external redirect URL and use AuthSession. This will give us the ability to know if the OAuth was successful or not.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL?.toString() || '',
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }
```

You may notice that we have an eslint to disable the checks on the next line. There is an assumption in this example that it will always be successful, but you can use the following [AuthSession](https://docs.expo.dev/versions/latest/sdk/auth-session/#returns-7) documentation to implement anything you may want to handle.

We now need to retrieve `rotatingTokenNonce` and reload our `signIn` object. This will allow us to get the `sessionId` and sign the user in.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL.toString(),
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      console.log
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })
```

Finally we can retrieve the `createdSessionId` from the `signIn` object and set that to our current session. This will let us know that the user is signed in with a valid session.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL?.toString() || '',
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })

      const { createdSessionId } = signIn

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign in OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)
      return
    }
```

Finally we can add a catch for anything that might go wrong that we aren’t handling and return the error.

```jsx {{ prettier: false }}
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL?.toString() || '',
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })

      const { createdSessionId } = signIn

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign in OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)
      return
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing in', err)
    }
  }
```

Our sign in method is now complete, so we can create a simple UI that, on touch, will attempt a sign in.

```jsx
return (
  <View className="rounded-lg border-2 border-gray-500 p-4">
    <Button title="Sign in with Discord" onPress={handleSignInWithDiscordPress} />
  </View>
)
```

Our Sign In component is now complete below is the full code. We will use this for a Sign Up component for anyone who doesn’t have an account yet for our application.

```jsx
import { useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()

  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL.toString(),
        returnUrl: redirectUrl,
      })

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      console.log
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signIn.reload({ rotatingTokenNonce })

      const { createdSessionId } = signIn

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign in OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)

      return
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing in', err)
    }
  }

  return (
    <View className="rounded-lg border-2 border-gray-500 p-4">
      <Button title="Sign in with Discord" onPress={handleSignInWithDiscordPress} />
    </View>
  )
}

export default SignInWithOAuth
```

## Create a Sign Up component

The good news is that the sign in component and the sign up component is very similar and 99% of the code we created can be reused and swapped for `useSignUp` hook. To save you from reading more content, here is the code.

```tsx
import { useSignUp } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignUpWithOAuth = () => {
  const { isLoaded, signUp, setSession } = useSignUp()

  if (!isLoaded) return null

  const handleSignUpWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signUp.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        verifications: {
          externalAccount: { externalVerificationRedirectURL },
        },
      } = signUp

      const result = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL!.toString(),
        returnUrl: redirectUrl,
      })
      console.log(result)
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { type, params } = result || {}
      console.log
      if (type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = params

      await signUp.reload({ rotatingTokenNonce })
      const { createdSessionId } = signUp

      if (!createdSessionId) {
        throw 'Something went wrong during the Sign up OAuth flow. Please ensure that all sign in requirements are met.'
      }

      await setSession(createdSessionId)

      return
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing up', err)
    }
  }

  return (
    <View className="my-8 rounded-lg border-2 border-gray-500 p-4">
      <Button title="Sign Up with Discord" onPress={handleSignUpWithDiscordPress} />
    </View>
  )
}

export default SignUpWithOAuth
```

### Creating a Sign in, Sign Up screen

We now need to use our components in our application. Under the screens folder, create a new file called `signInSignUp.tsx` and paste the following code. We are displaying the components we created so the code below is generic React Native code.

```jsx
import React from 'react'

import { View, SafeAreaView } from 'react-native'

import SignInWithOAuth from '../components/SignInWithOAuth'
import SignUpWithOAuth from '../components/SignUpWithOAuth'

export const SignInSignUpScreen = () => {
  return (
    <SafeAreaView className="bg-[#2e026d] bg-gradient-to-b from-[#2e026d] to-[#15162c]">
      <View className="h-full w-full p-4">
        <SignUpWithOAuth />
        <SignInWithOAuth />
      </View>
    </SafeAreaView>
  )
}
```

### Updating \_app.tsx

We can now update our `SignedOut` control component to use the `SignInSignUpScreen` so if a user doesn’t have a valid session and is not signed in, they will be able to sign in.

```jsx
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { TRPCProvider } from './utils/trpc'

import { HomeScreen } from './screens/home'
import { SignInSignUpScreen } from './screens/signInSignUp'
import { ClerkProvider, SignedIn, SignedOut } from '@clerk/clerk-expo'
import { tokenCache } from './utils/cache'

// Find this in your Dashboard.
const clerk_frontend_api = 'YOUR_API_KEY'

export const App = () => {
  return (
    <ClerkProvider frontendApi={clerk_frontend_api} tokenCache={tokenCache}>
      <SignedIn>
        <TRPCProvider>
          <SafeAreaProvider>
            <HomeScreen />
            <StatusBar />
          </SafeAreaProvider>
        </TRPCProvider>
      </SignedIn>
      <SignedOut>
        <SignInSignUpScreen />
      </SignedOut>
    </ClerkProvider>
  )
}
```

### Updating TRPC client

The TRPC client found under `utils/trpc` needs a very small update. As part of TRPC, you can provide headers as part of `httpBatchLink` . We can get the JWT token by using `getToken`, which is part of the `useAuth` hook.

First, add the import `import { useAuth } from "@clerk/clerk-expo";` , then, inside our TRPCProvider, add the `getToken` code before the client.

```tsx {{ prettier: false }}
export const TRPCProvider: React.FC<{
  children: React.ReactNode
}> = ({ children }) => {
  const { getToken } = useAuth()
  const [queryClient] = React.useState(() => new QueryClient())
......

```

Then finally, add the Authorization header to our `httpBatchLink`

```jsx {{ prettier: false }}
async headers() {
  const authToken = await getToken()
  return {
    Authorization: authToken,
  }
},
```

This will allow you to send a valid token with your requests to the TRPC backend. Below is the full code:

```tsx
import { createTRPCReact } from '@trpc/react-query'
import type { AppRouter } from '@acme/api'
/**
 * Extend this function when going to production by
 * setting the baseUrl to your production API URL.
 */
import Constants from 'expo-constants'
/**
 * A wrapper for your app that provides the TRPC context.
 * Use only in _app.tsx
 */
import React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { httpBatchLink } from '@trpc/client'
import { transformer } from '@acme/api/transformer'
import { useAuth } from '@clerk/clerk-expo'

/**
 * A set of typesafe hooks for consuming your API.
 */
export const trpc = createTRPCReact<AppRouter>()

const getBaseUrl = () => {
  /**
   * Gets the IP address of your host-machine. If it cannot automatically find it,
   * you'll have to manually set it. NOTE: Port 3000 should work for most but confirm
   * you don't have anything else running on it, or you'd have to change it.
   */
  const localhost = Constants.manifest?.debuggerHost?.split(':')[0]
  if (!localhost) throw new Error('failed to get localhost, configure it manually')
  return `http://${localhost}:3000`
}

export const TRPCProvider: React.FC<{
  children: React.ReactNode
}> = ({ children }) => {
  const { getToken } = useAuth()
  const [queryClient] = React.useState(() => new QueryClient())
  const [trpcClient] = React.useState(() =>
    trpc.createClient({
      transformer,
      links: [
        httpBatchLink({
          async headers() {
            const authToken = await getToken()
            return {
              Authorization: authToken,
            }
          },
          url: `${getBaseUrl()}/api/trpc`,
        }),
      ],
    }),
  )

  return (
    <trpc.Provider client={trpcClient} queryClient={queryClient}>
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    </trpc.Provider>
  )
}
```

Go ahead and test everything. At this point, you have a working application that uses TRPC

## Final Updates to our TRPC API

The final update here is to update the `post` router to use a `protectedProcedure` for creation so that when a user uses the Expo application, they will need to be logged in to create a new post. Open the `post.ts` under `/packages/api/src/router` and update the `create` to use `protectedProcedure` .

```jsx
import { router, publicProcedure, protectedProcedure } from '../trpc'
import { z } from 'zod'

export const postRouter = router({
  all: publicProcedure.query(({ ctx }) => {
    return ctx.prisma.post.findMany()
  }),
  byId: publicProcedure.input(z.string()).query(({ ctx, input }) => {
    return ctx.prisma.post.findFirst({ where: { id: input } })
  }),
  create: protectedProcedure
    .input(z.object({ title: z.string(), content: z.string() }))
    .mutation(({ ctx, input }) => {
      return ctx.prisma.post.create({ data: input })
    }),
})
```

## Next Steps

Now you have a working T3 Turbo application that has authentication both in Next.js and Expo with protected routes. Here are some next steps you might want to implement:

- Additional login methods for Expo ( more social logins or email and password screen)
- Use one of our [integrations](/docs/guides/development/integrations/overview) to use a database, such as Neon, Supabase, or Firebase.
- Join our [Discord](https://clerk.com/discord)

---

# Clerk raises $6.2m led by Andreessen Horowitz
URL: https://clerk.com/blog/a16z-seed.md
Date: 2022-11-30
Category: Company
Description: Clerk is building the future of authentication for React, where the Component is the new API

Today, we're thrilled to announce $6.2m in new funding led by Martin Casado at Andreessen Horowitz, with continued participation from S28 Capital, Fathom Capital, and South Park Commons. The formal press release is available below.

This funding marks a major milestone for Clerk. For the first time, we've raised based on the traction of our customers, who are simply blowing us away with their continued success. Here's a chart showing cumulative sign ups across all customer applications since we launched:

![Cumulative customer sign-ups chart](./33e2503da8bdd68d27f8100245b0e13c0faf8a3d-1940x762.png)

Our key insight at Clerk is that the Component is the new API. In fact, over 95% of our customers use **all** of our `<SignUp/>`, `<SignIn/>`, and `<UserProfile/>` components! Of the few who implement our APIs directly, most will build a custom sign-up flow with our APIs, but still use our `<SignIn/>` and `<UserProfile/>` components for efficiency.

This outcome is obvious in hindsight. Components combine the power of backend APIs with beautiful, prebuilt frontends, so they inherently deliver more value than APIs alone. We believe component-based integrations have set a new standard for developer tools, and we're excited for the massive improvement in developer productivity they enable.

With this new funding, Clerk will reinforce and expand on our foundation, including:

- Continued, emphatic support for cutting-edge frameworks like Next.js, Remix, Redwood, and more on the way
- Additional authentication strategies like passkeys and SAML SSO
- Expanded capabilities in our `<CreateOrganization/>` and `<OrganizationProfile/>` components for B2B SaaS

We can't wait to see what you build!

### Press Release

Clerk, the drop-in authentication and user management solution for React, announced today that it has closed a $6.2m seed round led by Andreessen Horowitz. Existing investors S28 Capital, Fathom Capital, and South Park Commons also joined the round. This new funding will allow Clerk to expand its suite of authentication and user management tools, and create new tools to help B2B SaaS companies manage both user accounts and business accounts.

Clerk empowers React developers to build sign-up and sign-in flows as well as user profiles without the assistance of backend developers. The solution comes complete with security essentials like multi-factor authentication and active device management. The beautifully designed React components can be customized to match any company's branding. By providing a full stack solution, Clerk minimizes the time engineers need to spend on authentication, freeing up development resources to focus on the core of their business.

The vast majority of authentication solutions on the market today are still managed in-house and are often incomplete and fail to meet security best practices. Many of these solutions are dated, as web development technologies have evolved to component-based frontend technologies like React. With Clerk’s solution, developers are getting what they prefer—components—because they help them move faster. Components are especially appealing in authentication and user management where businesses do not get much benefit from reinventing the wheel of self-serve 2FA or avatar-uploading. Clerk includes both in their `<UserProfile/>` component.

*"Our key insight is that React Components have replaced REST APIs as the premier developer experience,"* said **Colin Sidoti, Clerk cofounder and CEO**. *"Since components have a built-in backend and presentation layer, they're an order-of-magnitude faster to implement than APIs."*

While Clerk is intended for React frontends, the authentication solution works with any framework, programming language, or API gateway on the backend. This approach has been especially helpful for legacy web applications that are transitioning to React on the frontend, but do not want to change their backend technology.

*"There's a growing preference for React among businesses of all sizes, and devtools must evolve to cater to this new architecture. Clerk is hands-down the easiest and most-complete approach to auth and user management in React today,"* said **Martin Casado, General Partner at a16z.** *"We are excited to help accelerate Clerk's growth and reach more businesses, founders and startups who are looking for easy authentication and user management."*

Clerk's vision is to build a truly complete customer management solution for developers, helping facilitate authentication, authorization, communications, billing, and more. Clerk believes these essential services can all be bundled together, and presented cohesively in simple React components.

Notable startups using Clerk include database company Grafbase, women's shapewear company Honeylove, and apartment rental company Blueground. Clerk's React-optimized solution has led the company to be included in Netlify's Jamstack Innovation Fund, and named one of the [10 most promising Jamstack startups](https://www.netlify.com/blog/jamstack-innovation-fund-launches-with-the-10-most-promising-jamstack-startups).

---

# How to skip Next.js middleware for static and public files
URL: https://clerk.com/blog/skip-nextjs-middleware-static-and-public-files.md
Date: 2022-10-06
Category: Engineering
Description: Stop your Next.js middleware from running on static assets like images and Next.js internals

[Next.js middleware](https://nextjs.org/docs/advanced-features/middleware) is incredibly powerful, but by default it runs on more requests than is normally necessary. To see this in action, you can add a simple logger:

```javascript {{ title: 'middleware.js' }}
export default function middleware(req) {
  console.log(req.url)
}
```

Here's the log for loading [http://localhost:3000/](http://localhost:3000) on a brand new Next.js application:

```text
http://localhost:3000/
http://localhost:3000/_next/static/chunks/webpack.js?ts=1665116452838
http://localhost:3000/_next/static/chunks/main.js?ts=1665116452838
http://localhost:3000/_next/static/chunks/react-refresh.js?ts=1665116452838
http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1665116452838
http://localhost:3000/_next/static/development/_buildManifest.js?ts=1665116452838
http://localhost:3000/_next/static/development/_ssgManifest.js?ts=1665116452838
http://localhost:3000/_next/static/chunks/pages/index.js?ts=1665116452838
http://localhost:3000/favicon.ico
http://localhost:3000/_next/static/development/_devMiddlewareManifest.json
http://localhost:3000/_next/static/development/_devPagesManifest.json
http://localhost:3000/vercel.svg
```

The log shows several static assets that you probably don't want to process in your middleware, and doing so could break your application. To solve this, you can configure a [matcher](https://nextjs.org/docs/advanced-features/middleware#matcher), which tells your middleware to only run on requests that match a certain pattern.

To prevent middleware from running on static files, you can leverage a simple trick: static files have a **`.`** in the path, while dynamic files do not.

With a regular expression, you can configure middleware to run on every file that does not contain a **`.`**:

```javascript {{ title: 'middleware.js' }}
export default function middleware(req) {
  console.log(req.url)
}

export const config = { matcher: '/((?!.*\\.).*)' }
```

With this matcher, the log only shows one request:

```text
http://localhost:3000/
```

This matcher is a great starting point that minimizes middleware invocation. As your application grows, though, you may need to tweak it. Below are the two most common revisions.

### Including *some* static assets

The easiest way to include some static assets in middleware is to retain the exclusionary regular expression, but define an *additional* matcher. Here's a sample that excludes all static assets from middleware except `favicon.ico`:

```javascript {{ title: 'middleware.js' }}
export const config = {
  matcher: ['/((?!.*\\.).*)', '/favicon.ico'],
}
```

### Excluding more paths from middleware

Sometimes you will want to filter more than just static files. This can be done in two ways:

#### 1. Expanding the regular expression

Expanding the regular expression prevents additional middleware invocations, but regular expressions are also harder to read and write. Here's an example that excludes API routes in addition to static assets:

```javascript {{ title: 'middleware.js' }}
export const config = { matcher: '/((?!.*\\.|api\\).*)' }
```

#### 2. Adding a conditional statement

A more readable approach is to create a conditional statement, but this will waste compute resources since your middleware will be unnecessarily invoked. Here's an example:

```javascript {{ title: 'middleware.js' }}
import { NextResponse } from 'next/server'

export default function middleware(req) {
  if (req.nextUrl.pathname.startsWith('/api/')) {
    return NextResponse.next()
  }
  // ... your middleware
}

export const config = { matcher: '/((?!.*\\.).*)' }
```

This should be everything you need to get started on the right foot with middleware!

---

# Let's stop arguing about JWTs and just fix them
URL: https://clerk.com/blog/lets-stop-arguing-about-jwts-and-just-fix-them.md
Date: 2022-10-05
Category: Engineering
Description: JWTs have won. It's time we embrace them and fix the dangerous implementations.

This week there was a [fresh](https://news.ycombinator.com/item?id=33019960) [batch](https://news.ycombinator.com/item?id=33061873) of debates about JWTs as session tokens on Hacker News. For the uninitiated, this happens incredibly frequently on HN, to the point where moderator dang has posted roundups:

![Lets Stop Arguing About Jwts And Just Fix Them guide illustration](./5e84204a848495c412d2cf8d45a8b193b3417bcd-1258x476.png)

Just about every thread goes the same way:

1. Everyone agrees that infrequently-refreshed, stateless JWTs should not be used as session tokens because they're irrevocable
2. Everyone agrees that it's pointless to use long-lived, stateless JWTs in combination with a stateful, database-backed blocklist of revoked JWTs
3. Everyone agrees that database-backed, stateful session tokens are easy to build and sufficient for the 99% case
4. With trepidation, everyone agrees that frequently-refreshed, stateless JWTs are acceptable as session tokens because the short expiration serves as a revocation mechanism

Why the trepidation on 4? Usually, it's because 3 is easier. Here's [one viral post's](https://apibakery.com/blog/tech/no-jwt) rationale (they refer to stateful session tokens as bearer tokens):

> \[...] you've just reintroduced a bearer token, because that's exactly what the refresh token is. Looking at JWTs from that perspective, you've introduced a client-side cache of user identity (the JWT) and added a bunch of complexity (involving the creation, verification, and token refresh) for the hope of optimizing part of the work you used to do on the server (checking user identity using a bearer token). Was it worth it?

The author is right: The complexity of 4 is high and the benefits for the 99% case are minimal.

Yet, JWTs are clearly winning. Their usage has grown, not dwindled, while two major trends in software development have increased their demand.

### Trend 1: Developers are relentlessly focused on efficiency

This has been a trend for decades. It's *impressive* that today's developers care about a 10ms query vs a \<1ms JWT, but it's not *surprising*.

The simple reality is that Google Lighthouse scores – and the wealth of evidence supporting that users prefer fast applications – have placed an unprecedented emphasis on loading speed.

The developers who care most are no stranger to complexity, as they're often thinking about problems like distributed storage and operating at the edge. It's no surprise they're eager to treat one less query as an easy win.

### Trend 2: Modern integrations often require a synced session

This trend is more recent. Third-party integrations are sweetening the buy-vs-build deal by doing more for their customers. If an integration knows which user is signed in and their permissions, then it can expose APIs directly to the frontend, and even offer user-facing UIs as part of their service:

- New database tools like Supabase, Hasura, Grafbase, Convex all allow querying from the frontend, and use JWTs to know which user is signed in
- Embeddable help desk and community tools like Zendesk and Canny use JWTs to know which user is signed in
- Stripe's user-facing UIs (Checkout, Customer Portal, Payment Element) use a backend API request and session token to know which user is signed in (not a JWT, but still part of the trend!)

The newer a tool is, the more likely it is to allow syncing sessions by JWT.

### It's time to embrace JWTs and disarm the footguns

These trends aren't going anywhere. It's time we embrace JWTs and fix the bad implementations that have stained their reputation:

#### For web developers

Check your application code. If you use stateless JWTs (no database check) and they don't expire in 5 minutes or less, report it to your security team.

#### For authentication tools

Don't generate session JWTs with a lifetime greater than 5 minutes. If developers want to configure a longer lifetime, warn that it's bad practice for XSS attacks.

Provide a refresh mechanism that depends on a HttpOnly cookie in the browser.

#### For integrations

Don't accept session JWTs with a lifetime greater than 5 minutes. If you must, warn developers that it's bad practice for XSS attacks.

Critically, provide developers with a mechanism to send a new JWT after the first JWT expires – don't receive a JWT once and then manage an independent session.

### Really, just expiration?

Yes, long expiration is the #1 most common security mistake with JWTs. It leaves many sites especially vulnerable when XSS attacks or account takeovers occur.

#### Does Clerk do this?

Yes! Clerk's session JWTs default to a 1 minute lifetime, and our refresh mechanism depends on an HttpOnly cookie. We even offer "Active Device" management in our `<UserProfile/>` component so end-users can revoke their own sessions.

---

# How to pass a value from Next.js middleware to API routes and getServerSideProps
URL: https://clerk.com/blog/nextjs-pass-value-from-middleware-to-api-routes-and-getserversideprops.md
Date: 2022-10-05
Category: Engineering
Description: Compute a value in middleware and pass it to your API route or getServerSideProps. Works in both Node and Edge runtimes.

Unlike many web frameworks, [Next.js middleware](https://nextjs.org/docs/advanced-features/middleware) doesn't have a built-in mechanism for passing values from middleware to other parts of the application.

> For authentication-specific middleware patterns in Next.js, see our [Next.js Authentication](/nextjs-authentication) solution.

Instead, middleware has a feature called "rewrites" that we can leverage to pass data.

The high-level idea is to "rewrite" requests to the same URL, but modify the request's metadata to include the data we want to pass. Then, we can read the metadata from our API route or getServerSideProps.

Unfortunately, there are inconsistencies across runtimes that make it difficult to get this working. We hope these snippets help save you save you some headaches.

**License: MIT**

**[Live Demo](https://nextjs-context-demo.vercel.app) | [Source Code](https://github.com/clerkinc/nextjs-context-example)**

**Usage: middleware.js**

```javascript
import { NextResponse } from 'next/server'
import { withContext } from './context'

// Pre-define the possible context keys to prevent spoofing
const allowedContextKeys = ['foo']

export default withContext(allowedContextKeys, (setContext, req) => {
  setContext('foo', 'bar')
  return NextResponse.next()
})
```

**Usage: API route (Node)**

```javascript
import { getContext } from '../../context'

export default function handler(req, res) {
  res.status(200).json({ foo: getContext(req, 'foo') })
}
```

**Usage API route (Edge)**

```javascript
import { getContext } from '../../context'

export default function handler(req) {
  return new Response(JSON.stringify({ foo: getContext(req, 'foo') }))
}
```

**Usage: getServerSideProps (Edge and Node)**

```javascript
import { getContext } from '../context'

export const getServerSideProps = ({ req }) => {
  return { props: { foo: getContext(req, 'foo') } }
}
```

**Source: (saved to context.js on your root)**

```javascript
import { NextResponse } from 'next/server'

const ctxKey = (key) => `ctx-${key.toLowerCase()}`

export const getContext = (req, rawKey) => {
  const key = ctxKey(rawKey)

  let headerValue =
    typeof req.headers.get === 'function'
      ? req.headers.get(key) // Edge
      : req.headers[key] // Node;

  // Necessary for node in development environment
  if (!headerValue) {
    headerValue = req.socket?._httpMessage?.getHeader(key)
  }

  if (headerValue) {
    return headerValue
  }

  // Use a dummy url because some environments only return
  // a path, not the full url
  const reqURL = new URL(req.url, 'http://dummy.url')

  return reqURL.searchParams.get(key)
}

export const withContext = (allowedKeys, middleware) => {
  // Normalize allowed keys
  for (let i = 0; i < allowedKeys.length; i++) {
    if (typeof allowedKeys[i] !== 'string') {
      throw new Error('All keys must be strings')
    }
    allowedKeys[i] = ctxKey(allowedKeys[i])
  }

  return (req, evt) => {
    const reqURL = new URL(req.url)

    // First, make sure allowedKeys aren't being spoofed.
    // Reliably overriding spoofed keys is a tricky problem and
    // different hosts may behave different behavior - it's best
    // just to safelist "allowedKeys" and block if they're being
    // spoofed
    for (const allowedKey of allowedKeys) {
      if (req.headers.get(allowedKey) || reqURL.searchParams.get(allowedKey)) {
        throw new Error(`Key ${allowedKey.substring(4)} is being spoofed. Blocking this request.`)
      }
    }

    const data = {}

    const setContext = (rawKey, value) => {
      const key = ctxKey(rawKey)
      if (!allowedKeys.includes(key)) {
        throw new Error(`Key ${rawKey} is not allowed. Add it to withContext's first argument.`)
      }
      if (typeof value !== 'string') {
        throw new Error(`Value for ${rawKey} must be a string, received ${typeof value}`)
      }
      data[key] = value
    }

    let res = middleware(setContext, req, evt) || NextResponse.next()

    // setContext wasn't called, passthrough
    if (Object.keys(data).length === 0) {
      return res
    }

    // Don't modify redirects
    if (res.headers.get('Location')) {
      return res
    }

    const rewriteURL = new URL(res.headers.get('x-middleware-rewrite') || req.url)

    // Don't modify cross-origin rewrites
    if (reqURL.origin !== rewriteURL.origin) {
      return res
    }

    // Set context directly on the res object (headers)
    // and on the rewrite url (query string)
    for (const key in data) {
      res.headers.set(key, data[key])
      rewriteURL.searchParams.set(key, data[key])
    }

    // set the updated rewrite url
    res.headers.set('x-middleware-rewrite', rewriteURL.href)

    return res
  }
}
```

**Known limitations:**

Depending on the runtime, your data will be transmitted as either an HTTP header or a URL query string. This leads to several limitations:

- Headers and query strings only accept strings for key/value pairs. If you'd like to use non-strings, you'll need to bring your own serializer
- Keys are lowercases because headers are case-insensitive
- Your host likely limits the total overall length of headers and query strings. [Here are the limits for Vercel's edge runtime](https://vercel.com/docs/concepts/functions/edge-functions/limitations#limits-on-requests), for example

---

# @clerk/nextjs v4.5
URL: https://clerk.com/blog/clerk-nextjs-4-5.md
Date: 2022-10-04
Category: Engineering
Description: New in 4.5: Authentication moves to middleware, switchable runtime support, improved developer experience, preparation for Layouts

Version 4.5 of **@clerk/nextjs** brings sweeping improvements to server-side authentication in Next.js.

Get started with `npm i @clerk/nextjs@latest`

## Authentication moves to middleware

Going forward, developers will authenticate requests once in [Next.js middleware](https://nextjs.org/docs/advanced-features/middleware), then simply read the authentication state in endpoints (API routes and getServerSideProps).

**middleware.js example:**

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

export default withClerkMiddleware((req) => {
  // Your own middleware
})
```

**API routes example:**

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

export default function handler(req, res) {
  const { userId } = getAuth(req)
  // ...
}
```

**getServerSideProps example:**

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

export const getServerSideProps = ({ req }) => {
  const { userId } = getAuth(req)
  // ...
}
```

With this change, [authentication in Next.js](/nextjs-authentication) will finally feel familiar for developers who have worked with frameworks like Express or Ruby on Rails, where authentication is normally handled within middleware.

## Switchable runtime support

Next.js 12.2 brought a switchable runtime, so developers could choose between a node runtime or an edge runtime for each of their API routes and server-rendered pages.

Our new **getAuth()** helper is isomorphic, so it works regardless of the runtime you choose.

## Improved developer experience

If you've used Clerk in the past, you'll notice three small but delightful improvements to our developer experience:

1. All server-side imports are now from **@clerk/nextjs/server** instead of having import paths specific to the endpoint-type
2. Wrapper functions are no longer required inside endpoints, only once in middleware
3. **getAuth(req)** works everywhere there's a request object

```javascript {{ title: '@clerk/nextjs v4.5', prettier: false }}
// pages/api/foo.js
import { getAuth } from '@clerk/nextjs/server'

export default function handler(req, res) {
  const { userId } = getAuth(req)
  // ...
}


// pages/bar.js
import { getAuth } from '@clerk/nextjs/server'

export const getServerSideProps = ({ req }) => {
  const { userId } = getAuth(req)
  // ...
}


// middleware.js
import { withClerkMiddleware, getAuth } from '@clerk/nextjs/server'

export default withClerkMiddleware((req) => {
  const { userId } = getAuth(req)
  // ...
})
```

```javascript {{ title: 'Previous' }}
// pages/api/foo.js
import { withAuth } from '@clerk/nextjs/api'

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

// pages/bar.js
import { withServerSideAuth } from '@clerk/nextjs/ssr'

export const getServerSideProps = withServerSideAuth(({ req }) => {
  const { userId } = req.auth
  // ...
})

// middleware.js
// Clerk hasn't supported Next.js 12.2+ middleware until today
```

## Preparation for Layouts

Our team has been watching the [Next.js Layouts RFC](https://nextjs.org/blog/layouts-rfc) closely, and we designed the new helpers in anticipation of layouts support.

We expect that by computing the authentication state in middleware, we'll be able to share it with each of your parallel-loading layout files.

## Get started

Get started right away with our [guide to Next.js authentication](/docs/quickstarts/get-started-with-nextjs), or [join our community Discord](https://clerk.com/discord) to discuss with our team.

Thanks to the contributors: Mark Pitsilos, Nikos Douvlis

---

# Passwordless Authentication: Which Option Is Right for Your App
URL: https://clerk.com/blog/passwordless-authentication.md
Date: 2022-09-06
Category: Insights
Description: Passwordless Authentication is on an upward trajectory thanks to advancements in this space and recent password breaches.

## The Case for Passwordless Authentication

Password-based authentication systems are prone to various cyberattacks, including brute-force methods, phishing, and keylogging. In 2021, over [two billion passwords were leaked](https://www.techradar.com/news/over-two-billion-passwords-were-leaked-by-hackers-in-2021) by attackers. The number of stolen passwords has increased by [more than 35 percent](https://www.techradar.com/news/over-two-billion-passwords-were-leaked-by-hackers-in-2021#:~:text=What%E2%80%99s%20more%2C%20the%20two%20billion%20is%20an%20increase%20of%20more%20than%20a%20third%20\(35%25\)%2C%20compared%20to%20just%20two%20years%20ago) in recent years, proving how insecure password-based systems are (hint: something passwordless authentication can help with).

Even though applications encourage users to change passwords regularly and use complex and hard-to-guess phrases, it's inconvenient for users. Most users tend to choose a password that's easy to remember and, therefore, less secure.

This is where **passwordless authentication** can help. Passwordless authentication is the process of authenticating without needing to input a password or any memorized secret to gain access, in turn reducing data breaches. According to Verizon's Data Breach Investigations Report (DBIR), [over 80 percent of data breaches](https://cloudnine.com/ediscoverydaily/electronic-discovery/80-percent-hacking-related-breaches-related-password-issues-cybersecurity-trends)) happen due to stolen or weak passwords.

Passwordless authentication systems come in several different types, including biometric authentication, one-time passcodes, magic links, and social logins; and each has its own advantages and disadvantages. For instance, if you have a web application, biometric authentication or USB-based authentication might not be the best system since you'll need external devices for verification. In such cases, other authentication types, like social logins or magic links, make more sense.

In this roundup, you'll learn about different types of passwordless authentication that are currently available. You'll look at these options and compare them based on their well-supported standards, convenience, security, and promising new technologies.

### Different Types of Passwordless Authentication

As mentioned previously, passwordless authentication can mean using either a one-time passcode, magic link, or physical hard disk to give you access to the application. In the following section, you'll learn about different types of passwordless authentication, including their advantages and disadvantages.

### Magic Links

[Magic links](/features/email-magic-links) are currently a popular passwordless authentication approach that generates a one-time link and sends it to the user. If the link token verifies with the token stored in the database, the user gets access to the application. The basic workflow looks like this:

![Magic Links screenshot](./be0f848424add9550a53c129391b17a64a0df9d2-1022x662.png "Magic link workflow courtesy of Subha Chanda")

In this workflow, a user may enter their email, username, or any specific identifier. The application generates and stores tokens if the user exists on the database and sends a link to the user's email. When the user opens the magic link, the token retrieved from the link gets verified with the backend, and if the token matches, the user gains access to the application. The link stays valid for a specific amount of time, and a user will need to request a new link if it doesn't get authenticated within the allotted time frame.

This workflow may sound simple, but behind the scenes, several complex tasks are happening to ensure that an attacker can be prevented from maliciously accessing the links.

### Benefits of Magic Links

When users need to log in infrequently, magic links provide a frictionless experience that leads to a better user experience. In addition, since no password is stored in a database, there's no chance of a password breach, and the risk of a data breach is also reduced significantly.

On average, an enterprise spends[ $70 USD per password reset](https://bioconnect.com/2021/12/08/are-password-resets-costing-your-company). Large organizations in the US allocate almost a million dollars yearly for password-related support costs. With magic links, since no password is attached to the authentication system, there is no need to implement a password-reset solution or a support team.

### Disadvantages of Magic Links

Even though magic links provide significant benefits, there are also some dependency issues to take into consideration. For instance, if the user's email account gets compromised, the attacker can easily access all applications that authenticate with magic links and use the compromised email to gain access.

With magic links, you also have to worry about email deliverability. Since magic links depend on the user's email, if the email provider is down or the mailbox storage is full, the magic link will not be delivered. In this case, the user won't be able to log in until the mailbox is cleared or the email provider is up again.

In addition, large business-to-business (B2B) companies tend to filter their incoming emails strongly. That means it's possible that a magic link may land in a user's spam folder and affect the overall user experience.

If your application is smaller in size and the frequency of login is fewer, [magic link authentication](/blog/magic-links) can benefit you. But if a large set audience uses your application and it's essential to efficiently log into the application, you should provide multiple authentication options, like a social login or a password-based login, along with magic links.

### Email and SMS One-Time Passcodes

One-time password (OTP) authentication is another type of authentication that many modern applications use. This type of authentication sends a passcode (primarily numeric) to the user's registered email or mobile phone. After sending the passcode, the application then asks for the passcode. If the user provides the correct passcode, they can access the application.

OTPs are time-based (just like magic links), and they stay valid for a particular amount of time. After that time frame, a new OTP will need to be generated if the user wants access to the application.

### Pros of OTP

A [replay attack](https://en.wikipedia.org/wiki/Replay_attack) is a form of network attack in which legitimate data transmission is purposefully or fraudulently duplicated or delayed. Since no password is required in OTP-based authentication and a new OTP is required every time you log in, this type of authentication is safe from replay attacks.

In addition, because OTP-based authentication is provided by most authentication service providers, it's easy to adopt using an authentication service provider like [Clerk](/). And since no password is involved in authenticating a user, the user doesn't have to remember a password, creating a better user experience.

### Cons of OTP

One of the cons of using OTP is that the messages sent to mobile phones are unencrypted. If the phone or the email address gets compromised, an attacker can easily access the application with the user's profile.

You're also dependent on the network when using OTP. Mobile phone networks might not be stable everywhere and if there's a mobile network issue, the passcode may not get delivered to the user. This can also occur with email if the email provider is down.

Another drawback is that you have to share your mobile number with the application you use. This might be inconvenient and cause issues if your bank account is linked to the same number. Moreover, the provider might call or send the user spam messages; in addition, there is the risk of a data leak. If an attacker gets access to the database, the mobile numbers of all customers can get breached.

The issues with email OTP are similar to the problems associated with magic links. Overall, OTP-based authentication has a few drawbacks, which can be an issue considering there's only one layer of protection. However, your application can be heavily secured using OTP-based authentication as a second layer. For example, with password-based authentication, the chance of getting hacked will be significantly reduced if you integrate OTP as well.

### Social Logins

[Social login or social sign-in](/docs/authentication/social-connections/overview#social-connections-authentication-providers) is a type of login where the user logs in with an existing social account. For example, users can use their Google or Facebook credentials to log into an application, simplifying the login process.

### Benefits of the Social Sign-In

One of the benefits of the social sign-in is that the user doesn't have to fill out a registration form and enter details manually. Instead, when registering with a social sign-in, the necessary details are fetched from the social account. This creates a better user experience.

Another benefit of the social login is that the application can collect more information about the user. This information can be used to provide a better and more personalized experience. In addition, using a social login with familiar login identities helps the user perform login efficiently. Users are already familiar with services like Facebook, Google, and GitHub. Seeing a familiar logo and logging in with the social credentials help the user log in quickly.

### Disadvantages of the Social Login

One of the disadvantages of the social login is the lack of trust. If users don't trust your application, they might hesitate to share their social details.

In addition, if your application uses social login, then you give the user's control to a third party. If the social platform decides to shut its service or something else happens, your users won't be able to log into your application.

There's also a chance that the user is not providing accurate information on their social profile. In such a case, the application will receive false information about the user, which can lead to a poor user experience.

Social logins can provide a great solution if your application depends heavily on user customization. The data received from the social platform will be helpful for creating a custom experience. But this depends on the niche of your application. If your application is built for more professionals or older adults, this login solution might not be the right solution for your users. However, you could combine a social login with a traditional login system, and you can let the user decide which solution they prefer.

### WebAuthn

The [World Wide Web Consortium](https://en.wikipedia.org/wiki/World_Wide_Web_Consortium) (W3C) and [FIDO](https://fidoalliance.org) published the WebAuthn standard in 2016. It's a technology that focuses on securing private information. Rather than using a traditional password-based authentication system, WebAuthn uses [asymmetric cryptography](https://www.techtarget.com/searchsecurity/definition/asymmetric-cryptography) to secure a user's account.

When a user tries to log into your application, the server sends a challenge to the user. After completing the challenge, the user can access the application. The challenge can be solved by the server's approved method. Most of the browsers and operating systems are building native support for WebAuthn. You can see how WebAuthn works from their [official site](https://webauthn.io).

### Benefits of WebAuthn

One of the benefits of WebAuthn is its native support. WebAuthn continues to gain popularity, which means browsers and operating systems are continuously trying to provide native support. API and JavaScript functions (on most major browsers) are also available using WebAuthn.

Because WebAuthn uses public and private key encryption, it's more secure than a traditional password-based system. WebAuthn also doesn't require any password, and because of this, the chance of phishing or man-in-the-middle attack is reduced significantly.

### Disadvantages of WebAuthn

One of the disadvantages of WebAuthn is the lack of currently available support. Because the WebAuthn authentication system is new, not every browser or operating system natively supports it. However, this is rapidly changing, as most modern browsers are integrating the WebAuthn API.

WebAuthn can also be used with hardware authenticators like [YubiKey](https://www.yubico.com). But in such a case, if the device gets stolen or lost, the recovery might be tricky if there is no proper setup implemented. In addition, because WebAuthn is in a very primitive stage, the [user experience of using WebAuthn](https://blog.silverorange.com/web-authn-ux) is lacking and, at times, can feel too technical to use.

WebAuthn is an excellent alternative to traditional systems, but implementing it for a simple and small application might be overkill. It's ideal for large-scale applications that focus on privacy.

### SAML Login

Security Assertion Markup Language (SAML) is an XML-based open standard that transfers data between two parties. You can access all other services linked to your identity by logging into only one platform or dashboard. SAML transfers data between an identity provider and a service provider. The identity provider provides the user's identity and authorizes the service provider. The service provider, based on the identity provider, grants access to the user for the service.

SAML is primarily used in B2B use cases. For example, your company email might let you log into a specific dashboard from which you can access other services.

### Benefits of SAML

One of the benefits of SAML is that it provides a great user experience. Only a single credential is needed to log into different applications.

Security is another critical benefit of using SAML. It provides a single point of authentication, and the user's information doesn't leave the firewall boundary. All the different applications don't need to synchronize information between them, making the authentication system securer.

In addition, SAML is widely accepted by enterprises. It has been on the market for a long time and has gained the trust of enterprises.

### Disadvantages of SAML

One of the disadvantages of SAML is that it can be vulnerable to XML and DNS spoofing attacks, which makes the system less secure.

It's not suitable for personal applications like social platforms since setting up SAML is difficult; however, it works well for enterprise applications because employees won't need to think of multiple software that the company uses. Using a single set of login credentials, your employees can access all your software.

In addition, implementing SAML is a critical job. Different security aspects need to be considered, which might not be an easy job for a small-sized team.

### Conclusion

Passwordless authentication is gaining more attraction because it's an excellent solution for providing a better user experience and increased security to your users. In this article, you learned about different popular passwordless systems and their benefits and disadvantages.

[Passwordless authentication](/docs/authentication/configuration/sign-up-sign-in-options#authentication-strategies) can be an excellent solution for your application, but it's crucial that you understand the use case and implement a solution suitable to your needs. [Try Clerk free today](https://dashboard.clerk.com/sign-up) to add passwordless authentication to your application within minutes – not weeks.

---

# What are Webhooks? The Ultimate Guide 
URL: https://clerk.com/blog/what-are-webhooks.md
Date: 2022-08-19
Category: Insights
Description: Webhooks allow apps to communicate with one another. Find out best practices and more here.

**What are Webhooks? The Ultimate Guide**

Webhooks can be powerful tools for your business, but only if implemented correctly. In this blog post, you will learn the nature of webhooks, some of the webhook best practices for implementation, and their various use cases in a business.

You will also get to explore examples of platforms that use webhooks in their development processes. And finally, you will learn how to implement webhooks in your authentication and development strategies. By following these webhook best practices, you will ensure that your webhooks are secure and efficient.

## **What Are Webhooks?**

Webhooks are user-defined HTTP callbacks initiated by an event. In other words, a webhook is an HTTPS POST request sent whenever a specific event occurs to a URL that you have specified.

The usual trigger is some event, such as pushing code to a repository or a comment being posted to a blog. When that event occurs, the source site makes an HTTP request to the URL configured for the webhook. Webhooks can be used to perform various tasks, such as building a continuous integration system, sending notifications, or synchronizing data.

Webhooks offer a simple and flexible way to automate tasks that would otherwise be repetitive and time-consuming. They are preferred over polling because they allow you to receive information in near-real-time instead of waiting for a set interval. Their usage is not limited to development tasks; webhooks can be used for a wide range of integrations, such as social media, marketing, and customer support.

Webhooks are a powerful tool that can automatically send information from one system to another. However, before implementing webhooks in your system, it is essential to consider a few webhook best practices.

## **How Does a Webhook Work?**

So, how do webhooks work? A [webhook is an HTTP](https://cloud.ibm.com/docs/assistant?topic=assistant-dialog-webhooks) callback that is triggered by an event. When that event occurs, the source site makes an HTTP request to the configured webhook URL. Developers use webhooks to receive notifications about events within their applications. For example, a developer could use a webhook to be notified when a new user signs up for their service.

The webhook request will typically contain information about the event that triggered it. This information can be used to take action within the receiving application, such as updating a database or sending a notification. In some cases, the webhook may also trigger an action on the source site. For example, a webhook could be used to deploy application code when it is pushed to a repository automatically.

## **Best Practices When Implementing Webhooks**

Webhooks are a great way to get real-time data from your web application. They are perfect for automating tasks or getting notified when something happens in your app. Webhook traffic is described as a request that is initiated by an event. The request is then forwarded to the URL that you have configured for the webhook.

However, to reliably and efficiently use webhooks, there are some best practices to keep in mind when setting them up. The webhook best practices will ensure that your webhooks are working as intended and that you are getting the most out of them. When configuring webhooks for your application, security should be your top priority. Here are some best practices to follow when implementing webhooks:

### **Provide Developers With Sample Code to Authenticate Webhook Requests**

One of the most important things to do when setting up webhooks is to provide developers with sample code to authenticate webhook requests. This will ensure that only legitimate requests are processed and that any malicious requests are ignored.

There are a few different ways to authenticate webhook requests. The most common method is to use a shared secret. This is a piece of data known only to the server and the client. When a webhook request is made, the shared secret is used to calculate a hash. This hash is then compared to the one sent with the request. If they match, then the request is considered to be authentic.

Another method that can be used to authenticate webhook requests is to sign them with a digital signature. This signature is generated using a private key that is known only to the server. The client then verifies the signature using the server's public key. This method is more secure than using a shared secret, but it is also more complicated to set up.

Webhooks are incredibly powerful tools that enable your application to receive real-time updates from other applications or services. However, because webhooks involve sending potentially sensitive data over the internet, it's essential to take steps to ensure that your webhook endpoints are as secure.

### **Keep Your Webhook Endpoints Secure**

Webhook endpoints are URLs configured on a system to receive data sent by an HTTP callback. Webhook endpoints are [a potential attack vector](https://docs.oracle.com/en/cloud/paas/content-cloud/solutions/use-webhooks.html#GUID-3513A92A-1E36-4E47-B5C7-7D8989590AF1) for malicious actors. If an attacker can guess or brute force the URL of a webhook endpoint, a request can be sent to that endpoint and potentially cause damage.

As a preventative measure, it is crucial to keep your webhook endpoints secure. One way to do this is to use a randomly generated string as the endpoint URL. This will make it much harder for an attacker to guess the URL of the endpoint.

Another way to keep your webhook endpoint secure is to use HTTPS for all communication. This will ensure that all the webhook payload passing between the server and the client is encrypted. It also prevents anyone from eavesdropping on the transmission and potentially intercepting sensitive data.

The third step is consumer verification of the client before processing any requests. This can be done using a shared secret or a digital signature. Whichever method you choose, make sure that it is secure and that only trusted clients are able to access your webhook endpoint.

### **Configure To Receive Specific Webhook Events**

When configuring your webhooks, you should only receive the business process events in which you are interested. There is no need to receive all events for all of your users as it will just result in extra work for you and could lead to missed events if you are not paying attention.

Instead, only configure your webhooks to receive the specific events in which you have interest. This way, you can be sure that you will only receive the events that you care about and that you will be able to process them in a timely manner.

### **Utilize the Network Time Protocol To Prevent Replay Attacks**

Another critical webhook best practice when setting up is to utilize the Network Time Protocol (NTP). This protocol is used to [synchronize the clocks](https://www.ibm.com/docs/en/aix/7.1?topic=files-network-time-protocol-ntp) of computers over a network.

Using NTP will help to prevent replay attacks. A replay attack is where an attacker intercepts a webhook request and then re-sends it at a later time. If the clocks on the server and the client are not synchronized, the attacker could potentially resend the request before it has been processed. This could lead to the same event being processed more than once.

By using NTP, you can be sure that the clocks on the server and the client are synchronized. This will prevent replay attacks and ensure that each webhook request is processed only once. The use of NTP is vital when processing time-sensitive data.

### **Pay Attention to Delivery Attempt Data and Metrics**

When setting up webhooks, paying attention to the delivery attempt data and metrics is essential. This data can be used to troubleshoot any problems you are having with webhooks. Delivery attempt data is defined as information about each time webhook notifications are sent from the server to the client.

This data can be used to determine if there are any problems with the connection between the server and the client. It can also be used to determine if there are any problems with the webhook endpoint itself by reviewing already-logged events.

By paying attention to this data, you can be sure that your webhooks are being delivered successfully. This will help to prevent any missed events and ensure that your webhooks are working as intended. The delivery attempt data will tell you how many times a webhook request has been made and whether or not it was successful. This data can be used to identify any problems with the webhooks.

The webhook metrics will tell you how long it is taking for the webhook requests to be processed. This information can be used to identify any error in the system. By paying attention to the delivery attempt data and metrics, you can be sure that your webhooks are working correctly and that they are being processed promptly.

## **Why Do We Use Webhooks**

Now that we have covered some of the webhook best practices for configuration, let's take a look at why we use them. Webhooks are a great way to get real-time data from an external source. They are also a good way to keep your own internal data up-to-date.

For example, let's say that you have a website that sells products. Every time a product is sold, you could use a webhook to send the order information to your internal system. The information received from the website could then be used to update the inventory in your internal system. This would ensure that your inventory is always up-to-date.

Another example of why webhooks are useful is if you have a blog. Every time a new post is published, a webhook could be used to send the information to your mailing list. This would ensure that your subscribers are always updated on the latest posts.

Webhooks are also a good way to get real-time data from an external source. For example, let's say that you want to track the stock price of a company. You could use a webhook to get the information from an external source and then display it on your website. This would allow you to get the latest information without constantly refreshing the page. The following text describes two major ways on how to use webhooks.

### **To Receive Different Event Types**

Webhooks are essential to receive different event types. Events are defined as any actions that take place on your website or application.

Some examples of events include:

- A user signs up for an account
- A user adds an item to their shopping cart
- A user completes a purchase

If you are not using webhooks, then you will not be able to receive these events in real-time. For example, let's say that you have a web application that allows users to sign up for an account. Whenever a user signs up for an account, you could use a webhook to send an email to the user. This would allow you to receive different event types and take action based on those events.

### **To Store Information Securely**

Webhooks can also be used to store information securely. For example, let's say that you have a web application that allows users to input sensitive information. You could use a webhook to send that information to your internal system. This would allow you to store the information securely and not have to worry about it being intercepted by an attacker.

## **Authentication With Webhooks**

Another best practice when setting up webhooks is to use authentication. When you use authentication, you can be sure that only authorized users are able to access the data.

There are many[ different ways to authenticate](https://developer.zendesk.com/documentation/event-connectors/webhooks/webhook-security-and-authentication/#:~:text=Webhooks%20support%20two%20types%20of,authentication%20property%20from%20the%20request.) with webhooks. One popular way is to use an authentication tokens system. With this system, you would generate a token for each user. The user would then include the token in the webhook request. This would allow you to verify that the user is authorized to access the data.

Another way to authenticate with webhooks is to use an application programming interface (API) secret key. The API secrets would be used to sign each webhook request. This would allow you to verify that the request came from a trusted source.

## **Examples of Platforms That Use Webhooks in Their Development Process**

Many platforms use webhooks in their development process to achieve different goals. The following are some examples and use cases of webhooks explained.

### **Shopify**

Shopify is a popular e-commerce platform. Shopify uses webhooks to[ keep track of events](https://shopify.dev/api/admin-rest/2022-04/resources/webhook#top) that happen on the platform. When a customer makes a purchase, Shopify uses a webhook to send the order information to the merchant. This allows the merchant to keep track of their sales and fulfill their orders on time.

Shopify also uses webhooks to keep apps in sync with shop data or perform an action after a specific event occurs. Webhooks are a more efficient alternative to constantly polling for changes to data via an API server.

### **Discord**

Discord is a voice, video, and text chat app. It uses webhooks to[ send messages and data updates](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) to a text channel in your server. By creating a webhook endpoint in your server, you'll generate a webhook URL that you can drop into a number of other services to link the two.

For example, you could set up a webhook endpoint in your server to send a message to a Discord channel whenever someone made a post on your blog. Or, you could use a webhook to automatically keep a channel in your Discord server updated with the latest sports scores.

### **Mailchimp**

Mailchimp is a popular email marketing platform. Mailchimp uses webhooks to[ keep track of events](https://mailchimp.com/developer/marketing/guides/sync-audience-data-webhooks) that happen on the platform. Mailchimp uses a webhook to send the subscription information to the list owner when a user subscribes to a list.

Webhooks are also helpful tools that can be used to collect information about audience changes in Mailchimp as they happen. By entering a valid URL that is set up to accept HTTPS POST requests, you can receive updates on subscriptions, changed email addresses, campaign sending, and more. Webhook can also be used to keep your client's profile data in sync with your database, detect when an email address starts bouncing, or alert your application when a campaign has finished sending.

## **How You Can Implement Webhooks Into Your Authentication or Development Strategies**

Now that you know what webhooks are and how they can be used, you may be wondering how you can implement them into your authentication or development strategies.

One way to use webhooks is to set up a webhook endpoint in your server. This endpoint would be responsible for handling all webhook requests. The endpoint would need to be able to authenticate the request and process the data. Once the request is authenticated, the endpoint will take the appropriate action.

Another way to use webhooks is to use them as part of your authentication strategy. Webhooks can be used to verify that a user is authorized to access data. One way to do this is to use a secret key. The secret key would be used to sign each webhook request allowing you to verify that the request came from a trusted source.

If you're looking for a[ flexible, multi-factor authentication service](/features/multifactor-authentication) that can easily integrate with your webhook endpoints, Clerk is here to help. Clerk is the leading authentication and authorization services provider in the industry. [Try Clerk for free today](https://dashboard.clerk.com/sign-up) and learn how to implement authentication into your security strategy.

---

# What Is an SDK and How Is It Different From APIs?
URL: https://clerk.com/blog/sdk-vs-api.md
Date: 2022-08-10
Category: Insights
Description: While an SDK and an API often work together in the software development process, they each serve a different function. Find out what that is here.

Modern software development typically involves using both software development kits (SDKs) and application programming interfaces (APIs). Even people with experience in the world of application development get tripped up over the fundamental difference between both sets of tools. Both help users improve the functionality of their applications quickly without having to construct something from the ground up. Let’s look at the core differences between SDKs vs. APIs and how they enhance the development experience.

## **What Is an SDK?**

An SDK is often referred to as a dev kit. It’s a set of software-building tools made available from vendors. Developers usually rely on SDKs to build applications using a specific programming language targeted at a particular system or platform. An example of that would be the Windows SDK managed by Microsoft, which contains various frameworks for creating applications that run on Windows computers.

An SDK makes it easier for developers to create applications that follow a standardized pattern for a specific environment. Users download the kit and other components, like prebuilt application examples and instructions. SDKs give you a head-start on building, testing, and deploying a robust application.

## **What Is an API?**

An API is a mechanism that helps two software modules communicate using specific protocols and definitions. It's a piece of software designed to fulfill a particular function. The weather app on your phone and the GPS application providing directions are examples of APIs.

The interface part of an API outlines the contract used between two applications attempting to speak to each other. Your API defines the request and response format used between the two. Developers can refer to the documentation for APIs to understand how they can set up requests and responses within applications built using an SDK.

### **How APIs Work**

The architecture of your standard API typically consists of client and server functions. An application making a request is the client, while the one providing the response is the server. Your weather app calls the weather service database, asking for information, and the database provides information about the atmosphere in your specific location.

Below is an overview of different APIs:

- **SOAP:** The Simple Object Access Protocol exchanges messages between clients and servers using an Extensible Markup Language (XML) format. The format became popular among developers in the past. The biggest drawback is the lack of flexibility in structuring requests and responses.
- **RPC:** Remote procedure calls ask the client to execute a function, called a procedure, from a server. That server processes the output and sends it back to the client.
- **REST:** Representational state transfer APIs define functions used by clients to access data from a server. Both clients and servers use HTTP to exchange information. REST APIs do not preserve data between client/server requests. Responses from servers are sent using plain data.
- **WebSocket:** Instead of XML, WebSocket APIs rely on JavaScript Object Notation (JSON) to pass data back and forth. It’s a more modern approach that allows for two-way communication between clients and servers. The ability for servers to send callback messages to connected clients increases its efficiency versus REST APIs.

## **How a Software Development Kit Differs From an Application Programming Interface**

The most significant difference between an SDK vs. an API is in how they enable development. Your SDK provides the building blocks you need to write new programs designed for specific platforms using your preferred programming language. There’s often at least one API included with most SDKs. Everything you need to construct a basic app comes with an SDK.

Developers can’t use APIs to build brand-new applications. However, they do allow applications to work together to enhance various aspects of your applications. For example, you can use an API to pull financial data and feed it into a dashboard featured on a website.

## **Common SDK Features**

Let’s look at features that are often included when you download an SDK.

### **Integrated Development Environment**

An integrated development environment (IDE) is used for creating various applications. The platform brings together numerous tools that developers rely on with one graphical user interface (GUI). Here’s a breakdown of the components of a typical IDE:

- **Source-code editor:** Developers use this screen to write software code. A source-code editor often comes with options to highlight specific syntax, point out bugs, and auto-complete phrases in lines of code to help speed up development.
- **Build automation:** This utility automates tasks used to set up local software builds for a developer. Build automation performs functions like packaging binary code and running automated tests.
- **Toolbar:** An IDE toolbar resembles one found in a word processor. It organizes different components that developers rely on as they are writing code.

IDEs help enhance a software engineer’s productivity thanks to the way they standardize the configuration of various developer tools. Everything you need is available through one interface.

### **Debuggers**

A debugger is a computer program that tests and finds bugs within a developer’s code. The debugger typically starts working as soon as you begin writing your code. As you compile your code and integrate it with other programming components, your debugger will highlight errors that keep the program from running correctly. Debuggers are essential to the development process, especially if you’re working on an application containing thousands of lines of code. You can also integrate unit testing to make things easier.

### **Code Samples**

Code samples show developers how to implement different programming scenarios or concepts. They’re also helpful in showing you how to set up more complex architecture components, like a grid. Many SDKs provide you with complete applications and the source files needed to run the program.

### **Code Libraries**

One of the main rules that programmers follow is "Don’t Repeat Yourself," or DRY. Code libraries help you stick by that principle by providing prewritten code that you can modify. These reusable blocks of code make it easy to save time while building projects or optimizing other pieces of your program. Another advantage of using tested code libraries is that they add stability to your application.

### **Documentation**

The documentation that comes with SDKs provides you with instructions on using each component and integrating it with other systems.

### **APIs**

APIs that come with SDKs contain libraries built using the platform’s core language. You can use your SDK to leverage APIs that add more capabilities to your program.

## **The Benefits of an SDK for Software Developers**

SDKs make your job as a developer more straightforward by making it easier to pull different components together to construct an application. They make integrating standard processes easier and allow you to access pertinent information while coding. Many SDKs come with built-in support and documentation to help you leverage the program effectively.

### **Enhanced Control of User Interface and User Experience**

An SDK gives you more control over the elements used to build your user interface. If a customer wants components laid out in a certain way, you can follow their requirements seamlessly with an SDK versus trying to use a basic code editor and disparate libraries. You’ll also have an easier time testing each screen element and ensuring that the users will be happy with the final product.

### **Quicker Time to Market**

The code samples provided with SDKs allow you to create or expand the functionality of your applications quickly. You can leverage APIs and other libraries to quickly set up new components for your program. That makes the application easier to debug, test, and deploy in different environments before you release it for general use.

### **Broader Integration Options for Existing Tech Stack**

With more vendors choosing to integrate APIs into their SDKs, there are more integration options available for developers. For example, if you have an application built using the .Net framework, you can still integrate the SDK with other frameworks to enhance the look of your UI.

## **Types of and Common Uses for Development Kits**

While some SDKs enable connections between different tools, others help your applications run on specific devices and operating systems.

### **SDKs by Hardware**

Many hardware providers make SDKs available to developers for programming technology like the Internet of Things (IoT) or programming robots. Having an SDK readily available for specific hardware makes it easier for developers to start their coding.

### **Open-Source SDKs**

While most SDKs come from specific vendors, you can find open-source SDKs that allow developers to modify the underlying source code. However, there can be security risks associated with working with an unsupported platform.

### **Proprietary SDKs**

In contrast to open-source SDKs, developers can’t access and modify proprietary source code. Instead, they must purchase a license permitting them to use proprietary code elements.

### **SDKs for Each Programming Language**

Below are examples of SDKs available for different programming languages:

#### **C#**

- [.NET SDK](https://docs.microsoft.com/en-us/dotnet/core/sdk)
- [Twilio SDK](https://www.twilio.com/docs/libraries/csharp-dotnet)
- [AWS SDK for .Net](https://aws.amazon.com/sdk-for-net)
- [EOS SDK for C#](https://dev.epicgames.com/docs/services/en-US/GameServices/CSharpGettingStarted)

#### **JavaScript**

- [Facebook SDK](https://developers.facebook.com/docs/javascript)
- [AWS SDK for JavaScript](https://aws.amazon.com/sdk-for-javascript)
- [Google Maps SDK](https://developers.google.com/maps/documentation/javascript/overview)

#### **Java**

- [Oracle SDK](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/javasdk.htm)
- [AWS SDK for Java](https://aws.amazon.com/sdk-for-java)

#### **Python**

- [Carto Python SDK](https://carto.com/developers/python-sdk)
- [Square Developer Python SDK](https://developer.squareup.com/docs/sdks/python)
- [Smartling Python SDK](https://help.smartling.com/hc/en-us/articles/4412947322267-Python-SDK)

#### **Ruby**

- [AWS SDK for Ruby](https://aws.amazon.com/sdk-for-ruby)
- [Oracle SDK for Ruby](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/rubysdk.htm)
- [DocuSign SDK for Ruby](https://developers.docusign.com/docs/esign-rest-api/sdks/ruby)

## **Do You Need Both an API and an SDK for Development?**

It’s possible to build applications using an SDK without relying on APIs. However, working with APIs and SDKs together helps enhance the programming experience. It’s easier to construct platforms that meet your requirements. There are SDKs available for both Apple and Android developers who want to create mobile apps for those environments.

You don’t have to think of it as a choice between using either an SDK or an API. Remember, many SDKs come with preinstalled APIs. If you want to build a website that allows users to sign in through their Facebook account, an SDK makes that much easier.

You can automate user verification using the Facebook Graph API. That way, you, as the developer, don’t have to go through the trouble of figuring out how to generate tokens, inspect them, and determine which app the user is trying to connect through. The API makes the sign-in process for your app seamless.

### **Benefits of SDKs**

SDKs help developers quickly add functionality to their applications and construct standard components. Typically, there’s no need to integrate an SDK with other elements. If you do, that might slow down your development process.

Most software engineers rely on SDKs to complete simple functions like allowing users to make mobile payments or setting up location services. Certain SDKs let you do more complex programming, like creating virtual reality (VR) and augmented reality (AR) programs.

When used correctly, SDKs help relieve the back-end burden of building software programs. You have a modular foundation to rely on that saves you much of the manual effort. Many of the apps created by software engineers contain a few features that serve a common purpose.

For example, a telemedicine app might offer chat features that let users reach out to medical professionals with questions or concerns. A mobile insurance app would contain features that allow users to check on a claim payment's status or print out a copy of their insurance card.

The efficiency provided by an SDK makes it easier for dev team members to work independently. It limits the number of common touchpoints, decreasing the risk of one person breaking another team member’s code during an update.

Adding APIs into the mix cuts down on lag time because of the research needed to figure out how to build a new capability. Working with an API means developers have to worry only about the necessary pieces that make their application work the way they want it to, eliminating the need to dive into how everything works under the surface.

## **Other SDK Considerations**

Some SDKs have agreements to which you must provide consent before you are allowed to use the software. Vendors often make new versions of SDKs available for alpha or beta testing, meaning they are not yet publicly available. Those features you try out could undergo modifications or changes before the SDK’s general release. Certain features may fall under a license agreement, so you have to be careful that you do not develop a project that falls outside of its scope.

Read through all the documentation of any SDK you want to use and make sure there is nothing that conflicts with your desired usage. You can’t develop proprietary apps using an SDK with a General Public License. You should also look for any constraints around SDKs that come with a Lesser General Public License (LGPL) if you intend to build a project containing proprietary elements. Think about the ease of implementing security features like multifactor authentication.

### **Commercial vs. Open Source**

Organizations also have to think about the cost of using an SDK. Many are tempted to use open-source SDKs because they’re free. However, your company could still end up paying if there’s a need for developers to spend hours getting up to speed on how the software functions. The cost of the time lost trying to figure out how an open-source SDK works could exceed what you might pay for a licensed version.

Commercial products do bring expenses associated with paying for licenses and integrating the components into current applications. However, you can turn to the vendor for support when you have questions. Paid SDKs tend to be more secure, which lowers the risk of your SDK becoming a gateway for a cyberattack.

You also have to think about the ease of using the SDK in your development shop. The goal of an SDK is to make coding easier. If you’re spending more time getting the application to function correctly than building software, there's a problem. Think carefully about implementing an open-source SDK. If your company has knowledgeable staff who are comfortable working with the product and bringing other developers along, you can succeed.

Usability is often the most significant advantage commercial products have over open-source SDKs. Even if you have developers who are capable of leveraging an open-source SDK, you have to think about who might be asked to maintain those applications if they end up moving on to another position or leaving the organization. How easy will it be to bring other software engineers up to speed on the SDK?

You should also look at the support provided by the SDK manufacturer. With open-source SDKs, there may be only online communities to turn to instead of a fully knowledgeable staff. If you have questions, there’s no guarantee that you’ll get timely answers or that there will be someone available who can help.

## **A Roundup of SDKs vs. APIs**

SDKs provide developers with everything necessary to create or modify applications. Many come with prebuilt code that helps software engineers get started on their applications. APIs create connections between two applications and allow developers to expand the functionality available within a program.

It’s easier for developers to become more efficient by using SDKs and APIs together. When deciding on an SDK, look at whether you’re really saving by going with an open-source version when it comes to the cost, time, and effort. If your development team is unfamiliar with the platform, you could lose time and money trying to adapt.

Make sure that your SDK does not come with license restrictions that would impact your development. Explore the support that would be available to you or your dev team if you were to run into problems with your SDK.

***Ready to implement your own authentication?***

Clerk has been built with developers in mind and allows you to add authentication to your application with just a few lines of code. [Get started for free today](https://dashboard.clerk.com/sign-up)!

---

# A ‹Component/› is worth a thousand APIs
URL: https://clerk.com/blog/a-component-is-worth-a-thousand-apis.md
Date: 2022-08-07
Category: Company
Description: Clerk is the only authentication service that offers a User Profile component. It sounds incremental, but it's 10x more work – this post explains why

Clerk started with a simple vision. We loved the professionalism of Google's Sign Up, Sign In, and User Profile, so we set out to build developer tools that would help everyone match their caliber.

![A Component Is Worth A Thousand Apis guide illustration](./a0904584e9cb4e0751a833c1bc0bdd14f5060fa2-1080x494.png)

With UIs as our primary goal, we realized that Clerk wouldn't be a traditional API company. We focused on building a fantastic frontend component SDK, rather than a traditional backend REST SDK.

We chose React as our first target given its popularity, and split Google's surface area into four components: `<SignUp/>`, `<SignIn/>`, `<UserProfile/>`, and `<UserButton/>`.

![A Component Is Worth A Thousand Apis guide illustration](./e9dbf939e2b523fdf51e5f9e59a6f5e16907298b-2458x1248.png)

Components are a higher-level of abstraction than REST SDKs. They provide UIs to end-users instead of just a function to developers, so they inherently offer more value.

But what's surprising is just *how much* more value. Even at Clerk, we assumed we could just "slap a UI on top of an auth API." Despite having a team full of seasoned engineers, we failed to realize just how much work sits between traditional APIs and the end-user features they enable.

### Stripe example

As an example outside of authentication, let's compare Stripe's original 9 lines for creating a charge, to the *sidebar* for their current Checkout documentation:

![A Component Is Worth A Thousand Apis guide illustration](./cccc2d59d94fa8b00928e84940a25f5392dbbb90-1082x981.png)

Checkout has far more complexity than the original Charge API, but why? Aren't both responsible for charging a customer?

The difference is that Charge asked for the exact amount to charge, while Checkout needs to display *why* an amount is being charged. It needs all of the context of the Products being purchased, their Price, the quantity, the taxes and shipping costs, any discounts applied, and more. Stripe needed to build dozens more API resources and paramaters to produce the end-user Checkout UI.

Before Checkout, this additional context lived inside the developer's application. Now that it lives inside Stripe, charging customers has become massively easier. Stripe solves so much more complexity for developers today than it did 10 years ago.

### Clerk example

Clerk is seeing the same patterns in authentication that Stripe saw in Checkout. To build our core components, we need to manage much more complexity than legacy vendors like Auth0.

This is particularly apparent with our `<UserButton/>` and `<UserProfile/>` components. We are the only authentication provider to offer these, and there's a foundational reason why: **Clerk is the only authentication provider that manages sessions as-a-service.**

Legacy vendors focus on just the sign-up and sign-in screens. Once the user's identity is verified, the session is managed within the application – not within the authentication service. This makes it impossible for them to offer drop-in `<UserButton/>` and `<UserProfile/>` components like Clerk.

And since we're not ones to cut corners, our session management solution is fully featured. We include active device management from within `<UserProfile/>`, so users can remotely force sign outs from other devices:

![A Component Is Worth A Thousand Apis guide illustration](./3135b92fe15d7d789429299c6354d1662ea941b1-616x391.png)

Plus, we (optionally) include account switching within `<UserButton/>`, just like Google's:

![A Component Is Worth A Thousand Apis guide illustration](./c962088265770e23f04b1cf2b0b5eeba2c32d2b6-471x527.png)

Beyond session management, we also enable self-serve two-factor authentication from within `<UserProfile/>`:

![A Component Is Worth A Thousand Apis guide illustration](./dfec3db47a85e8f1f17f882a97c2b00bcbdf2ab5-615x352.png)

Once setup is completed, `<SignIn/>` will automatically request the second factor during the next sign-in:

![A Component Is Worth A Thousand Apis guide illustration](./478885fd08c6525391c6878688bea54c3d091274-526x527.png)

If Clerk didn't manage sessions and two-factor authentication, developers would be stuck implementing these features from within their application – a much more challenging prospect than simply using `<UserButton/>` and `<UserProfile/>`.

### On components vs redirects

Some readers may be aware that Clerk uses embeddable components while Stripe Checkout uses a redirect flow. That's completely correct, so we kept this blog focused on points that remain true regardless of how the UI is ultimately presented to the end-user.

That being said, there is one advantage to components that deserves a special callout:

At Clerk, every component we build is composed using React hooks, and the hooks we use are actually pacakaged alongside our components. So, if frontend developers don't like our components for any reason, they can still build their own UIs **without involving a backend developer and a backend SDK.**

This extra layer of composability has been a huge boon for companies with strict branding requirements, since we eliminated the need for backend application logic regardless of if our UIs are used.

### In summary

We've seen this pattern enough to say confidently: **a `<Component/>` is worth a thousand APIs.**

Components have become the new gold-standard in developer tools – they are the new, optimal, composable building block. They save developers far more time than traditional REST SDKs, both by providing end-user UIs, and by eliminating huge swaths of code that used to be managed in-house.

---

# User Management and How It Relates to Authentication
URL: https://clerk.com/blog/user-management-in-authentication.md
Date: 2022-08-03
Category: Insights
Description: User management assists in authenticating and storing users. Find out more about it here.

**User Management and How It Relates to Authentication**

User management identifies and authorizes users in order to provide secure access to digital resources. This process usually involves an authentication procedure that confirms the user's identity without revealing the password. This article discusses user management and authentication in detail.

You will learn what user management is and how it relates to authentication. Additionally, you will look at different types of authentication and how they are used in user management systems. Finally, you will take a closer look at traditional approaches to user management versus real-time approaches. Read on to learn more!

## **What Is User Management?**

User access management is [the process of identifying, authorizing and authenticating users](https://cloud.ibm.com/apidocs/user-management) on authorization platforms. This process usually starts with user registration, where the user provides their personal information. Once the user is registered, they can sign in to the platform. During sign-in, the user's identity is confirmed, and they are given access to the platform.

User management has four main aspects: user profiles, user properties, user privileges, and user migration.

### **User Profiles**

User profiles contain the user's personal information, such as user names, contact details, and photograph. This information is used to identify individual users and is usually stored in a database. User profiles can also contain other information, such as user creation method, and users' preferences and interests.

### **User Properties**

User properties are specific attributes assigned to individual users that identify them within the system. These attributes can include the user's name, contact information, and role within the company. User properties can be static, such as individual user type (e.g. administrator, user, guest), or dynamic, such as a user's current status (e.g. active, inactive, suspended). User properties are used to identify users within the system.

### **User Privileges**

A user privilege, on the other hand, is a permission that allows a user to perform certain actions, such as creating new users or accessing restricted areas of the system. For example, a user might be given the privilege to view customer data or to create new categories in the product database. User privileges define custom user roles i.e., what a user can do and are used to control user's level of access within the user interface.

### **User Migration**

User migration is the process of moving user data from one platform to another. This is usually done when users change the user type or are deleted from the system. User migration can be a complex process, depending on the size and complexity of the user data.

## **Benefits of a User Management API**

A user management API (Application Programming Interface) [is a set of software instructions that allow one application to interact with another](https://www.forbes.com/sites/moorinsights/2020/08/06/for-devops-application-programming-integration-api-is-a-major-security-vulnerability/?sh=79fdba931f20). An API can be used to create, read, update and delete user profiles. It can also be used to manage user access and privileges.

Using an API to manage users has many benefits, including:

### **Ability To Manage User Identities and User Access**

API-based user access management allows you to manage users and their access to your platform from a central location. This means that you can easily add, remove or update user accounts without having to make changes to your code. Additionally, it is easier to keep track of user activity and identify potential security risks.

### **An Enhanced User Experience**

API-based user management can provide a better user experience by allowing users to self-register and sign in using their own social media accounts. This eliminates the need for users to remember multiple usernames and passwords. Additionally, API-based user management enables you to provide a personalized experience for each user by tailoring the content and functionality of your system to their specific needs.

A user access management API provides many other benefits for users and website administrators. For instance, an API can allow user synchronization across multiple devices and platforms. This means that users' preferences and settings can be seamlessly applied without regard to their sign-in location.

In addition, an API can allow you to create custom user roles. This is beneficial for websites that need to give specific users different access levels. Administrators can create a more seamless and user-friendly experience by using a user management API for all users.

### **Compliance With Security Policies**

API-based user access management can help you comply with security policies, such as the EU [General Data Protection Regulation (GDPR](https://gdpr-info.eu) and the [U.S. Privacy Act](https://www.hhs.gov/foia/privacy/index.html#:~:text=The%20Privacy%20Act%20of%201974,other%20identifying%20number%20or%20symbol.). This is because an API allows you to control how your user data is collected, used and stored. Additionally, an API can help you keep track of user activity and identify potential security risks.

### **A Reduction in Password Issues**

API-based user management can help to reduce password issues, such as forgotten passwords and resetting passwords. This is because an API allows you to use various authentication methods, such as social media sign-in or two-factor authentication. Additionally, an API can help you keep track of user activity and identify potential security risks.

## **What Is Authentication and How Does It Relate to User Management Systems?**

Authentication is the [process of verifying the identity of a user](https://www.forbes.com/sites/davidbalaban/2021/07/27/what-is-authentication-and-how-does-it-work/?sh=33d355b7e2bc). This can be done in a variety of ways, including using a username and password, using a biometric identifier, or using a physical token. User management systems are responsible for managing users' identities within small-and medium-sized businesses (SMBs). This includes creating and maintaining user accounts, assigning permissions to users, and resetting passwords.

Identity and access management (IAM) is a term that is often used interchangeably with the user access management system. However, IAM is a more comprehensive term that encompasses [all of the processes and technologies used to manage user identities](https://www.forbes.com/sites/davidbalaban/2021/07/27/what-is-authentication-and-how-does-it-work/?sh=33d355b7e2bc), including authentication.

When it comes to authentication, user management systems and IAM systems are responsible for managing the credentials that users need to access accounts. This includes storing passwords, generating and issuing tokens, and managing the authentication process.

The relationship between authentication and user access management systems is an important one. User access management systems are responsible for managing users' identities, and authentication is responsible for verifying those identities. Without both of these systems in place, it would be impossible to manage user accounts and ensure that only authorized users have access to them.

There are various authentication methods that SMBs can use, and the best method for a given SMB will depend on its specific needs. User management systems and IAM systems can help SMBs choose the suitable authentication method for the identified needs and ensure that users' identities are properly verified.

## **Types of Authentication for a Frictionless Experience**

There are many different types of authentication, each with its strengths and weaknesses. When choosing an authentication method, it is crucial to consider both the user experience and the security of the system.

One of the most common types of user authentication is single-factor authentication. This method relies on a single piece of evidence to verify the user's identity. The typical form of single-factor authentication is a password. While passwords are relatively easy to use, they can be cracked or guessed if they are not strong enough. As a result, many SMBs are moving to two-factor authentication.

Two-factor authentication adds an additional layer of security by requiring two pieces of evidence to verify the user's identity. The most common form of two-factor authentication is a combination of a password and a physical token, such as a key fob or a card.

Two-factor authentication is much more secure than single-factor authentication because it is much harder for an attacker to get both pieces of information. However, it can inconvenience users who for some reason lose access to the chosen second factor.

Biometric user authentication is another user authentication type that is gaining popularity. This method uses physical or behavioral characteristics to verify the user's identity. Common examples of biometric user authentication include the use of fingerprint scanners, and iris or facial recognition to verify user identity and grant access permissions.

Biometric authentication is more secure than other methods, such as passwords, because it is very difficult to fake someone's biometric information. Additionally, biometrics can be used in conjunction with other methods, such as two-factor authentication, to further improve security. Correct system design is critical to a positive user experience.

Another method of authentication is to use a physical token. This can be in the form of a card, a key, or a badge. The user must have the physical token in order to sign-in. This is more secure than password authentication but loss of the token will necessarily result in user inconvenience.

There are many different types of authentication, but not all of them are equally effective. When choosing an authentication method, it is crucial to consider the user experience as well as the security of the system.

## **Traditional Versus Real-Time User Management Approaches**

There are two approaches to user management: traditional and real-time. Traditional user management is the process of creating, storing, and managing user accounts and passwords. Real-time user management is the process of authenticating user accounts in real time, as users request access to resources.

The traditional approach to user management is time-consuming and error-prone. It requires IT staff to manually create user accounts, assign passwords, and keep track of user activity.

This approach is vulnerable to password attacks, such as [brute force and dictionary attacks](https://www.kaspersky.com/resource-center/definitions/brute-force-attack). It is also susceptible to [social engineering attacks,](https://www.itgovernance.co.uk/social-engineering-attacks) where attackers trick users into revealing user names and corresponding access permissions.

The real-time approach to user access management is more efficient and secure. It uses an authentication server to validate user credentials in real-time. This approach eliminates the need to store user passwords, which reduces the risk of password attacks.

This approach eliminates the need to create and manage user accounts manually. It also reduces the risk of password attacks by validating user credentials before storing them on the server.

The real-time approach to user access management is the preferred method for managing user accounts. It is more efficient and secure than the traditional approach.

## **How Authentication Services Aid User Management**

User access management and authentication go hand-in-hand. Authentication services provide the foundation for keeping user data secure, while user access management tools help maintain control over who has access to that data. By integrating these two technologies, small-and medium-sized businesses can increase security and efficiency while reducing the risk of data breaches.

### **Security Settings**

Start-ups can use authentication services to control access to data and applications. By setting up user groups and assigning permissions, administrators can ensure that only authorized users have access to sensitive information. Additionally, platform administrators can use authentication services to track user activity and monitor suspicious behavior.

#### **Password Management**

One of the most critical aspects of user security is password management. Authentication services can help small-and medium-sized businesses enforce strong password policies and prevent users from reusing passwords across different systems. Identity access management services can also provide a single location from which to manage access to your network users' data, making it easier for users to keep track of sign-in information.

#### **Management of Different Devices**

With the rise of mobile and the practice of allowing employees to use their own computers, phones, or other devices for work purposes (BYOD, or bring your own device), it is more important than ever for startups to be able to manage and control access to data from a variety of devices. Authentication services can help by allowing administrators to set up device-specific permissions and enforce security policies. Identity access management services can also offer a centralized platform for controlling and tracking user activity, which makes it much simpler to identify suspicious behavior across multiple devices.

#### **Multi-Factor Authentication**

Another way to improve security is to require users to authenticate with more than one factor. User platforms can employ multi-factor authentication by using a combination of passwords, biometrics, and tokens. By requiring users to provide multiple forms of authentication, SMBs can increase user interface data security and reduce the risk of unauthorized access.

### **User Profile Management**

User profile management is the term used to describe the process of creating and managing user accounts. User management tools can also be used to manage user profiles. This includes setting up new user accounts and managing user permissions, email addresses, social media accounts, and other user-related information.

By centralizing this information, SMBs can reduce the risk of data breaches and make it easier for users to keep track of sign-in information.

#### **Email Address Management**

Small-and medium-sized businesses can employ user access management tools to manage email addresses. This includes verifying, adding, removing, and updating email addresses.

A user management platform needs to be able to handle bounced emails and other problems that can occur with email addresses. Additionally, user access management tools can be used to set up email forwarding and provide a central location for managing email addresses.

#### **Social Sign-in**

Another critical aspect of user management is social sign-in. Social sign-in allows users to sign-in with existing social media accounts instead of creating new ones. User management tools provide a central location for managing social media accounts, i.e., adding, removing, and updating social media accounts related to individual users.

By integrating authentication services and user access management tools, startups can increase security and efficiency while reducing the risk of data breaches. Startups can accomplish a lot with these tools, i.e., control access to data, enforce strong password policies, and require multi-factor authentication.

User management tools can also help manage user profiles and reduce the risk of data breaches. These technologies can help SMBs keep users data safe and secure when used together.

User profile management is a vital part of any platform that relies on central user identity. It would not be easy to control who has access to what resources without proper identity access management.

## **How To Find the Cloud-Based User Management System for You**

Effective user management is a critical part of any business, and it can be challenging to find the right system for your needs. There are a few things to consider when choosing a user management system.

The first question is how many user names you need to manage. You may not need a full-fledged user management system if you only have a small user base.

You'll also want to consider the features that you need in a user interface. Some identity access management systems offer more features than others. If you need specific features in your user interface, you'll want to choose a system that provides them.

Another thing to consider is how easy the system is to use. You'll want to choose a system that is easy to use so that you can manage your users without any problems.

Finally, you'll want to consider the price of the system. User management systems can vary in price, so you'll want to choose one that fits your budget.

You can narrow down your options by considering these factors and find the appropriate user management service provider for your needs, like Clerk.

Clerk provides the tools you need to manage your user identities and access permissions while also enhancing your user experience. With our services, you can rest assured that your authentication process will be smooth and compliant with any security policies you may have in place.