Щоб перевірити вебхуки Clerk на локальному хості в Next.js, створіть POST-маршрут App Router, відкрийте порт 3000 за допомогою тунелю HTTPS, додайте загальнодоступну URL-адресу як кінцеву точку вебхуку Clerk і перевіряйте кожен запит за допомогою verifyWebhook() перед синхронізацією даних користувача. Зберігайте маршрут відкритим у проміжному програмному забезпеченні Clerk: секрет підпису автентифікує міжмашинний запит, а не сеанс браузера.
Коли вебхуки Clerk є правильним інструментом синхронізації
Clerk залишається джерелом істини. Вебхук корисний, коли вашій програмі потрібна локальна проекція для об’єднань, пошуку, звітування, метаданих авторизації або інтеграцій, які не можуть запитувати Clerk на вимогу. Типові події включають user.created, user.updated, і user.deleted.
Вебхук є асинхронним. Користувач може завершити реєстрацію до того, як ваша проекція бази даних буде створена, доставку можна спробувати повторно, а оновлення можуть надійти близько один до одного. Не робіть проекцію єдиним джерелом для перевірки особи відразу після реєстрації. Дизайн допускає коротку затримку або створює рядок програми явно в потоці користувача та дозволяє вебхукам узгоджувати його.
Створіть загальнодоступну кінцеву точку маршрутизатора програми Next.js
додати app/api/webhooks/clerk/route.ts. Clerkівський струм посібник із синхронізації використовує verifyWebhook від @clerk/nextjs/webhooks. Помічник використовує запит, перевіряє підпис Standard Webhooks і повертає введені дані події.
// app/api/webhooks/clerk/route.ts
import { verifyWebhook } from '@clerk/nextjs/webhooks';
import { NextRequest } from 'next/server';
export const runtime = 'nodejs';
export async function POST(request: NextRequest) {
try {
const event = await verifyWebhook(request);
await processOnce(event, async () => {
switch (event.type) {
case 'user.created':
case 'user.updated':
await upsertClerkUser(event.data);
break;
case 'user.deleted':
if (event.data.id) await archiveClerkUser(event.data.id);
break;
}
});
return new Response('accepted', { status: 200 });
} catch (error) {
console.error('Clerk webhook rejected', safeError(error));
return new Response('invalid webhook', { status: 400 });
}
}
За замовчуванням помічник читає CLERK_WEBHOOK_SIGNING_SECRET. Clerk verifyWebhook посилання також дозволяє явний signingSecret параметр, але конфігурація середовища уникає вбудовування секрету в джерело.
Виключити маршрут webhook із захисту сеансу
Запити Webhook не передають сеанс Clerk вашого користувача. Якщо виклики проміжного ПЗ auth.protect() для кожного шляху API доставка Clerk отримує перенаправлення 401 або 404 перед запуском перевірки підпису. Визначте захищені маршрути додатків явно та вийдіть /api/webhooks/clerk громадськість.
// middleware.ts for Next.js 15 and earlier
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isProtectedRoute = createRouteMatcher([
'/dashboard(.*)',
'/api/private(.*)',
]);
export default clerkMiddleware(async (auth, request) => {
if (isProtectedRoute(request)) await auth.protect();
});
export const config = {
matcher: [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico)).*)',
'/(api|trpc)(.*)',
],
};
Clerk посібник із налагодження вебхука спеціально викликає виключення маршрутів вебхуку. У новіших версіях Next.js може використовуватися конвенція proxy.ts; дотримуйтеся посібника з версії Clerk, встановленого у вашому проекті. Громадський не означає довірений: verifyWebhook() є обов'язковим перед будь-якими діями.
Підключіть Clerk до localhost
- бігти
npm run devі переконайтеся, що програма Next.js прослуховує порт 3000. - бігти
npx portpreview 3000. - На інформаційній панелі Clerk створіть кінцеву точку вебхуку за допомогою
https://your-subdomain.portpreview.dev/api/webhooks/clerk. - Виберіть лише потрібні події користувача, сеансу, організації чи електронної пошти.
- Скопіюйте секрет підпису кінцевої точки
CLERK_WEBHOOK_SIGNING_SECRETу вашому локальному середовищі та перезапустіть Next.js. - Відкрийте вкладку «Тестування» кінцевої точки, виберіть
user.createdі виберіть Надіслати приклад. - Переконайтеся, що спроба каже «Успішно», ваш локальний маршрут повернув 200, а очікуваний рядок бази даних змінився один раз.
URL-адреса тунелю має залишатися активною для подальших прикладів. Якщо зміниться, оновіть кінцеву точку. Не використовуйте повторно секрет підпису робочої кінцевої точки для локальних тестів; створювати кінцеві точки для певного середовища, щоб історія ротації та аудиту залишалася чіткою.
Ретельно моделюйте синхронізацію користувачів
Використовуйте ідентифікатор користувача Clerk як зовнішній ключ
Магазин user_... в унікальному clerk_user_id колонка. Upsert на цьому ключі, тому повторна спроба user.created зближується замість того, щоб виходити з ладу. Зберігайте власний внутрішній первинний ключ, якщо на нього вже посилаються інші таблиці.
Вибирайте основну електронну адресу свідомо
Дані користувача Clerk містять записи адрес електронної пошти та ідентифікатор основної адреси електронної пошти. Розділіть основний запис за ідентифікатором замість першого елемента масиву. Електронна пошта може змінюватися; не використовуйте його як незмінний зовнішній ключ.
Вирішіть, що означає видалення
А user.deleted Подія може містити менше даних, ніж створити або оновити. Використовуйте ідентифікатор для анонімізації, м’якого видалення або запуску робочого циклу збереження відповідно до вашої політики. Сліпе каскадне видалення може знищити записи про виставлення рахунків або аудит, збереження яких вимагають нормативні акти.
Не віддзеркалюйте все
Зберігайте лише ті поля, які потрібні вашій програмі. Кожне скопійоване поле профілю створює зобов’язання конфіденційності, збереження та застарілості. Отримайте рідко використовувані дані Clerk на вимогу, а не дублюйте всю корисну інформацію.
Зробіть повторні спроби та замовлення нешкідливими
Clerk документує, що відповідь, відмінна від 2xx, викликає повторну спробу події. Запишіть ідентифікатор повідомлення вебхуку з підписаних метаданих або заголовків вебхуку як унікальну квитанцію перед застосуванням ефектів. Якщо ваш SDK надає стандартні ідентифікатори вебхуків у заголовках, збережіть їх разом із типом події та міткою часу. Поверніть 200 для завершеного дубліката.
Для оновлень користувачів порівняйте позначки часу подій або використовуйте правила останнього запису, які запобігають перезапису старішою подією нових даних профілю. Для високого стану отримайте поточного користувача з Clerk після перевірки та розглядайте вебхук як сигнал для узгодження. Зберігайте вставку квитанції, оновлення користувача та завдання вихідної папки в одній транзакції бази даних.
await db.transaction(async (tx) => {
const inserted = await tx.webhookReceipt.insertIfAbsent(messageId);
if (!inserted) return;
await tx.user.upsert({
clerkUserId: clerk.id,
primaryEmail: findPrimaryEmail(clerk),
sourceUpdatedAt: eventTimestamp,
});
await tx.outbox.enqueue('profile-synced', { clerkUserId: clerk.id });
});
Цей шаблон запобігає дублюванню вітальних листів і частковим записам. див повторні спроби веб-хуку та ідемпотентність для параметрів схеми.
Вирішення проблем із доставкою місцевого Clerk
404, переспрямування або HTML замість вашого обробника
Перевірте шлях до файлу, експорт POST і повну URL-адресу тунелю. Перевірте перезапис проміжного програмного забезпечення та локалі. Вебхук не повинен проходити через переспрямування входу або перевірку форми CSRF. Перевірте загальнодоступну URL-адресу за допомогою простого POST; очікуйте відхилення підпису від вашого маршруту, а не фреймворку 404.
verifyWebhook() завжди кидає
Перезапустіть Next.js після встановлення секретного підпису. Підтвердьте, що секрет належить цій кінцевій точці та середовищу. Не аналізуйте, не клонуйте неправильно та не використовуйте тіло запиту, перш ніж передати його помічнику. Переконайтеся, що тунель зберігає стандартні заголовки підпису Webhooks.
Інформаційна панель показує повторні спроби
Подивіться на точну відповідь спроби. Повертайте 2xx лише після тривалого прийняття, але продовжуйте обробку нижче часу очікування постачальника. Переміщення бази даних, помилки унікальних обмежень і синхронний виклик недоступної служби є поширеними 500 причинами.
Рядки дублюються або застарілі
Додайте унікальні обмеження для ідентифікатора Clerk ID та ідентифікатора повідомлення webhook. зробити user.created і user.updated обидві безпечні upserts, а потім захистити від старіших позначок часу подій. Відтворюйте приклад після кожного виправлення, щоб підтвердити повторну обробку.
Контрольний список безпеки
- Перевіряйте кожен запит за допомогою помічника Clerk, перш ніж реєструвати поля корисного навантаження або записувати дані.
- Зберігайте маршрут без автентифікації проміжним програмним забезпеченням сеансу користувача, але захищеним підписом вебхука.
- Використовуйте окремі секрети кінцевих точок для локального середовища, середовища попереднього перегляду, постановки та виробництва.
- Дедуплікація підписаних ідентифікаторів повідомлень і однозначне обмеження ідентифікаторів користувачів.
- Видаліть електронну пошту, телефон, маркери, секрети та повне корисне навантаження зі звичайних журналів.
- Додатково додайте задокументовані IP-контролю Clerk/Svix як глибокий захист, але ніколи не замінюйте перевірку підпису фільтрацією IP.
- Обмежте швидкість недійсного трафіку, обмежте розмір тіла та змініть секрет, якщо він з’являється в журналах або системі керування джерелами.
Clerk огляд веб-хуків пояснює перевірку підпису та додаткові обмеження IP-адреси Svix. Щодо основ необробленого тіла Next.js і поведінки маршруту продовжуйте з Посібник з вебхуку локального хосту Next.js.
