# Clerk Blog — Page 14

# Session management: What it is and why your security depends on it
URL: https://clerk.com/blog/what-is-session-management.md
Date: 2021-09-21
Category: Insights
Description: Learn about session management, its components, and security concerns.  

Constantly having to log back in to your online accounts is a frequent annoyance — but this irritating problem stems from an inefficient solution to a genuine security concern.

Web applications need to make sure that your accounts are safe from hackers, and some handle that by requiring frequent re-authentication. Still, that’s not the best solution. Proper session management can help apps like yours keep users safe *without* needing to constantly log back in.

Below, we’ll cover the fundamentals of session management, what’s required to implement it, and how it can help you keep your users safe without creating a frustrating user experience.

## What is session management?

[Session management](https://www.packetlabs.net/session-management) is the process of facilitating private interactions between users and web applications. It specifically refers to managing different “sessions,” or periods when the user is logged in and active in the application. The session management process lets users access their unique and potentially sensitive information securely without letting others get into their account, without forcing users to constantly re-authenticate.

Session management can take two forms: short-lived and long-lived. Short-lived sessions last only as long as the user remains in the application. Every time they leave the app, they need to re-authenticate to get back in.

Long-lived sessions keep the user logged in to the app even if they leave. These sessions store session IDs on the user’s device, allowing them to reopen the app and start using it without needing to re-authenticate.

Long-lived sessions typically offer the best user experience, since they let people get into their accounts with no hassle. But this approach also has drawbacks. Anyone who accesses the device can also access that account as long as the session is still active, which is a security risk. For apps that contain sensitive information, short-lived sessions may make the user experience slightly more complicated, but will be more secure.

## The elements of session management implementation

Proper session management implementation involves three functions: creating session IDs, storing session cookies or tokens, and enforcing session expiry dates.

Here’s what that means:

### Session IDs

When the user first logs into the website or app, the server creates a unique session ID associated with the authenticated user. However, with each new request, the server still needs a way of identifying if the request came from that authenticated user without needing re-authentication. Which is where cookies or [JWT](https://en.wikipedia.org/wiki/JSON_Web_Token) tokens come in.

### Session cookies vs. tokens

When the server creates a unique session ID, it also creates a cookie that is stored in the user’s browser. The information contained in that cookie is sent along with each new request so the server understands it comes from the same authenticated user.

Session cookies are most commonly used with websites or web-based platforms. When it comes to modern web applications, a JSON Web Token, or JWT, is used instead.

When the user logs on with the right credentials, a JWT is created instead of a session ID and sends it to the user. The JWT is stored in local storage and the header of the token is sent with every new request.

This means that the user’s state is not stored on the server, but inside the token, making this option more scalable and more useful for mobile device authentication.

### Session expiry

Sessions are temporary states and expire under certain circumstances, such as the mobile app being closed, a set period of inactivity, or a maximum session duration that cannot be exceeded. Long-lived sessions may expire when the user hasn’t interacted with the app in a certain number of days or weeks. The cookie or token storing the session ID should automatically delete itself at the end of those periods.

## Security concerns addressed by well implemented session management

The purpose of session management is to help keep user data secure. Without appropriate session management, you can run into several security problems, putting your users at risk. Common vulnerabilities caused by a lack of or poorly implemented session management include:

### Session hijacking

The cookies that you use to store session IDs need to be truly secure. Insecure session cookies are easy for hackers to predict or to use for brute-force attacks. If a hacker can spoof your users’ session IDs, they can impersonate users and take over their accounts. This is known as session hijacking, and it can lead to the loss of sensitive information connected to the account.

### Session fixation

If a specific session token can be used across platforms and without proper expiry protocols, it can be “fixated” by hackers. Essentially, the hacker tricks a user into logging in with a specific session ID, often by adding to the session ID in the URL argument, and then uses those credentials to log in to the user’s account.

### Session resources

Session management systems should beare resource-light, so that attacks, such as denial of service (DDoS) that flood the system with new session requests, don’t consume huge amounts of resources.

### Anomaly detection

Every application runs the risk of hacking attempts. If your session management tool doesn’t have a way to detect abnormal patterns like brute force session ID guessing or DDoS attacks, you’re more likely to fall victim to these attacks.

### Session expiry unset or too long

Session expiration has two potential problems. If you don’t set the timeout period, many programs may leave the cookie or token on the device forever, leaving the account vulnerable to anyone else with the device. Also, a set timeout period that’s too long has the same issue.

## Stay secure with session management

Proper session management addresses all these concerns. It keeps your users and accounts safe by providing secure cookies or tokens, setting appropriate protocols and timeouts, and implementing anomaly detection.

Session management is a fundamental part of running a secure, trustworthy web application. By keeping a handle on your users’ sessions, you can help them avoid the hassle of constant re-authentication without putting them at risk.

You can address all your session management needs by implementing a [user management](/) service, or you can write your own. Either way, your users will thank you for protecting them without making their lives more difficult.

---

# Don’t underestimate the value of a secure, seamless ‘forgot password’ flow
URL: https://clerk.com/blog/forgot-password-sspr.md
Date: 2021-09-16
Category: Insights
Description: Learn about “forgot password” flows, how they work, and the best practices to keep in mind.


Just about every software application today relies on individual user accounts to provide people with a personalized and private experience. However, as [“software eats the world,”](https://a16z.com/2011/08/20/why-software-is-eating-the-world) the average user is managing an increasing number of accounts. Practically every online store, social media platform, SaaS product, newsletter, game, and group requires users to create an online account with a username and password. The average American adult has a total of [130 online accounts](https://www.prweb.com/releases/dashlane_study_us_internet_users_drowning_in_online_accounts_with_further_tidal_wave_approaching/prweb12860738.htm) — and they all need to be kept secure, which exacerbates an already all-too-common problem: lost and forgotten passwords.

That’s why most apps offer password reset flows. This essential workflow allows users to reclaim their accounts while maintaining their security and privacy. Keep reading to learn about “forgot password” flows, how they work, and the best practices to keep in mind.

**‌**

## **What is a ‘forgot password’ flow?**

If you’ve ever had to reset a password, you’ve gone through a “forgot password” flow. Users go through this self-service process to reset their passwords and reclaim their accounts. Any website, app, or other account that relies on passwords for security should have some kind of reset flow.

**‌**Why? Because users are prone to forgetting their passwords. It’s also common for people to forget their accounts entirely or change devices and lose their saved passwords. Without some way for users to quickly and easily reset passwords and reclaim accounts, you may lose users, have to support multiple accounts for the same user, and/or deal with an overwhelming number of “forgot password” support requests.

**‌**

## **How ‘forgot password’ flows work**

Password resets can be manual or automatic. Manual resets rely on the user reaching out to support by email or phone. The support team member asks them some kind of security or verification questions and resets their password accordingly. However, manual flows mean that a significant percentage of your support tickets will be password resets, taking up your staff’s valuable time. Additionally, manual verification is often less secure than an automated process, and can be especially frustrating for a user that needs access quickly.

**‌**The alternative is to implement a [self-service password reset](https://www.hcinnovationgroup.com/home/article/13005329/password-resetting-goes-the-selfservice-route) (SSPR) process. These automated workflows allow users to reset their passwords or reclaim their accounts without human intervention. They’re used by most websites, apps, and other password-protected systems to streamline the security process. Your support staff won’t need to spend time answering password reset claims and can focus on more important work.

Each type of self-service flow works a little differently. For example:

- **Temporary passwords:** This process will send the user a temporary password that they can use to access the system. The user then resets their password themselves once they’re logged in.
- ‌**Email verification:** The system emails the user a link at their primary email address, and the link takes them to a dedicated password reset page.
- ‌**SMS verification:** The system sends the user a text to confirm they want to reset their password, with instructions to follow the reset link.
- ‌**Passwordless logins:** Passwordless flows send a one-time link to the user’s email or phone, allowing them to log in without resetting their password at all. This can be great for a user that just wants to log in from a different device one time, or is pressed for time and wants to reset their password later on
- ‌**Two-factor authentication (2FA) reset:** Two methods are used instead of one to confirm the reset. The user confirms their identity one way and then resets their password with another method. The system may have them check their email or phone for the reset link, and then on the reset page, it may ask for a code that was sent to their phone or a sign-in authentication app.

**‌**

## **Why implementing SSPR workflows can be challenging**

While password reset systems are essential, they can be a complex feature to implement on your own. Rolling your own password reset process means dealing with:

- **The constant evolution of best practices.** [Best practices](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Forgot_Password_Cheat_Sheet.md) regarding SSPR workflows are constantly evolving - from manual reset to security questions to email reset to SMS workflows to passwordless logins. You should keep up with these changes to make sure your password reset process stays secure and up-to-date.
- ‌**Security maintenance.** Password resets need to be a secure workflow end-to-end, or your users’ accounts are at risk of being hacked. If you write your own, designing a secure process is your responsibility.
- ‌**Design and integration.** Your reset process might be technically sound, but it should also be frictionless and well-designed, as an easy sign in experience is critical to retention.
- **Complexity**. Adding more authentication features and options can provide an excellent user experience when everything works right, but it also creates the potential for more “edge cases” where problems occur.

**‌**‌**‌**

## **Get started with password resets today**

If your team has more pressing features to focus on than creating a password recovery flow, [Clerk](/) can eliminate the guesswork (and real work) of user management and authentication. Clerk makes it easy to add complete user management to your app in minutes today, while allowing you to easily make changes and add new features in the future.**‌**

---

# Add authentication to your Gatsby app
URL: https://clerk.com/blog/add-authentication-to-your-gatsby-app.md
Date: 2021-09-15
Category: Guides
Description: Learn how to add authentication and user management to your Gatsby app with Clerk. 

At Clerk, our mission is to empower every developer to easily add authentication and user management to their apps.

We know it's hard to keep up with all the exciting new options out there, so we strive to create more tools and integrations, so you, the developer, can spend more time building what really matters: your app.

With that in mind, we're happy to announce our `gatsby-plugin-clerk`.

## What it does

The plugin wraps our `ClerkProvider` component around the entire Gatsby app.

This has two benefits: keeping the layout component cleaner while grouping all the configuration in `gatsby-config.js`, alongside other plugins.

## How to use it

First and foremost, install the necessary packages:

```sh
yarn add gatsby-plugin-clerk @clerk/clerk-react

# or

npm install gatsby-plugin-clerk @clerk/clerk-react
```

Now, let's configure the plugin on `gatsby-config.js.`

For this step, you'll need the `frontendApi` key of your Clerk application. To find it, go to your [dashboard](https://dashboard.clerk.com), choose the application and the instance you're working on, and locate the key on the **Home** tab.

```javascript
// gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-clerk',
      options: {
        // OBS: Don't push your frontend API key to version control.
        // A safer approach is to set it as an environment variable for each environment your app will run in.
        frontendApi: 'YOUR_FRONTEND_API_KEY',
      },
    },
  ],
}
```

From here onwards, everything should work just the same. You can start using components like `SignedIn` and `SignedOut` from the root of your app.

```jsx
// src/pages/index.js

import React from 'react'
import { SignIn, SignedIn, SignedOut, UserButton } from '@clerk/clerk-react'

function IndexPage() {
  return (
    <>
      <SignedIn>
        <UserButton />
      </SignedIn>

      <SignedOut>
        <SignIn />
      </SignedOut>
    </>
  )
}

export default IndexPage
```

And that's it, in just a few steps, we added easy and secure authentication with beautiful and complete user management to your Gatsby app.

## Bonus: Clerk + Gatsby starter

To make it even easier for you, we went ahead and created a [Clerk + Gatsby starter repository](https://github.com/clerkinc/clerk-gatsby-starter). It has Clerk integrated with [Gatsby's default starter](https://github.com/gatsbyjs/gatsby-starter-default).

Inside `src/api` you can also find the new Gatsby Functions in action. We added a couple of examples there, so you know how to use Gatsby's serverless functions with Clerk's backend API.

Fork it, clone it and build it!

## Bonus 2: Deploy the starter on Gatsby Cloud

Ok, we owe this one to the Gatsby team. They did a great job in building a super easy deployment flow.

So, if you want to deploy the [Clerk + Gatsby starter](https://github.com/clerkinc/clerk-gatsby-starter) on Gatsby Cloud, just click [here](https://www.gatsbyjs.com/dashboard/deploynow?url=https://github.com/clerkinc/clerk-gatsby-starter).

Once there, you can configure a number of things, like the Gatsby Cloud workspace the project should live in, the repository name that will be created in your GitHub account, and even add more integrations.

But here's the one thing you can't forget: your need to add your environment variables, like in the image below. If you don't know where to find them, check the [README](https://github.com/clerkinc/clerk-gatsby-starter/blob/main/README.md) file of this starter.

![Add Authentication To Your Gatsby App guide illustration](./37292ec19825df500deddefc4a6d70f7c3a52a72-1782x928.png)

Once you're done, head over to your GitHub account, find the newly created repository, clone it and start building.

And just like this, you can use all the benefits and performance that Gatsby Cloud provides to Gatsby apps.

*If you encounter a permissions error while doing the steps above, here's what's happening: Gatsby Cloud requires permissions to create and manage future repositories on your GitHub account in order to create a new repository for you.*

*To fix it, go to your [GitHub installations page](https://github.com/settings/installations), and configure Gatsby Cloud as such:*

![Add Authentication To Your Gatsby App guide illustration](./12c63a17a9f99acbc4fa4a623c613da79efac314-1498x546.png)

## Need help?

If you're unfamiliar with how our prebuilt UI components or other details described in the guide work, you can always go to our [documentation](/docs) to find out more or reach out to us on our [Discord](https://clerk.com/discord) server.

Happy coding!

---

# Authenticated data access using Clerk, Prisma, and MongoDB - A post-making fullstack app
URL: https://clerk.com/blog/clerk-prisma-mongodb-fullstack-post-app.md
Date: 2021-08-17
Category: Guides
Description: Add a complete authentication workflow with authenticated access to your Prisma API layer to your web application.

Prisma is a server-side library that helps your app read and write data to your database in an intuitive and safe way. As a next-gen ORM, Prisma lets you increase your productivity and simplify your codebase, by allowing you to write much less code for CRUD operations, and by giving you the protection of type safety.

Prisma has supported connectors for relational databases like PostgreSQL, MySQL and SQLite for quite some time. Recently though, the good folks at Prisma developed and released their MongoDB connector, which combines the type-safe Prisma TypeScript generator with the flexibility of a document store like MongoDB.\*

*\*Currently in Preview mode*

At Clerk we've been really excited about this release, so, we decided to showcase how you can easily add a complete authentication workflow to your web application along with authenticated access for your Prisma API layer.

## The post publishing application

You can find the full source code of this example in our Clerk-Prisma [starter repository](https://github.com/clerkinc/clerk-prisma-starter).

This example application will let you create an account, create posts for others to see, and browse existing user posts. Random idea sharing at its best!

![Clerk Prisma Mongodb Fullstack Post App tutorial illustration](./61c4e714599615331383c0058a018bf5b7226bf7-1497x911.png)

## Setting up the application

To run this application properly you need to configure your Clerk application, create a [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) database instance, then follow the [instructions in the repository](https://github.com/clerkinc/clerk-prisma-starter/blob/main/README.md).

### Creating a Clerk application

If you are new to Clerk you will first need to [create an account](/), then create a new application. For this application, choose the "Standard Setup". Creating a Clerk application will automatically create a development instance, which is what you'll be using.

### Creating a MongoDB Atlas database

MongoDB Atlas is the database-as-a-service solution provided by MongoDB, that gives you all the goodies of a world-class managed database service. From cross-regional resiliency, to security and performance monitoring, MongoDB Atlas is a great choice both for quickly spinning up a MongoDB instance in the cloud, and for companies that require enterprise level services.

Since we just need to get a database instance as quickly as possible for our example project, the forever-free tier is more than enough. Simply sign up, create a database, and **retrieve your secure connection URL**.

*Note: If you would rather use a local database instance, remember that [Prisma requires](https://www.prisma.io/docs/concepts/database-connectors/mongodb#example) your MongoDB instance to be in [replica-set mode](https://docs.mongodb.com/manual/replication). This comes by default with MongoDB Atlas.*

## Show me the code

To run the full example locally, you will need to follow a few small steps. First, go ahead and clone the example application.

`git clone git@github.com:clerkinc/clerk-prisma-starter.git`

Go inside your project folder and copy the .env.example file to a .env.local file.

`cp .env.example .env.local`

### Clerk Environment Variables

You will need the Frontend API value which can be found on the [dashboard](https://dashboard.clerk.com) on your development instance's home page. Add the following to your .env.local file: `NEXT_PUBLIC_CLERK_FRONTEND_API=<your-frontend-api>`.

Next you will need the Clerk API key which can also be found on your dashboard under **Settings ➜ API** **keys**. Add the following to your .env.local file:

`CLERK_API_KEY=<your-api-key>`

### Prisma setup

For Prisma to generate the required TypeScript bindings for our code and facilitate the database access layer, we need to setup a `DATABASE_URL` environment variable beside our application schema file.

Inside the `server/db/prisma` folder, create a `.env` file and there add the `DATABASE_URL` environment variable with the connection URL for your MongoDB instance. It will look something like this:

```bat
DATABASE_URL="mongodb+srv://username:pass@dblocation/myFirstDatabase?retryWrites=true&w=majority"
```

When this is set you can now run the Prisma code generator. The Prisma schema that we have used for this application, signifies to the Prisma ORM that we would like to create a collection of Post documents with the fields and connections as shown below:

```
model Post {
 id          String   @id @default(dbgenerated()) @map("_id") @db.ObjectId
 createdAt   DateTime @default(now())
 title       String
 body        String?
 views       Int      @default(0)
 author      String
 authorEmail String

 @@unique([authorEmail, title])
}
```

Prisma provides a [multitude of helpers](https://www.prisma.io/docs/concepts/components/prisma-schema) to apply on your data model definition which you can use to describe relationships, set constraints and configure attribute types. All that configuration is in code, making it a much more familiar environment for application developers with zero amount of boilerplate.

To generate the TypeScript API for accessing this model, inside the repository, execute the `npm run schema:generate` command. This will create all the required types and APIs to use your MongoDB Posts collection which you can import directly from the `@prisma/client` package. You can use the types both for the entities and the database operations, as shown in the `types/index.ts` file.

### Use Prisma Studio to add a few posts

Another great tool from the Prisma team is Prisma Studio. Prisma Studio gives you a visual data editor with direct access to your database.

![Clerk Prisma Mongodb Fullstack Post App tutorial illustration](./2772efaeae7e205dfabdcfa7a9720803766978b8-1999x438.png)

For this example you can add a couple of posts or more with the `authorEmail` attribute matching the email address with which you will sign up for the app.

## How Clerk provides authenticated access to your data

For the frontend part of our example, `@clerk/nextjs` provides access to the Clerk pre-built components and helpers to enhance your application with user authentication, as quickly and intuitively as possible. Below we will show some of the code snippets that guarantee user authenticated behaviours.

### Only allow interface actions to specific users

Our users should be able to delete only their own posts and capability should be as intuitive as possible on the interface level. To achieve this, we include a deletion button on our post cards, only visible to users which are signed in and their email matches the author of the post.

```tsx
function PostCard({ deletePost }) {
  /** Clerk hook */
  const user = useUser()
  /** Get the user email address */
  const primaryEmailAddress = user.primaryEmailAddress?.emailAddress

  return (
    <CardLayout>
      {/* ... */}
      {primaryEmailAddress === post.authorEmail && (
        <Image
          cursor="pointer"
          onClick={async () => await deletePost(post.id)}
          boxSize="20px"
          alt="delete"
          src="/images/trash.png"
        />
      )}
      {/* ... */}
    </CardLayout>
  )
}
```

As you can see, just by using the `useUser` hook from the Clerk package, we are able to get all the required properties for the signed in user, and achieve the functionality we described.

### Authenticated access to Prisma models

To safeguard your data from unauthenticated access and unauthorized operations directly at the  Prisma model API, you only need to add a thin middleware layer on top of the data model access code. This middleware for our application, will use the `@clerk/nextjs/api` in the API routes to determine the authentication status and recognize the signed in user.

```typescript
async function handler(req: RequireSessionProp<NextApiRequest>, res: NextApiResponse) {
  /** On how this works visit https://nextjs.org/docs/api-routes/dynamic-api-routes */
  const postId = req.query.id as string

  /**
   * For this example, we want to identify the email of the person trying to modify some post.
   * We do this through the Clerk cookie ;)
   */
  const primaryEmailAddress = await getClerkUserPrimaryEmail(req.session.userId as string)

  /** We check if the persisted post email matches the requesters. */
  const persistedPost = await getPostById(postId)

  if (primaryEmailAddress !== persistedPost?.authorEmail) {
    /** If it does not match, he will get a 401 */
    res.status(401).end()
  }

  switch (req.method) {
    case 'PUT':
      /** The client will send the post object in the PUT request body. */
      const modifiedPost = req.body
      const updatedPost = await updatePost(postId, modifiedPost)

      res.status(200).json(updatedPost)
      break
    case 'DELETE':
      await deletePost(postId)
      res.status(200).json({ completed: true })
      break
    default:
      res.status(405).end()
      break
  }
}

export default requireSession(handler)
```

The requireSession helper guarantees that an authenticated user is accessing the endpoint, and also populates the `req.session` attribute on the request object coming from Next.js.

In this endpoint, we retrieve the primary email address of the authenticated user and compare it with the author of the post to be deleted or updated. For the sake of the example, we only check for the primary email address of the user, but since Clerk also supports multiple email addresses per account, you could adjust the logic accordingly.

## Wrapping up

This showcase application demonstrates how, with little effort, you can add authentication and authorization to both the frontend and the backend layers using Clerk and Prisma. Prisma has proved to be an excellent addition to an engineer’s arsenal, especially when it comes to simplicity, productivity and type safety. Folks at Prisma have done an excellent job listening to community feedback, adding new features and solidifying their place as one of the top ORMs out there.

At Clerk we strongly believe that you as an engineer should not have to spend so much time and effort building and maintaining authentication workflows. Authentication, user management and security are hard, and we focus exclusively on giving you the best in class solution. All this so you can focus on what really matters, which is realizing the idea that makes your product unique.

If you have any feedback, are running into trouble, or just want to share what you've built - we'd love to hear from you! Reach out to us on X [@clerk](https://x.com/clerk), on our [Discord community](https://clerk.com/discord), or through any of our other [support channels](https://clerk.com/contact/support).

---

# Generating sortable Stripe-like IDs with Segment's KSUIDs
URL: https://clerk.com/blog/generating-sortable-stripe-like-ids-with-segment-ksuids.md
Date: 2021-08-06
Category: Engineering
Description: Learn how Clerk generates resource IDs with inspiration from Stripe and Segment.

On the shoulders of giants, as they say...

Early in Stripe's lifetime, they launched a new style of resource ID's to a great deal of fanfare. The ID's are prefixed with an abbreviation of the object they represented. For example:

- `ch_` represents a Charge object
- `cus_` represents a Customer object

Patrick Collison offered the motivation for these prefixes on [Quora](https://www.quora.com/How-does-Stripe-generate-object-ids):

![Generating Sortable Stripe Like Ids With Segment Ksuids guide illustration](./a47bef704ff445167a03ad95e862e34ef8f7ca52-1222x440.png)

At Clerk, we're big fans of the prefix and knew early on that we wanted to offer their convenience to our own customers.

That was the easy part of generating our IDs— we spent a lot more time deciding what to put *after* the prefix.

For the uninitiated, ID generation is a surprisingly wide subject area with many important considerations.

For a long time, it was commonplace for developers to rely on sequential IDs generated by the database. There are artifacts of this practice all over the web - but these days, they tend to be avoided because:

1. They can easily be guessed. This isn't inherently a problem, but many, many security vulnerabilities are made worse when attackers can guess resource IDs. On a more light-hearted note, a "bug" involving guessable IDs [led to the creation Reddit self-posts](https://news.ycombinator.com/item?id=20453120).
2. They can reveal a lot of information about application usage. Again, this isn't inherently a problem, but it can lead to unintended side effects. One example came recently when StackOverflow sold to Prosus, and there was [discussion on HackerNews about the low user IDs](https://news.ycombinator.com/item?id=27370507) some users had, indicating they were an early user.
3. They're impossible to generate in distributed systems. For modern applications, this should be the primary concern. If a system has servers in two different regions, it's impossible for them to generate sequential IDs independently, without coordination - but coordination would likely undermine the point of distributing the system in the first place.

To mitigate these issues, randomness has been introduced into ID generation. Enough randomness ensures that IDs cannot be guessed and that collisions are avoided in distributed systems.

But purely random IDs - like [UUIDs](https://en.wikipedia.org/wiki/Universally_unique_identifier) - also eliminate a trait of sequential IDs that developers love: they're sortable.

Finding a middle ground between sortable and unique IDs was a primary motivation behind two newer ID generators:

- Twitter's [Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake)

  > To generate the roughly-sorted 64 bit ids in an uncoordinated manner, we settled on a composition of: timestamp, worker number and sequence number.

- Segment's [KSUID](https://segment.com/blog/a-brief-history-of-the-uuid)

  > It borrows core ideas from the ubiquitous UUID standard, adding time-based ordering and more friendly representation formats.

## Clerk's ID generator

After considering both Snowflake and KSUID, we decided to use KSUID for our primary ID generator. The key factor in our decision was that Twitter's Snowflake included a worker number, which we did not need.

Combined with Stripe-like prefixes, our IDs look like this:

![Generating Sortable Stripe Like Ids With Segment Ksuids guide illustration](./44bfae985e59215dc8839f8e96c82093ec5d6825-1344x239.svg)

---

# Serverless authentication with Clerk and Firebase
URL: https://clerk.com/blog/serverless-auth-with-clerk-and-firebase.md
Date: 2021-07-30
Category: Guides
Description: Protect your Firebase Cloud Functions with user authentication using Clerk.

As modern ventures have a need for architectures and infrastructure that support constant innovation and dynamism, development agility and convenience must be at their core. One of the computing categories that support this paradigm and has solidified its place on our engineering efforts is *Function as a service* (FaaS).

A leading product in this space is Firebase and its [Cloud Functions](https://firebase.google.com/docs/functions) solution. Cloud Functions give you all the power of a serverless framework with both callable and event-driven architectural capabilities.

In this article we are going to show you how to secure your Cloud Functions in an easy and seamless way using Clerk, making sure only authenticated Firebase user clients can access the results of your serverless functions. To do that, we are going to be using the Firebase [web SDK](https://firebase.google.com/docs/web/setup?sdk_version=v8) and the latest Firebase [Callable Functions](https://firebase.google.com/docs/functions/callable).

The Clerk-Firebase integration is **natively** authenticating a user as a Firebase authenticated user, recognized by both systems. This fact provides tremendous flexibility without going through any backend code or calling *yet another API* to continuously verify with both platforms. You as a web developer do not have to do **anything** additional for authentication to work the same way as it would with a standard Firebase authentication provider.

## Prerequisites

This article assumes that you have already:

1. Set up a Firebase Web project with the ability to use [Cloud Functions](https://firebase.google.com/docs/functions/get-started)
2. Correctly set up the [Firebase integration](/docs/integrations/databases/firebase) on your Clerk account

If you need a refresher with an example of the whole process, you can check out our showcase of [how to integrate Firebase with Clerk](/blog/build-a-premium-recipes-app-clerk-firebase).

## Creating and Securing your Function

For the sake of the example, we are going to create a function which receives a message from the Firebase web SDK and returns the message with the user identifier attached. A pretty trivial example but it showcases how to configure your Functions to only be accessible by your authenticated users.

```typescript
import * as functions from 'firebase-functions'

export const returnAuthenticatedMessage = functions.https.onCall((data, context) => {
  /** Prevent unauthenticated Firebase users from receiving the result. */
  if (!context.auth) {
    throw new functions.https.HttpsError(
      'unauthenticated',
      'The function must be called while authenticated',
    )
  }

  /** Any kind of data parameter sent from the web client. */
  const text = data.text

  /** Authentication / user information is automatically added to the request through context. */
  const clerkFirebaseUserId = context.auth?.uid

  return {
    message: `Authenticated message '${text}' from user ${clerkFirebaseUserId}.`,
  }
})
```

What this function does is first of all check if the request is coming from an authenticated user, *Firebase callable functions store this information in the context argument*, and if the user is not authenticated, a self-explanatory error is returned. If all goes well, the message is returned, along with the user identifier.

As you can see, there are no external calls on any Clerk related API. The user is **automatically recognized** as being authenticated and also shares the same user identifier in both Clerk and Firebase.

## Invoking the Function from the client

The second part of the equation is to call the function from your client application using the Firebase web SDK.

In your application, after you successfully sign in using the[ Clerk-Firebase integration](/docs/integration/firebase), you can normally call the Cloud Function from your client code.

```typescript
try {
  const returnAuthenticatedMessage = firebase
    .functions()
    .httpsCallable('returnAuthenticatedMessage')

  const response = await returnAuthenticatedMessage({
    text: 'some message',
  })

  /**  Read the result of the Firebase Function. */
  const authenticatedMessage = response.data.text
  // ...
} catch (error) {
  /**  Get the Error details. */
  const code = error.code
  const message = error.message
  const details = error.details
  /** Handle the error in any way you want. */
}
```

That's it! Using the Clerk-Firebase integration, user authentication works native to Firebase, while also providing consistency between user identifiers.

## How does this work ?

The way Clerk integrates with Firebase, authentication is ensured through a token representing a valid Firebase user. This token is retrieved through the Clerk JavaScript library and then handled internally by the Firebase web SDK.

The SDK then automatically attaches the required authentication token on the *HTTP Authorization* header. From there the Firebase platform can provide any user credentials on the `context` object in the callable Firebase Function.

![How does this work ? screenshot](./377971a37ee2b38b6ce0738418a8fcc1f6c6fa4d-774x384.jpg "Low-level abstraction by the Firebase web SDK")

## Parting Words

This brief example showed how you can authenticate your Firebase serverless Functions while using Clerk for authentication. There are no extra steps compared to using Firebase's standard authentication system, but you get all of the benefits of Clerk's best-in-class user management system, including beautiful UIs and a complete user profile page.

We would love to hear your feedback and use cases for integrating Clerk and Firebase. If you have questions or ideas for improvement, reach out to us on X [@clerk](https://x.com/clerk), or through any of our [support channels](https://clerk.com/contact/support). We also have a [Discord server](https://clerk.com/discord) and we would love to see you there. Cheers!

---

# Row-level access for your Airtable-powered application with Clerk
URL: https://clerk.com/blog/row-level-access-for-your-airtable-powered-application.md
Date: 2021-07-17
Category: Guides
Description: Learn how to add complete user authenticated access to your Airtable data API using Clerk.

Airtable is an online platform to access, manage, and collaborate on relational or spreadsheet-like information. The folks at Airtable have done an amazing job on both the user experience and the technical aspects of the product. As a no-code tool – for most use cases – it can help with your whole team’s efficiency around data management.

Airtable is a great choice as a database for any kind of resource you want to serve in an application, but lacks the granular access management capabilities that most web applications need.

As an example, consider an apartment hunting application where realtors need to add and manage the most attractive apartments for each of their clients. Each apartment will be listed in a single table, and you need to make sure that clients can only access the apartments selected for them. To achieve that, we can leverage some Clerk magic to provide **authenticated user access** to only certain rows in your Airtable apartment hunt database.

## Setup for the Apartment Hunt

To kickstart the apartment hunt project, you can start by creating your Airtable account and then use the [Apartment Hunting Template](https://airtable.com/templates/everyday-life/expPfTzGnfpwjgWlS/apartment-hunting) from the template gallery.

![Row Level Access For Your Airtable Powered Application tutorial illustration](./abca3d93141f8442e077610f4b14c9afd905e040-705x599.png)

In the created dataset you will need to add a column that represents the email that the Apartment has been assigned to. Go ahead and create the Email column of type *“Email”.*

![Row Level Access For Your Airtable Powered Application tutorial illustration](./d17297b7d9f1d68ad2d14e5bc2a6ee9916bf987c-1284x423.png)

*Setting the column's type to Email adds more capabilities to the field, including validation that the email address is valid.*

For the sake of our example, you can go ahead and fill the Email column with the email address you will use to access your Apartment Hunting application. For me, it's *[peter@clerk.com](mailto:peter@clerk.com)*.

## Create a Clerk application

If you are new to Clerk you will need to [create an account](https://dashboard.clerk.com/sign-up) on our platform, then follow the steps to create a new application.

After you create an account and a new application for this example, you can move on to the repository setup.

## Show me the code

To run the full example locally, you will need to follow a few small steps. First, go ahead and clone the example application.

```sh
git clone https://github.com/clerkinc/clerk-airtable-apartment-hunt.git
```

Go inside your project folder and copy the `.env.example` file to a `.env.local` file.

```sh
cp .env.example .env.local
```

#### Clerk Environment Variables

You will need the Frontend API value which can be found on the [dashboard](https://dashboard.clerk.com) on your development instance's home page. Set this value as the `NEXT_PUBLIC_CLERK_FRONTEND_API`.

Next you will need the Clerk API key which can also be found on your dashboard under Settings ➜ API keys. Add that as `CLERK_API_KEY` in your .env.local file.

#### Airtable Environment Variables

For Airtable you need to go to the Airtable [account page](https://airtable.com/account) to generate an API key and retrieve your base key. The base key can be found after selecting the newly created database on the [API page](https://airtable.com/api). These variables should be set as `AIRTABLE_API_KEY` and `AIRTABLE_BASE_ID` respectively.

Finally your .env.local file should look something like:

```text
AIRTABLE_API_KEY=keyojbaeZ5KBe9JMR
AIRTABLE_BASE_ID=appBMXDYAGWAgvH8S
NEXT_PUBLIC_CLERK_FRONTEND_API=clerk.2ct1o.leet.lcl.dev
CLERK_API_KEY=test_avDIYjpk0SqaTGF1Wx8MdrEHZIkg2zSObU
```

Now you just need to install the project dependencies with `yarn install` inside the project folder, then `yarn dev` to start the application locally.

## How Clerk provides authenticated access to your data

To authorize Airtable data access with Clerk, we introduce a thin and customizable access management layer over the Airtable API in our backend.\*

*\*The Airtable Rest API does not restrict us from calling it directly from the browser, but it is not recommended since we would need expose sensitive information. For more information, please see [this community forum answer](https://community.airtable.com/t/can-i-use-the-airtable-api-securely-from-the-browser/28810).*

In the Apartment Hunting application, `@clerk/nextjs` takes care of the frontend of user authentication. For apartment data access, we use Next.js API routes to interact with the Airtable API in a secure manner. These routes use `@clerk/nextjs/api` to determine the signed in user.

### Only showing apartments assigned to the current user

To make sure users only have access to the properties assigned to them, we create a `/api/apartments` endpoint to fetch this information. The code for this endpoint can be seen below:

```typescript
async function handler(req: WithSessionProp<NextApiRequest>, res: NextApiResponse) {
  switch (req.method) {
    case 'GET':
      /**
       * Get the user email from the userId attached on the request.
       */
      const userId = req.session?.userId as string
      const user = await ClerkInstance.users.getUser(userId)
      const primaryEmailAddress =
        user.emailAddresses.find((emailAddress) => emailAddress.id === user.primaryEmailAddressId)
          ?.emailAddress || ''

      /** Use the email to retrieve the assigned apartments. */
      const apartments = await getApartmentsByEmail(primaryEmailAddress)
      res.status(200).json(apartments)
      break
    default:
      res.status(405).end()
  }
}

/**
 * Only allow authenticated access or respond with status code 403 Forbidden.
 * Add the req.session attribute on the NextApiRequest object
 */
export default requireSession(handler)
```

The `requireSession` helper guarantees that an authenticated user is accessing the endpoint, and also populates `req.session` attribute on the request object coming from Next.js.

In this endpoint, we retrieve the primary email address of the authenticated user and use it to fetch only apartments assigned to this email. Here, we only check for the primary email address of the user, but since Clerk also supports multiple email addresses per account, you could adjust the logic accordingly.

### Only allow assigned users to modify the apartment status

In a similar manner, we want to restrict editing the apartment status to only the assigned user. The logic for restricting that access can be seen below:

```typescript
async function handler(req: WithSessionProp<NextApiRequest>, res: NextApiResponse) {
  switch (req.method) {
    case 'PUT':
      const apartment = req.body
      const userId = req.session?.userId as string

      /** We make sure prevent a user with different account to update the visitation status. */
      const user = await ClerkInstance.users.getUser(userId)
      const primaryEmailAddress = user.emailAddresses.find(
        (emailAddress) => emailAddress.id === user.primaryEmailAddressId,
      )?.emailAddress

      /** We check if the persisted apartment email matches the requesters. */
      const persistedApartment = await getApartmentById(apartment.id)

      /** If the emails do not match, return 401 Unauthorized */
      if (primaryEmailAddress !== persistedApartment.fields.Email) {
        res.status(401).end()
        break
      }

      const results = await updateApartment(apartment)
      res.status(200).json(results)
      break
    default:
      res.status(405).end()
      break
  }
}

export default requireSession(handler)
```

In the same manner as the apartment fetch, we only allow authenticated access by using the `requireSession` middleware. We perform an extra check with the signed in user's email address to ensure they are assigned to the apartment.

## In summary

This was just a simple example of how Clerk can be used to add row-level access an to application that uses Airtable as it's database. While we built this example, we were really impressed with how powerful Airtable can be at managing project data, with little to no code involved.

In the same manner, Clerk abstracts away the intricacies of authentication and user management, allowing a robust solution to be deployed with little code, and users to managed with no code through our dashboard.

If you have any feedback, are running into trouble, or just want to share what you've built - we'd love to hear from you! Reach out to us on X [@clerk](https://x.com/clerk), on our [Discord community](https://clerk.com/discord), or through any of our [support channels](https://clerk.com/contact/support).

---

# Build a premium recipes app with Clerk and Firebase
URL: https://clerk.com/blog/build-a-premium-recipes-app-clerk-firebase.md
Date: 2021-07-10
Category: Guides
Description: Learn how to connect Clerk as an authentication and user management solution together with your Firebase as your backend.

Firebase is among the top Platform-as-a-Service (*PaaS*) providers for web and mobile applications. It packs tons of powerful and well designed features for developers to spin up a fully fledged application with minimal effort, like storage, analytics, and authentication.

Clerk integrates directly with Firebase, so developers can easily add our beautiful Sign Up, Sign In, and User Profile UIs to their Firebase application. The integration allows developers to use all the full feature set of Firebase without compromising on user management.

In this post, we are going to show you a full example integrating Clerk with Firebase, to make a "premium" recipe showcase application. The recipe data is going to be stored in Firebase Firestore and will only be available to authenticated users.

![Premium recipes app hero UI with Clerk and Firebase](./359e8539774d761e686f5eb611472e72efcc59bf-1131x701.png)

The full code for this guide is available in the [clerk-firebase-starter repository](https://github.com/clerkinc/clerk-firebase-starter), and includes instructions for how to set up Firebase and connect it to Clerk. The application demo is live at [https://fir-clerk.web.app/](https://fir-clerk.web.app).

If you would like to read the documentation before getting started, please refer to our Firebase integration documentation.

## Setting up the Firebase project

To start off, we need a Firebase Web project. Go to the [Firebase Console](https://console.firebase.google.com) and create a new project:

![Create Firebase project in Firebase Console screenshot](./94736e4366e190ee7431337ce1104c1ae5812333-333x236.png)

After giving it a valid name and confirming, you will find yourself in the Firebase dashboard.

## Enabling Firestore and adding recipes

From the Firebase dashboard, you can go ahead and create a new Firestore Database for our example project. The Firestore instance will serve as our database where we will store and retrieve our recipes. If you want to learn more about Firestore, you can take a look at the starter [documentation](https://firebase.google.com/docs/firestore).

During the database instance creation, you should choose the storage location somewhere close to your users. Also keep in mind that by selecting the production mode ruleset, by default you have disabled any reads/writes to your database from outside the platform. We are gonna change that right after!

If you are not familiar with Firebase [Security Rules](https://firebase.google.com/docs/rules), they are basically a Domain-specific language to limit the access to important data in Firebase storage solutions. As we mentioned previously, since these are premium recipes, only authenticated users will be allowed to view them.

To allow authenticated users to read any database but not write, you can use the security rule shown below:

```text
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if request.auth != null;
    }
  }
}
```

## Adding recipes

To add a few recipes, go ahead and create a `recipes` collection with recipes of your liking, but please conform to the same attribute schema shown below:

![Firestore recipes collection document schema screenshot](./749dbbe0c48ae8b85e95e44fb25d6509122cd722-1256x524.png)

If it's helpful, here is the TypeScript type for each recipe document:

```typescript
type Recipe = {
  /** The recipe description */
  description: string

  /** The amount of guilty you should feel */
  calories: number

  /** Cooking time in minutes */
  cookingTimeMin: number

  /** Publicly accessible image full URL */
  imageUrl: string

  /** Number of ingredients needed */
  ingredientsNum: number

  /** The title of the recipe */
  title: string
}
```

After adding a few recipes, you are all set from the data side.

## Enabling Firebase Authentication

Since this is a new project, you will need to enable the Authentication feature. No further action is needed, since Clerk will handle the rest.

![Enable Firebase Authentication feature screenshot](./05531358eaa7d8152a46ee80bb1e9734ca10e810-1438x482.png)

## Enabling the Firebase integration on Clerk

If you are new to Clerk you will need to [create an account](https://dashboard.clerk.com/sign-up) on our platform, then follow the steps to create a new application.

After you create an account and a new application for this example, you can follow [these instructions](/docs/integration/firebase) to enable the Firebase integration on Clerk for your application instance.

With that done, you are now able to authenticate Clerk users in your Firebase application.

## Show me the code

To run the full example locally, you will need to follow a few small steps. First, go ahead and clone our Firebase starter application.

```sh
git clone git@github.com:clerkinc/clerk-firebase-starter.git
```

Go inside your project folder and copy the .env.example file into a .env.local file.

```sh
cp .env.example .env.local
```

Take the Frontend API value which can be found on your [application dashboard](https://dashboard.clerk.com) and add it as the `NEXT_PUBLIC_CLERK_FRONTEND_API` value. Your .env.local file should look something like:

```text
NEXT_PUBLIC_CLERK_FRONTEND_API=clerk.sample.api.lcl.dev
```

The final configuration step is to replace the firebase.web.ts config file with one from your own Firebase project. You can find a specification for the [config object](https://firebase.google.com/docs/web/setup?sdk_version=v8#config-object) in Firebase's documentation.

After you create new Firebase Web project, you will be able to find the required values under Project settings ➜ General.

![Firebase web app configuration settings screenshot](./874f36e6473bd7a22559394ceb65bd9cbed15c8a-936x720.png)

Now you are ready to install the dependencies and run your project in development mode. Go to the root directory of the project and run:

```sh
yarn install
```

and after completion

```sh
yarn dev
```

Your application is now running in your local environment and you can experience the same functionality as the live demo.

## Where the magic happens

If you take away the application setup, the integration is seamless and works out of the box with just a few *copy & paste* steps across Clerk and Firebase. Here's how it works:

Let us go over the way the integration works in your web application code and what are the actions you need to authenticate a Firebase user with Clerk.

The `firebase` application object houses the `.auth()` namespace which includes methods to authenticate a user. One of those methods is `signInWithCustomToken`, which allows third-party providers like Clerk to pass authenticated user data to Firebase.

*Where does this "custom token" come from ?*

After setting up Firebase integration on Clerk, you can retrieve the necessary "custom token" by calling the `getToken` method on the Clerk User object.

Combined, it's just two lines of code:

```typescript
const firebaseToken = await clerkUser.getToken('firebase')
await firebase.auth().signInWithCustomToken(firebaseToken)
```

From that point on, your user is authenticated and can complete all the actions that require privileges of an identified Firebase user.

You can see this in action in our [useRecipes](https://github.com/clerkinc/clerk-firebase-starter/blob/main/client/hooks/useRecipes.ts) hook implementation. If you remove these two lines, the request will fail since the Clerk user will not also be authenticated in Firebase. (*Remember, we set a Security Rule - `allow read: if request.auth != null;` - which restricts access to authenticated users.)*

## Moving forward

This end to end example showed how you can use Clerk and Firebase together for a new web project. Firebase is an exceptional development platform and we are really excited to see what you build with this integration.

If you have any feedback, and running into trouble, or just want to share what you've built - we'd love to hear from you! Reach out to us on X [@clerk](https://x.com/clerk), on our [Discord community](https://clerk.com/discord), or through any of our [support channels](https://clerk.com/contact/support).

---

# Clerk raises $4 million to build the next-gen authentication and user management platform for developers
URL: https://clerk.com/blog/clerk-raises-for-next-gen-auth.md
Date: 2021-07-01
Category: Company
Description: Clerk raised a $4 million seed round led by S28 capital with Andrew Miklas (cofounder, PagerDuty) joining our board.

## Announcing our seed round

Today, we're thrilled to announce that Clerk has raised a $4 million seed round, led by S28 Capital with Andrew Miklas (cofounder, PagerDuty) joining our board. Additional participants include Fathom Capital, Calvin French-Owen and Ilya Volodarksy (cofounders, Segment), Darragh Buckley (first employee, Stripe), Max Stoiber (creator, styled-components).

## The business case

Developers love Clerk because it's fast to set up and maximizes conversion through their Sign Up and Sign In forms. Development speed and conversion rates have become bigger challenges in recent years, as users are demanding more variety in the ways they authenticate.

While privacy-focused users are demanding to create accounts by email, convenience-focused users are demanding "single sign-on" through vendors like Google and Facebook. Subsets of both groups are also security-focused, and are demanding multi-factor authentication.

Creating a cohesive user experience that caters to every group is challenging, and developers often make mistakes that leave their users frustrated or unable to access their accounts. A few examples we commonly see are:

- Disallowing single sign-on for users who originally created their accounts by email
- Allowing single sign-on for users who originally created their accounts by email, but accidentally creating them a second account
- Accidentally reducing multi-factor authentication to single-factor authentication during a "forgot password" flow

Clerk's prebuilt Sign Up and Sign In forms eliminate these mistakes and more. They are built by a team of designers and engineers who focus on maximizing conversion without sacrificing security. If custom designs are preferred, Clerk's API can be used instead to speed up development while still mitigating these errors.

## The path ahead

With this funding, we will focus our efforts on five product areas that are crucial to our customers' success:

1. **Security -** Applications built on Clerk automatically receive critical security features like multi-factor authentication, password breach protection, and device management. We will continue to invest in new protections **for our customers' applications**, as well as begin applying for formal security certifications like SOC-2.
2. **Optimization -** Most businesses simply do not have the resources to focus on optimizing the conversion of their Sign Up and Sign In forms. This is our core competency, and we will continue to analyze our prebuilt components to ensure they are as streamlined as possible.
3. **Customization -** In the months since launch, we've heard a chorus of requests for more customization capabilities in our prebuilt components. More flexibility is on the way, as well as better documentation for creating completely custom user experiences with Clerk's API.
4. **Extensibility -** Another frequent request is the ability to connect user data with other applications. We already deployed webhooks so developers can build connections in-house, and now we will focus on prebuilt connections for common vendors, [starting with Hasura](/docs/integrations/databases/hasura).
5. **Developer Experience -** We launched Clerk with SDKs for React, Next.js, and Express - but beneath those SDKs are language-agnostic REST APIs. The coming months will bring official support for more languages and frameworks.

These five focus areas are driven by the requests of our early adopters, whose enthusiasm and steadfast support made this funding possible. We're excited to continue servicing their needs, and also to welcome the next wave of developers in need of better [tools for authentication and user management](/nextjs-authentication).

## Growing our team

Our team has grown from 2 to 15 in the past eight months, and we're excited to continue that growth across engineering, design, developer advocacy, and more. If you're interested in complex design and engineering problems, or the challenge of creating a ubiquitous developer tool, [come join us](/careers).

With immense gratitude,

Colin and Braden Sidoti\
Cofounders, Clerk

---

# Designing fast sign in forms— diving into the data
URL: https://clerk.com/blog/designing-fast-sign-in-forms.md
Date: 2021-06-17
Category: Insights
Description: Key insights on building fast sign in forms with Social Sign In, password-based, and passwordless authentication.

The modern web is obsessed with speed. Just this week, Vercel [launched Next.js 11](https://nextjs.org/blog/next-11) with a special focus on [Core Web Vitals](https://web.dev/vitals), a new set of Google metrics that are measured in tens of milliseconds to determine page speed. Google has noticed that faster websites mean better user experiences, and has incorporated these metrics into their search ranking algorithms.

At Clerk, we're focused on a speed challenge that's equally important but often neglected: **how quickly can users sign in?**

In working to optimize our prebuilt Sign In UI, we've had a few surprising insights we thought are worth sharing.

## Social Sign In deserves the top spot

After much qualitative debate - Clerk originally launched with Google and Facebook sign in buttons *below* the option to sign in by email.

After collecting a few months of data, we realized we should make an adjustment. There was a near-perfect 50/50 split between users who preferred Social Sign In vs email and password. But, Social Sign In was faster: \~5 seconds on average compared to \~8 seconds for email and password. So we made the switch:

![Designing Fast Sign In Forms tutorial illustration](./714c2cb7ab631cfa11a4ea560116103434d62de5-2400x1600.png)

In the months since making this change, Social Sign In usage has started to outpace email and password, with the last month seeing a 52/48 split.

As expected, since more users are now using a faster authentication strategy, the change has also resulted in a faster overall sign in speed.

## Passwordless should remain a fallback

The passwordless concept has existed in authentication systems for decades. If a user forgets their password, a code or link is emailed to them for authentication without a password.

Recently, there has been a lot of buzz about promoting passwordless flows to the primary authentication mechanism. While Clerk allows developers to configure their Sign In this way, we recommend against it, and suggest leaving it as a fallback.

On average, we see passwordless flows take \~35 seconds to complete. Despite using Sendgrid to deliver our emails quickly and with high inbox rates, the process of checking email is simply *slow* in comparison to Social Sign In or email and password.

## The "edge cases" of Social Sign In are surprisingly common

While building Clerk, we cataloged our frustrating sign in experiences across the web and made sure we had a resolution. The source of much frustration was Social Sign In - even amongst the web's biggest properties, we came across sign in flows that were blocking users from using Social Sign In if they hadn't originally signed up that way:

![Designing Fast Sign In Forms tutorial illustration](./9730f6175509949c5ee0d18fb99e83cc7b61b424-2000x1333.png)

While it's obvious that roadblocks like these slow the sign in process, handling them elegantly takes a lot of development time. Many developers are comfortable pushing off a proper solution because these scenarios feel like edge cases.

In practice, we've learned that these "edge cases" are surprisingly common. In fact, 15.9% of users who have used Social Sign In have also used another method. Of those:

- 2 in 3 originally signed up with a password then later chose Social Sign In
- 1 in 3 originally signed up with Social Sign In, then later tried signed in without (they were sent a code to their email)

At Clerk, we've invested heavily in handling these scenarios as elegantly and quickly as possible. Regardless of a user's choice of sign in strategy, they will always be linked to the same underlying account.

## Clerk's prebuilt Sign In UI

Clerk enables developers to add beautiful, high-conversion Sign In form to their application in minutes. Our prebuilt UI can easily be themed to match any company's brand and style guidelines.

We're constantly analyzing the data in search of better user experiences, as well as evaluating new technologies for addition to our product. If you have questions or ideas for improvement, reach out to us on X [@clerk,](https://x.com/clerk) or [through support](https://clerk.com/contact/support).

---

# Build or Buy? A Look at User Management with Next.js: Part 1
URL: https://clerk.com/blog/build-or-buy-user-management-with-nextjs-1.md
Date: 2021-06-15
Category: Insights
Description: In this article, you'll learn the pros and cons of developing or buying a user management system so you’re ready to make the right choice for your project.

User management is one of the most critical components of any consumer-facing application. Put simply, a user management system is responsible for creating, managing, and removing users. It provides users a way to authenticate themselves so they can use the application, and it offers admins a way to manage the user store. Any application designed to serve users must have a user management system, either developed in-house or bought from a third-party vendor. However, with the advent of modern software development and the rise of various security threats, a simple username-and-password sign-up and sign-in often isn’t enough. The dilemma faced when building an application is if you should build or buy a user management solution.

## Features of a User Management System

A complete user management system comprises a multitude of different features. Here are some of the most important.

### Authentication

Authentication is an essential part of a user management system, as it acts as the entry point for your application. Although a simple username-password or email-password authentication is possible and works for small applications, there are alternative authentication mechanisms that can offer extra convenience and security. You can eliminate the need for passwords by using [email magic links](/blog/magic-links). Although magic links are 4.1x slower than using passwords, they can provide a seamless sign-in and sign-up experience, as well as prevent bot attacks and account takeover risks related to having a password that can be compromised. [Single sign-on (SSO)](/features/social-sso) is another important feature—one that’s 1.3x faster than using passwords. With SSO, users can use their existing account with a third-party service (e. g. Google, Facebook. etc.) to sign in to your application. In addition to being fast, SSO is the preferred method for authentication for 53% of users, resulting in higher conversion rates.

To offer the best possible experience for your users with social SSO, your application must support a wide range of social SSO providers: Google, Facebook, Twitter, GitHub, GitLab, and Discord are the most common. The more social SSO providers you support, the more likely it is that users can use their preferred provider to sign in to your application. Another recommended feature is automatic account linking—if a user signs in with SSO after creating their account with another form of sign in, a new account shouldn’t be created; rather, the SSO should be linked to the original account.

Another consideration is [multi-factor authentication](https://en.wikipedia.org/wiki/Multi-factor_authentication). It's a way to add extra security to your application by requiring users to enter their password and a second factor such as a security code, and is strongly [recommended](https://www.getcybersafe.gc.ca/en/blogs/why-multi-factor-authentication-essential-part-cyber-security), especially for applications where users might store sensitive information.

### Session Management

When a user signs into an application, a session is created, which saves the user from needing to log in with every request. This session must be maintained for the duration of the user's active period, and be destroyed when they sign out. A robust session management system must provide security features like [XSS leak protection](https://clerk.com/docs/security/xss-leak-protection), [CSRF protection](https://clerk.com/docs/security/csrf-protection), and [session leak protection](/docs/security/fixation-protection). In some instances, a multi-session feature can also be useful, allowing users to have multiple accounts and switch between them seamlessly, without having to log out and log in again.

### User Profile Management

A centralized profile/settings page where users can edit their personal information, such as name, email, and profile picture, and security details, such as password, multi-factor authentication preferences, and connected accounts and devices, is another important component of a user management system.

### User Interface

The user-facing side of the user management system is equally important. A poorly designed user interface or clunky user experience can turn potential users away. Whether you buy or build a user management solution, make sure that interfaces like the sign-in page, sign-up page, profile page, etc., are well designed and match the rest of the application.

### Integrations with Other Components

Your user management system should be easy to integrate with the various parts of the application, and flexible enough to allow any future integrations. For example, if you're building a web app, it's quick and easy to build a user management system that is coupled tightly to the web app. But if you build a companion mobile app in the future, you’ll need to either separate the user management system into its own service that the mobile app can communicate with through APIs, or build a separate system for the mobile app—both time-consuming and costly solutions. So it's vital to start with a user management system flexible enough to handle both what you need right now, and what you might need further down the line.

## Pros and Cons of Building a User Management System

In-house development of a user management system offers some advantages. First of all, you get a highly customized system for your application. The design can be tweaked to match your requirements exactly. You also have complete control over how it works and integrates with other components. You can make changes to it when needed, and roll updates whenever and however you want.

Building a user management system might be tempting because of the control that it offers. But before you start building, take a look at the disadvantages.

As you can see from the number of features listed above, a complete, future-proof user management system is incredibly challenging to build, and you'll need a diverse team to tackle it. Developers with expertise in different domains—including database security, cryptography, cybersecurity, system engineering, and of course, developers familiar with the ever-changing landscape of user management—are needed for in-house development.

To build a user management system from scratch also requires you to invest a significant amount of time, money, and engineering power. Devoting resources to the development and ongoing maintenance of a user management system means fewer resources for critical business operations and the development of the core application features. Unless you have manpower to burn, you're probably better off having your developers and resources focused on developing the core application.

A user management system must also be secure enough that users are comfortable entrusting their data to your application. While hashing and salting passwords with an algorithm like [Bcrypt](https://en.wikipedia.org/wiki/Bcrypt) is standard, the security measures shouldn't stop there. Standards like [NIST 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html) should be followed to ensure the highest possible security standard. Proper protection against brute force attacks, dictionary attacks, and [credential stuffing attacks](https://owasp.org/www-community/attacks/Credential_stuffing), as well as using a service like [HaveIBeenPwned](https://haveibeenpwned.com) to prevent the use of previously leaked passwords, is a must. You’ll also need to rate limit the endpoints to protect the system from [DDoS attacks](https://us.norton.com/internetsecurity-emerging-threats-what-is-a-ddos-attack-30sectech-by-norton.html). Automated logging and monitoring of all activities must be implemented, and alerts for suspicious activities should be set up to prevent data breaches.

Since the user management system provides the entry point to your application, it needs to be highly available, and must scale in response to increasing load—it can’t crash because too many users are attempting to log in at once.

Even after successfully building a user management system, the hassle doesn't end there. You need to constantly monitor, audit, and improve the code to ensure security. Failure or delay runs the risk of the application being [compromised](https://www.contrastsecurity.com/security-influencers/a-week-of-web-application-hacks-and-vulnerabilities). You'll need an experienced DevOps team to deploy and maintain the user management system to ensure it stays up and running.

## Pros and Cons of Buying a User Management System

Buying a user management system alleviates many of the challenges of user management systems. You don’t have to worry about the scalability or availability of the system, since the service provider will handle them. The security concerns are also lifted from your shoulders, and best practices are already implemented. Reputable vendors, such as [Clerk](/), supports almost any available [social SSO providers](/features/social-sso). They also offer libraries for different programming languages and frameworks such as [Next.js](https://nextjs.org), as well as prebuilt [UI components](https://clerk.com/docs/components/overview). This means you can quickly integrate the user management system with your codebase. You'll also get full technical support from your service provider if you run into any issues.

Though buying a user management solution makes user management easier, there can be some downsides. The biggest concern lies in the fact that you don’t have complete control over the service. You can evaluate different service providers and choose the one that works best for you, but it may be hard to find one who meets all of your requirements. You can always provide feedback or request new features, but implementation is ultimately up to the service provider.

The service provider is also in control of your data, and it can be difficult to verify their level of security before entrusting valuable user data to them. To ensure your data is in good hands, you’ll need to evaluate the policies and practices of the service providers you’re considering. For example, [Clerk](/) has a [secure-by-default philosophy](https://clerk.com/docs/security/overview) and a [responsible vulnerability disclosure policy](https://clerk.com/docs/security/vulnerability-disclosure-policy), which ensures that all the data is properly protected.

The possibility of vendor lock in is another concern. Once your application is tied to a particular user management system, it becomes difficult to switch to a new vendor if the need arises. You'll have to manage the change of vendor without breaking your application.

## Build or Buy?

Now the advantages and disadvantages of each approach are clear, let's answer the title of the article. Should you build or buy? The answer is *it depends*.

You might opt for building a user management system if:

- You only require basic features, like username-password authentication. You can build this yourself using libraries like [next-session](https://www.npmjs.com/package/next-session). For a very simple project, you might be able to use one or two social providers and get away without a username/password database.
- You need a highly customized solution tailored to your needs, and can’t find a service provider that can meet the requirements.
- You have an expert team of highly experienced developers, and you have enough resources to continue developing core business features.
- You're on an extremely tight budget. Although [authentication providers like Clerk](/nextjs-authentication) are free for 500 MAU and only cost $10/month after that, sometimes budget restrictions might force you to make a compromise between buying a user management system and buying some other essential service.

For almost all other cases, it's preferable to buy a user management system. It's the sensible choice when:

- You want to get your product to the market as quickly as possible.
- You want a robust, future-proof user management system.
- You want to save on costs, and don't want to waste resources on reinventing the wheel.
- You don’t have a team of developers who are well versed in the technologies required to create and maintain a user management system.
- You want to focus the organization's resources on the core business operations.
- You have a small userbase that can fall under the free tier of your provider.

## Conclusion

To build or to buy—that's the age-old question of the software development world. Since user management is a crucial part of applications, it makes sense to have a comprehensive, robust system. In this article, you explored the various features of user management systems and looked at the pros and cons of building and buying user management systems.

In the [next part](#link-to-next-part) of this series, you'll follow a hands-on tutorial to build a user management system from scratch with [Next.js](https://nextjs.org), as well as see how to use [Clerk](/) to achieve the same result.

---

# How we use End To End tests to bulletproof our authentication flows across browsers
URL: https://clerk.com/blog/how-we-use-end-to-end-tests-to-bulletproof-our-authentication-flows-across-browsers.md
Date: 2021-06-11
Category: Engineering
Description: Due to the evolution of tooling and the shift towards high-velocity product development, End To End testing is a regular topic of discussion for small teams.

At Clerk, we use End To End testing to create bulletproof authentication flows across browsers.

## The 10,000 ft view of the End To End landscape

In the past, End To End testing was almost exclusively considered a Quality Assurance Engineering topic. For one reason or another, the development of test automation pipelines and application workflow validation tests were not so popular with software engineers. That view has gradually become dated and replaced with the growing popularity of tools like Cypress, Puppeteer, Playwright, and even the latest version of Selenium.

![How We Use End To End Tests To Bulletproof Our Authentication Flows Across Browsers guide illustration](./490c57865ef4011f0134f142c2fee8d3057ad7fd-2000x1404.png)

The growth of those tools should not be seen as a simple technical advancement, but instead as an immediate answer to the growing need to efficiently and effectively validate fast moving development cycles of agile teams. At Clerk we deploy multiple times per day, and without these tools it would be impossible to ensure reliability.

## The high bar for reliability at Clerk

As a solution for authentication and user management, Clerk must maintain exceptionally high reliability, even as our product and team expands rapidly around our core offering. It is critical that end-users can always access their accounts quickly, even through edge cases like originally signing up with Google, then trying to sign in with email instead.We also take great pride in our developer experience, and often jump through hoops to ensure that Clerk works consistently across development, staging, and production environments and across all browsers.To keep reliability high across our myriad of flows - and importantly, to give our own development team confidence that our product won't break with new deploys - it became clear the most pragmatic solution was to develop an End To End test suite.

## Laying out our needs

These were our initial needs exactly as voiced by our team:

- **Cross-browser**: The suite needs to cover all major browsers with as little external service interaction as possible.
- **Happy to code in**: Meaning TypeScript. Most probably Frontend Engineers should be able to write and maintain the tests for the suite (*with as much joy as possible*).
- **Support containerized deployment**: The suite needs to be portable enough to run on a GitHub Action workflow.

## Choosing a platform

After investigating Selenium, Puppeteer, WebDriverIO, Cypress, and Playwright and weighing each platform against our needs, we decided to go with Playwright.

Although it felt less hyped, as a team we felt really confident in the architecture behind Playwright, its stellar documentation and tooling, and the excellent community backing the effort.

We will describe our exact selection process in a later post, but most critically, we appreciate the ability to execute our workflows across Chromium, WebKit and Firefox with so much ease and fine grained control.

![How We Use End To End Tests To Bulletproof Our Authentication Flows Across Browsers guide illustration](./8a588e6ff8136f408783a02c95ef6cbd64c402ef-1048x433.png)

## How the suite is orchestrated

Our End to End test suite is a separate system from our main codebase as we have seen this pattern working really well for most applications.

Its main components as a Node.js application written in TypeScript are:- **Playwright** as the browser automation framework.

- **Jest** as the test suite runner.
- [jest-playwright](https://github.com/playwright-community/jest-playwright) to connect Jest and Playwright as it makes our lives so much easier.
- [Faker.js](https://github.com/faker-js/faker) to create API fixtures that fit our needs for the sign-up and sign-in processes fixtures.
- [Page Objects](https://playwright.dev/docs/pom) as the main pattern representing the interaction facade with our application views in code.

These components have proved to work together seamlessly while staying welcoming to our frontend engineering team. One of our main goals was to ensure that new teammates could understand the system quickly and create new tests, and so far this structure has exceeded our expectations.

## Delivery of the suite on our day to day efforts

To keep us safe from accidental regressions, the test suite must run (and pass!) before any merge to production. To automate this process, integration with our Continuous Integration (CI) tooling was essential.

We run our CI through GitHub Actions, and fortunately, the Playwright team has created GitHub Action tools to simplify triggering the test suite. Paired with Vercel preview deployments, which is where most of our CI tasks take place, both Actions fit the spot quite nicely for End to End suite scenarios. The Playwright team has also created a GitHub action to quickly bootstrap Playwright tests.

The final action file that triggers our End to End suite on every pull request looks something like this:

```bat
jobs:
  e2e:
    if: github.event.deployment_status.state == 'success'
    name: End to End
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14.x]
    steps:
      - uses: actions/checkout@v2
      - uses: microsoft/playwright-github-action@74fbf9d1a7c5d8735dab59804da3fdd367a98020
      - uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}
      - name: Run Playwright tests
        run: cd e2e && npm install && npm run test
```

If the action succeeds, we are good to go!

## Parting words

This was a really brief overview of how we went about designing our End to End test suite at Clerk. As Clerk and our customers' needs continue to evolve, we will continue to share our experiences with Playwright and any new tools we adopt.

***P. S.** We have open sourced a template for starting up your own End To End suite using Playwright, so feel free to try it out! [https://github.com/clerkinc/playwright-e2e-template](https://github.com/clerkinc/playwright-e2e-template)*

---

# Build a to-do app with Clerk and Hasura— and no backend code
URL: https://clerk.com/blog/build-a-to-do-app-with-clerk-and-hasura-and-no-backend-code.md
Date: 2021-05-27
Category: Guides
Description: Learn to build a to-do app using Clerk for authentication, Hasura for data storage and access, and Next.js for the frontend.

This guide is outdated. For a more up-to-date tutorial, check out [Build a Cookie Clicker App with Clerk and
Hasura](/tutorials/build-a-cookie-clicker-app-with-clerk-and-hasura).

## Introduction

While traditional applications require both frontend and backend developers, new technologies like Clerk and Hasura are making it possible to build robust backends without writing backend code.

In this tutorial, we'll leverage these new technologies to build a simple to-do list application without writing any backend code. The primary tools we'll use are:

- [Hasura Cloud](https://hasura.io/cloud), for creating a frontend-accessible GraphQL API
- [Heroku Postgres](https://www.heroku.com/postgres), for storing to-do list data
- [Clerk](https://dashboard.clerk.com/sign-up), for authentication
- [Next.js](https://nextjs.org), for frontend development
- [Tailwind CSS](https://tailwindcss.com), for styling

Before we get started, you can see the final result here:

- [Demo of the to-do app](https://clerk-hasura-todos-zeta.vercel.app)
- [Completed codebase](https://github.com/nachoiacovino/clerk-hasura-todos)

Let's begin!

### Create a Hasura project

Start by [signing up for Hasura Cloud](https://hasura.io/cloud).

If you already have a Hasura Cloud account, you will need to manually create a New Project. If this is your first time, a new project will automatically be created for you.

After your project initializes, you will see something like this (with a different name), go ahead and click the cog wheel to go to the project settings:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./9083441a012c0cff18e6ba1144c537db356951d5-842x253.png)

From here, you will need our project's GraphQL API URL. Please copy it, you will need it in a second:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./871909e71d7ce6afe01b48440352579a74254c45-915x729.png)

### Deploy the starter project

We prepared a starter project for this tutorial, the easiest way to get started is with the following "Deploy" button. The button will prompt you through cloning the repo, initializing Clerk, and deploying the app live on Vercel. The starter project uses Next.js, Tailwind CSS and Clerk. It's already setup with some styles using Next.js and Tailwind CSS but you don't have to be proficient in either of these to follow the tutorial.

This button will first prompt you to create a Vercel account if you do not have one. When signing up, Vercel may ask you to grant access to all of your repositories or just selected ones - feel free to choose either option.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./03e4ba61a5b5aff2fd3effd485f4d12835f64756-659x481.png)

The Next step will prompt you to integrate Clerk into your project, click **Install.**

If you do not have a Clerk account already, you will be asked to create one now.

Next, you will be asked to select an application name and a brand color. Then, click **"Create application"**:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./2afb0a154750312a1938002fb3b8e170356cbce1-800x599.png)

After the window closes, click Continue and you will be prompted to pick a Git provider. In this tutorial, we will use **GitHub:**

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./d43be00e7a7e9af7089ac464e0f6b4130a0fa79c-656x477.png)

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./1dbf12f443839f6e57f82e894d520b8e98c0962d-657x481.png)

This is where you will use Hasura Cloud's **GraphQL API** URL you copied earlier. Add it below and click **Deploy**.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./cb34702cda69ba093dce6c2eb9f9f891c9517c2e-663x742.png)

While you wait for Vercel to deploy our project, you can move to GitHub, where Vercel has created a new repository on your behalf. Go ahead and clone it locally.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./cd9946c2d21a8e8f86dcd58b81ab6b3d1b53bf20-1244x771.png)

To clone, go to your desired folder, open a terminal and paste:

```bat
git clone <repository-url>
```

Then, go inside the project folder and run:

```bat
yarn
// or
npm install
```

This will install the necessary dependencies.

After this, go ahead and launch your project:

```bat
yarn dev
// or
npm run dev
```

If you haven’t previously used Vercel on your computer, you will be asked to sign in when you launch the project.

You will be prompted to set up link this local project with the Vercel project. Respond \***\*Y\*\*** to each prompt.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./8fc953112b70f944728a7da4790fedcc9fc8425a-760x347.png)

Then, you will see your project running on [http://localhost:3000](http://localhost:3000).

### File structure

```bat
├── components
│   ├── AddTodo.js (Form to Add todo)
│   ├── Header.js (Header of our app with UserButton)
│   ├── Layout.js
│   ├── SingleTodo.js (One todo with toggle/delete methods)
│   └── TodoList.js (List to render all todos with get method)
├── lib
│   └── apolloClient.js (Apollo configuration wrapper)
├── pages
│   ├── sign-in (Clerk-powered sign in page)
│   │   └── [[...index]].js
│   ├── sign-up (Clerk-powered sign up page)
│   │   └── [[...index]].js
│   ├── user (Clerk-powered user profile page)
│   │   └── [[...index]].js
│   ├── _app.js (where Clerk is configured)
│   ├── index.js (first page you see)
│   └── todos.js (page we will work on)
├── public (images)
├── styles (all css styles for our app)
│   ├── globals.css
│   ├── Header.module.css
│   └── Home.module.css
├── .env.local (environmental variables pulled from Vercel)
├── postcss.config.js (postcss config, needed for Tailwind)
├── package.json (where your packages live)
├── README.md
├── tailwind.config.js
└── yarn.lock
```

### Activate Hasura integration

Hasura is one of the integrations that Clerk offers, with many more coming the future. To use it, you need to enable it. Go to your [Clerk dashboard](https://dashboard.clerk.com), click on your application -> Development -> Integrations and activate Hasura.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./8b8f6731437b043e67dc633131e6818c1ad4ac0e-1043x319.png)

Before leaving the dashboard, go to Home and copy your Frontend API, you'll need to to create the link between Clerk and Hasura.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./9386188495ad4b6f061a00364f397295fe6ed8f0-1046x454.png)

With your project already running, it's time to go back to Hasura and start setting up the database.

## Set up Hasura Cloud

Go back to Hasura, click the cog wheel, click **"Env vars"** and then **"New Env Var"**.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./6e87e29874cfedabb12fa0f18dd7bdb8243929bf-1144x556.png)

Pick HASURA\_GRAPHQL\_JWT\_SECRET from the list and then add this, replacing **%FRONTEND\_API%** with the Frontend API you copied from Clerk.

```bat
{"jwk_url":"https://%FRONTEND_API%/v1/.well-known/jwks.json"}
```

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./1b8ffd6da9dd20b504f25ef5f5f8edaad0ccb2e6-527x461.png)

Click "Add" and then, click "Launch Console".

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./1c5c860f88e543bcca4bc0326ca10d7ba5657bbd-1142x455.png)

This will bring us to GraphiQL. GraphiQL is the GraphQL integrated development environment (IDE). It's a powerful tool you can use to interact with the API.

After GraphiQL opens, the first thing you need to do is to create a table. Start by clicking Data on the top navbar:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./235d8400a644434f2a5e1f611f1dac4c48863ef7-1920x947.png)

For this tutorial, we recommend creating a Heroku database for free:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./1d96a16745ba10676e89944599b6ceadadef008e-792x331.png)

If you don't have a Heroku account, now is the time to create one.

Follow the steps and the database will automatically be created and linked for you.

After the database is created, click **"Public"** and then **"Create Table"**

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./8698910f66341bfe6c355d84552a113a6b0867b0-681x478.png)

Fill the table like this and **"Add Table"**.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./51f8cd6e28ac4ac497ae5ddc56426b0acfb31e66-1007x645.png)

This not only creates our table, but also triggers Hasura to create a GraphQL backend.

After creating the table, the next step is to restrict who can access the data. By default, Hasura is configured for all fields to be public. You need to set permissions and fix that.

### Set table permissions

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./592153500640383cd960b95b03667109bfbac9a6-609x191.png)

You need to create a new role called "user" and edit each of the four possible permissions they have. If you are familiar with **CRUD** (Create, Read, Update, Delete), this is basically the same thing.

### Insert (Create)

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./bbc6ae94e0cc9ed1f528850126775f134b3780d7-1243x811.png)

For **Insert** permissions, choose that the user can only set the `title` of a to-do when a new one is created. There others all have default values:

- `id` is autogenerated (set during table creation)
- `completed` starts as `false`
- `created_at` is autogenerated to `now()` (set during table creation)
- `user_id` is set to the requesting user's ID

Since the `user_id` is dependent on the particular request, it must be configured as a "Column preset."Set it to `X-Hasura-User-Id` from the "session variable."

When you use Clerk's Hasura integration, `X-Hasura-User-ID` is automatically set in the session variable that gets sent to Hasura. The code to retrieve the session variable and send it to Hasura is in `lib/apolloClient.js`.

### Select (Read)

For **Select** permissions, you want to configure Hasura so users can only read their own to-dos. You can verify this by "checking" if the to-do's `user_id` is the same as the `X-Hasura-User-Id` you receive from the session variable.

If the user ID's match, you can grant read permissions to every column. The exact configuration required is below:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./4835557a24bb810db6c74ac78a1e5107f0779e50-583x715.png)

### Update

For **Update** permissions, you want to include the same "check" as **Select**, to ensure that a user can only update their own to-dos.

However, if the check is valid, you don't want the user to have permission to update every column. Instead, only grant permission to update the `completed` column.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./16fc8d112053b024ddd9f20218aea292ddbd350f-560x758.png)

### Delete

For **Delete** permissions, you want to include the same "check" as **Select**, to ensure that a user can only delete their own to-dos.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./cdfcf7790ce2e6d07238c23aad1e6695da0c5139-538x425.png)

That's all of the permissions we need to set! Now, let's work on the frontend.

## Connect Hasura to the Frontend

Go to [http://localhost:3000](http://localhost:3000) and create an account on your app. Then, click **"Start saving your todos"** and you will see this:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./c18fe60869e319bd82bcb6e8f3e72e3125fcf3d7-485x316.png)

These is sample data and is still static. In the next steps of the tutorial, we will connect this list to Hasura and your database, so users can create and manage their own to-dos.

### Create a to-do

The first step is giving users the ability to create a to-do. We will do this from `components/AddTodo.js`.

If you look at the `onSubmit` function, you will see that nothing will currently happen when the user clicks add. You must create a GraphQL "mutation" to update the database when add is clicked.

Replace the top of your file (everything above the return statement) with this code:

```jsx {{ prettier: false }}
import { gql, useMutation } from '@apollo/client'
import { useState } from 'react'

const ADD_TODO = gql`
  mutation AddTodo($title: String!) {
    insert_todos_one(object: { title: $title }) {
      id
      title
    }
  }
`;

const AddTodo = () => {
  const [title, setTitle] = useState("");
  const [addTodo] = useMutation(ADD_TODO, {
    onCompleted: () => setTitle(""),
  });

  const onSubmit = (e) => {
    e.preventDefault();
    addTodo({
      variables: { title },
    });
  };

  return (...
```

This mutation accepts a title and passes it to the `insert_todos_one` method that Hasura has created for us.

Now, let's go back to our frontend and try adding a todo.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./5ca789e007ad71c91b663402b4dc6619f5ad81c6-430x108.png)

You'll see notice that nothing happens on the frontend, and that's expected because we're still reading static to-dos. But, let's check the database to see if the mutation succeeded. Go back to the Hasura Cloud Console, copy and paste the following query and click the play button:

```graphql
query GetTodos {
  todos {
    id
    title
    user_id
    created_at
    completed
  }
}
```

You should see your todo was created successfully:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./6a24c4a662abb8aca62498b14c6de56890aedfcf-953x384.png)

### Fetch to-dos

Now, we will update the frontend to read the user's to-dos from Hasura. You can do this from `components/TodoList.js`.

The file starts by showing static data. Update the component to instead run a GraphQL "query":

```jsx
import { gql, useQuery } from '@apollo/client'

import SingleTodo from '../components/SingleTodo'

export const GET_TODOS = gql`
  query GetTodos {
    todos(order_by: { created_at: desc }) {
      id
      title
      completed
    }
  }
`

const TodoList = () => {
  const { loading, error, data } = useQuery(GET_TODOS)

  if (loading) return 'Loading...'

  if (error) return <>{console.log(error)}</>

  return (
    <div className="overflow-hidden rounded-md bg-white shadow">
      <ul className="divide-y divide-gray-200">
        {data?.todos.map((todo) => (
          <SingleTodo key={todo.id} todo={todo} />
        ))}
      </ul>
    </div>
  )
}

export default TodoList
```

First, we created a query that gets all to-dos (remember, the user can only see the ones attached to their own `user_id`). We set the query to return `id`, `title`, and `completed`. We order the to-dos by `created_at` descending, so the newest are first in the list.

`useQuery` returns an object so you can render different things depending on if the data is loading, if there's an error, or if the data has been retrieved.

We've configured an early return while the data is loading or if there's an error, then render the list if that is available. After saving, you should see something like this:

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./5a80afdca9917e3ec1fb8fdcb49e8bd086b23ab1-268x178.png)

Let's try adding a new todo.

![Build A To Do App With Clerk And Hasura And No Backend Code guide illustration](./85f7ac27b6b73c4343812e4a42fae99dabdc79a2-304x189.png)

You should see that the form clears after clicking "Add", but the list below doesn't automatically update. However, if you manually refresh the page, you will see new to-do.

That's not the best experience and we will fix this later by implementing a cache, so your can keep your database and your frontend in sync.

Before that, let's implement toggle and delete mutations.

### Delete Todo

Open `components/SingleTodo.js`, which is the component the renders for each individual to-do.

Update the code to add a delete mutation when the delete button is clicked:

```jsx {{ prettier: false }}
import { gql, useMutation } from '@apollo/client'
import { GET_TODOS } from './TodoList'

const DELETE_TODO = gql`
  mutation DeleteTodo($id: uuid!) {
    delete_todos_by_pk(id: $id) {
      id
      title
    }
  }
`

const SingleTodo = ({ todo }) => {
  const [deleteTodoMutation] = useMutation(DELETE_TODO)

  const deleteTodo = () => {
    deleteTodoMutation({
      variables: { id: todo.id },
    })
  }

  // rest of the code
```

Now, try deleting a todo. It works, but you get same experience as inserting. You need to refresh the page to see it.

We will fix this shortly, but first let's add toggle functionality.

### Toggle Todo

Still inside `components/SingleTodo.js`, now you can add a new toggle mutation. Here is the updated component with both delete and toggle functionality:

```jsx
import { gql, useMutation } from '@apollo/client'
import { TrashIcon } from '@heroicons/react/solid'
import { GET_TODOS } from './TodoList'

const DELETE_TODO = gql`
  mutation DeleteTodo($id: uuid!) {
    delete_todos_by_pk(id: $id) {
      id
      title
    }
  }
`

const TOGGLE_TODO = gql`
  mutation ToggleTodo($id: uuid!, $completed: Boolean!) {
    update_todos_by_pk(pk_columns: { id: $id }, _set: { completed: $completed }) {
      id
      completed
    }
  }
`

const SingleTodo = ({ todo }) => {
  const [deleteTodoMutation] = useMutation(DELETE_TODO)
  const [toggleTodoMutation] = useMutation(TOGGLE_TODO)

  const deleteTodo = () => {
    deleteTodoMutation({
      variables: { id: todo.id },
    })
  }
  const toggleTodo = () => {
    toggleTodoMutation({
      variables: { id: todo.id, completed: !todo.completed },
    })
  }

  return (
    <li key={todo.id} className="flex justify-between px-6 py-4">
      <div>
        <input
          id={todo.id}
          name="completed"
          type="checkbox"
          checked={todo.completed}
          onChange={toggleTodo}
          className="mr-3 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
        />
        <label htmlFor={todo.id} className={todo.completed ? 'text-gray-400 line-through' : ''}>
          {todo.title}
        </label>
      </div>
      <TrashIcon className="h-5 w-5 cursor-pointer text-gray-500" onClick={deleteTodo} />
    </li>
  )
}

export default SingleTodo
```

Now, every CRUD operation works. But you need still need to refresh the page to see changes. Let's fix that.

Notice we are importing `GET_TODOS`, we'll need it for the next step.

### Using Apollo Cache

The GraphQL library this tutorial uses, Apollo, implements a dynamic, local cache. Instead of reloading the full list of updates after each mutation, you can run the mutations against your local cache. Then, the to-do list on your frontend will automatically be updated.

One great feature of this cache is called the `optimisticResponse`. With this, you can assume that your GraphQL mutations will succeed and reflect the change in your frontend right away, instead of waiting for the success message from Hasura. The `optimisticResponse` is preferred for your to-do app since you're not anticipating any errors, and it results in a faster-feeling user experience.

To use the cache, you need to add the `cache` and `optimisticResponse` parameters to your mutation functions.

In your `deleteTodo` function:

```jsx
const deleteTodo = () => {
  deleteTodoMutation({
    variables: { id: todo.id },
    optimisticResponse: true,
    update: (cache) => {
      const data = cache.readQuery({ query: GET_TODOS })
      const todos = data.todos.filter(({ id }) => id !== todo.id)
      cache.writeQuery({
        query: GET_TODOS,
        data: { todos },
      })
    },
  })
}
```

In your `toggleTodo` function:

```jsx
const toggleTodo = () => {
  toggleTodoMutation({
    variables: { id: todo.id, completed: !todo.completed },
    optimisticResponse: true,
    update: (cache) => {
      const data = cache.readQuery({ query: GET_TODOS })
      const todos = data.todos.map((t) => {
        if (t.id === todo.id) {
          return { ...t, completed: !todo.completed }
        }
        return t
      })

      cache.writeQuery({
        query: GET_TODOS,
        data: { todos },
      })
    },
  })
}
```

Finally, we must leverage the cache in `components/AddTodo.js`:

At the top of the file, add:

```jsx
import { GET_TODOS } from './TodoList'
```

And update your `onSubmit` as follows:

```jsx
const onSubmit = (e) => {
  e.preventDefault()
  addTodo({
    variables: { title },
    update: (cache, { data }) => {
      const existingTodos = cache.readQuery({
        query: GET_TODOS,
      })
      cache.writeQuery({
        query: GET_TODOS,
        data: { todos: [data.insert_todos_one, ...existingTodos.todos] },
      })
    },
  })
}
```

## Final thoughts

That's it! You now have a complete to-do list using Clerk, Hasura, and Next.js - and you didn't write any backend code. It's powerful, easy to configure, and easy to scale.

If you have enjoyed this tutorial or have questions or concerns, please check our [support page](https://clerk.com/contact/support). If you prefer Twitter, feel free to contact me ([@nachoiacovino](https://twitter.com/nachoiacovino)) or Clerk ([@clerk](https://x.com/clerk)) directly.