Nader's Daily Blog
Welcome to Every Developers favorite blog in the Devosphere

New product features | The latest in technology | The weekly debugging nightmares & more!

Sync clerk data with your database using webhooks

Sync clerk data with your database using webhooks

July 25, 2023

Nader Elmahdy

Nader Elmahdy

Take my knowledge and shove it up your brain...

Learn how to store users data on your database using webhooks

Authentication

By default, clerk stores users' data on their servers, but in some cases, you might need to store their data on your own database.

for example, if you have an e-commerce website, you'll need to store their data (name, email, etc..) in addition to their cart, orders, wishlist, and so on...

Webhooks

If you don't know what webhooks are, they are similar to API endpoints, they connect multiple applications together, in our case we'll connect clerk with our backend.

So in order to create a webhook you'll need to go to your application and in your API folder create a new route for the webhook (eg: api/webhook/route.ts)

This is the code that we're going to use:

route.ts

1import { createUserAfterAuth } from "@/lib/users"; // a function that creates a user in the database after they have been authenticated
2import { IncomingHttpHeaders } from "http";
3import { headers } from "next/headers";
4import { NextResponse } from "next/server";
5import { Webhook, WebhookRequiredHeaders } from "svix";
6const webhookSecret = process.env.WEBHOOK_SECRET || "";
7async function handler(request: Request) {
8  const payload = await request.json();
9  const headersList = headers();
10  const heads = {
11    "svix-id": headersList.get("svix-id"),
12    "svix-timestamp": headersList.get("svix-timestamp"),
13    "svix-signature": headersList.get("svix-signature"),
14  };
15  const wh = new Webhook(webhookSecret);
16  let evt: Event | null = null;
17  try {
18    evt = wh.verify(
19      JSON.stringify(payload),
20      heads as IncomingHttpHeaders & WebhookRequiredHeaders
21    ) as Event;
22  } catch (err) {
23    console.error((err as Error).message);
24    return NextResponse.json({}, { status: 400 });
25  }
26  const eventType: EventType = evt.type;
27  if (eventType === "user.created") {
28    const { id, ...attributes } = evt.data;
29    await createUserAfterAuth(
30      id,
31      attributes.first_name + " " + attributes.last_name,
32      attributes.email_addresses[0].email_address,
33      attributes.image_url
34    );
35  }
36}
37type EventType = "user.created" | "*";
38type Event = {
39  data: Record<string, string | number | any>;
40  object: "event";
41  type: EventType;
42};
43export const GET = handler;
44export const POST = handler;
45export const PUT = handler;
46



Let's understand what this code does:

In the first line, I imported a function that I created, this function simply takes a new user in my database.

So I need to call this function every time a new user logs in.

Luckily Clerk has many events that we can listen to.

Such events as user created, user updated, session created, session ended, and many more.

We're only interested in the user created event, so in line 27, you'll see that I check if the event is user.created , then I get the name, email, and image of the user and store them in my database.

Once you're done with that, push these updates to GitHub, then go to Clerk dashboard and select webhooks.


Click Add Endpoint then paste the link of your webhook (eg: https://mywebsite.com/api/webhook)

And now every time a new user logs in, you should be able to store his data in your database, so you can allow him to change it later.

Just don't forget to install svix: npm i svix

You might also like: