New product features | The latest in technology | The weekly debugging nightmares & more!
July 25, 2023
Take my knowledge and shove it up your brain...
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...
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
How to add credential authentication using Auth.js & Next 14
Allow users to login using their email & password.
How to add email verification using Auth.js
Enhance your website security by allowing only verified users to log in.
How to enable password reset using auth.js
Forgot your password? now worries, I got your bro.
How to add 2-factor authentication
Enhance your users' security using 2-factor authentication