user20706285
user20706285

Reputation: 21

Nextjs Clerk Webhook shows no response

I have integrated clerk authentication in my nextjs app. Now I need to save the users in MongoDB through clerk webhook. I have already hosted my application to vercel, added ${vercel_site}/api/webhook endpoint in clerk, picked up the clerk webhook key and added it to .env.local but so far nothing is working. In clerk, I am getting the message:

This endpoint has not received any messages yet.

There are no errors in the console, the application seems to be working fine but I am not getting any response from clerk. What might be the problem?

api/webhook/route.js

import { Webhook } from "svix";
import { headers } from "next/headers";
import { createOrUpdateUser } from "../../lib/controllers/user.controller.js";

export async function POST(req) {
  // You can find this in the Clerk Dashboard -> Webhooks -> choose the webhook
  const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;

  if (!WEBHOOK_SECRET) {
    throw new Error(
      "Please add WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local"
    );
  }

  // Get the headers
  const headerPayload = headers();
  const svix_id = headerPayload.get("svix-id");
  const svix_timestamp = headerPayload.get("svix-timestamp");
  const svix_signature = headerPayload.get("svix-signature");

  // If there are no headers, error out
  if (!svix_id || !svix_timestamp || !svix_signature) {
    return new Response("Error occured -- no svix headers", {
      status: 400,
    });
  }

  // Get the body
  const payload = await req.json();
  const body = JSON.stringify(payload);

  // Create a new Svix instance with your secret.
  const wh = new Webhook(WEBHOOK_SECRET);

  let evt;

  // Verify the payload with the headers
  try {
    evt = wh.verify(body, {
      "svix-id": svix_id,
      "svix-timestamp": svix_timestamp,
      "svix-signature": svix_signature,
    });
  } catch (err) {
    console.error("Error verifying webhook:", err);
    return new Response("Error occured", {
      status: 400,
    });
  }

  // Handle the event
  const eventType = evt?.type;

  if (eventType === "user.created" || eventType === "user.updated") {
    const { id, first_name, last_name, profile_image_url, email_addresses } =
      evt?.data;

    try {
      await createOrUpdateUser(
        id,
        first_name,
        last_name,
        profile_image_url,
        email_addresses,
      );

      return new Response("User is created or updated", {
        status: 200,
      });
    } catch (err) {
      console.error("Error creating or updating user:", err);
      return new Response("Error occured", {
        status: 500,
      });
    }
  }
}

user.controller.js

import User from '../models/Users.model.js';
import { connectToDB } from '../mongo.js';

 export const createOrUpdateUser = async(id, first_name, last_name, profile_image_url,      email_addresses) => {
 try{
    await connectToDB();

    const user = await User.findOneAndUpdate(
        { clerkId: id },
        {
          $set: {
            firstName: first_name,
            lastName: last_name,
            profilePhoto: profile_image_url,
            email: email_addresses[0].email_address,
          },
        },
        { upsert: true, new: true } // if user doesn't exist, create a new one
      );
  
      await user.save();
      return user;
    } catch (error) {
      console.error(error);
    }
}

Connection to database

 import mongoose from "mongoose";

 let isConnected = false;

 export const connectToDB = async () => {
     mongoose.set("strictQuery", true);

   if (isConnected) {
     console.log("Database is connected");
   } else {
    try {
      await mongoose.connect(process.env.MONGO_STRING, {
        dbName: "Users",
        useNewUrlParser: true,
         useUnifiedTopology: true,
      });
      isConnected = true;
    } catch (error) {
      console.log(error);
    }
  }
};

In route.js, I tried to console.log(svix_id, svix_timestamp, svix_signature) but again no response. This makes me to wonder, is this file even getting called in the first place. I also tried to catch any errors in case the POST request fails but there is no error so far.

catch (err) {
      console.error("Error creating or updating user:", err);
      return new Response("Error occured", {
        status: 500,
      });
    }

Upvotes: 1

Views: 527

Answers (1)

Carlos Damian Perez
Carlos Damian Perez

Reputation: 161

You can try removing the autentication in the vercel app settings -> under deployment protection turn of vercel authentication. i was getting 401 and webhooks were not working this change everything. and now is working as expected

Upvotes: 0

Related Questions