Skip to content

Find a component

Loading the directory…

↑ ↓ to select · Enter to open · Esc to closeBrowse all →
Contributor login

Kinde Sync

A kinde sync component for Bijection.

Bijection source
git clone https://github.com/bijectionhq/kinde-sync.git
cd kinde-sync
git checkout 55b4a880315f1e865b4088125364ec89282bdddc

Bijection repository access is required. Request access.

Description

A kinde sync component for Bijection.

Explore the package README for API concepts, configuration, and examples. Check the Bijection source for adaptation-specific setup.

Available to evaluate

Review the source and its dependencies before adopting this package. Source availability does not establish npm publication or runtime qualification.

Getting started

  1. Get the source at the revision above and read its package documentation.
  2. Check the required Bijection SDK version, dependencies, and external service credentials.
  3. Follow the package setup instructions and the guide to using components.
  4. Exercise the component in your deployment according to your project’s verification rules.

Open source

Maintained source: bijectionhq/kinde-sync. Based on sholajegede/kinde-sync. License: Apache-2.0. Consult the repository for license terms, notices, and contributor attribution.

From the upstream publisher

A kinde sync component for Convex.

Explore the demo ↗

Upstream overview

From the upstream package documentation.

Automatically syncs Kinde authentication events into your Convex database via webhook handlers. Eliminates the need to write custom JWT verification, event parsing, and user synchronization logic. When users are created, updated, or deleted in Kinde, your Convex tables update in real-time without polling or manual intervention.

Use cases

From the upstream package documentation.

  • Building user dashboards that need to display real-time user data without fetching from Kinde's API on every request
  • Implementing user management features where you need to query, filter, or aggregate user data using Convex's reactive queries
  • Creating admin interfaces that show live user statistics, organization membership, or suspension status
  • Supporting offline-first applications where user data needs to be locally available in your Convex database
  • Building user-triggered workflows that need to react immediately when users are created or updated in Kinde

How it works

From the upstream package documentation.

The component provides a KindeSync class that wraps JWT verification and webhook processing. You mount the webhookHandler in your convex/http.ts file to create an endpoint that Kinde can POST to. When Kinde sends webhook events, the component automatically verifies the JWT signature against Kinde's JWKS endpoint and deduplicates events by webhook ID.

User data gets stored in a component-managed Convex table with fields like kindeId, email, organizations, and isSuspended. The component exposes reactive query functions like getUser, getUserByEmail, and listUsers that you can call from your own Convex functions using ctx.runQuery(components.kindeSync.lib.getUser, args).

Setup requires configuring your Kinde webhook URL to point at your Convex deployment's /webhooks/kinde endpoint and setting environment variables for your Kinde issuer URL. The component handles user.created, user.updated, and user.deleted events automatically, keeping your local user data in sync without any polling or manual API calls.

Upstream package FAQ

Does Kinde Sync handle webhook signature verification?

Yes, Kinde Sync automatically verifies JWT signatures from Kinde webhooks against Kinde's JWKS endpoint. The component handles all cryptographic verification without requiring you to write JWT validation code or manage signing keys manually.

How does the component prevent duplicate webhook processing?

Kinde Sync deduplicates events using webhook IDs to ensure each event is processed only once. This prevents duplicate user records or state inconsistencies if Kinde retries webhook deliveries or sends the same event multiple times.

Can I customize which user fields get synced to Convex?

The component syncs standard Kinde user fields into a component-owned Convex table. You can query this table and transform or extend the data in your own mutations and queries as needed for your application's requirements.

What happens when users are deleted in Kinde?

Kinde Sync automatically removes deleted users from the Convex table when it receives user deletion webhook events from Kinde. Your frontend queries will reactively update to reflect the user removal without additional code.

Use with agents and CLI

Give your coding agent the component’s source identity and setup guidance.

agent-prompt.md
Help me integrate Kinde Sync with Bijection.

Read: https://bijection.com/components/kinde-sync/SKILL.md

Check SDK compatibility and dependency availability.
Follow this project's execution and verification rules.

Upstream README.md

View repository ↗

Documentation from sholajegede/kinde-sync, recorded October 23, 2026. APIs and setup may differ in the Bijection adaptation.

@sholajegede/kinde-sync

A Convex component that syncs Kinde users into your Convex database in real time via webhooks. When a user is created, updated, or deleted in Kinde, your Convex database updates instantly — no polling, no boilerplate JWT verification, no manual sync logic.

Found a bug? Feature request? File it here.

How it works

Without this component, every Convex + Kinde app has to write the same webhook handler: validate the JWT, parse the event, upsert the user. This component does all of that for you. Point your Kinde webhook at your Convex deployment and your users are synced automatically.

Kinde sends a JWT-signed POST request to your endpoint on every user event. The component verifies the signature against Kinde's JWKS endpoint, deduplicates events by webhook ID, and upserts or deletes the user in a component-owned Convex table. Your frontend subscribes reactively via useQuery.

Prerequisites

  • A Kinde account with an application configured
  • Your Kinde issuer URL, client ID, and client secret (see below for how to find these)

Getting your Kinde credentials

1. Create a Kinde account and application

Go to kinde.com and sign up. Once inside the dashboard, you will already have a default application created. Click View details on your app.

2. Find your credentials

On the application details page you will find:

  • KINDE_ISSUER_URL — shown as your domain e.g. https://yourapp.kinde.com
  • KINDE_CLIENT_ID — labeled "Client ID"
  • KINDE_CLIENT_SECRET — labeled "Client secret" (click to reveal)

3. Set your redirect URLs

Still on the application details page, set:

  • Allowed callback URLs: http://localhost:3000 (add your production URL when deploying)
  • Allowed logout redirect URLs: http://localhost:3000

Your .env.local should look like this:

KINDE_CLIENT_ID=your_client_id
KINDE_CLIENT_SECRET=your_client_secret
KINDE_ISSUER_URL=https://yourapp.kinde.com
KINDE_SITE_URL=http://localhost:3000
KINDE_POST_LOGOUT_REDIRECT_URL=http://localhost:3000
KINDE_POST_LOGIN_REDIRECT_URL=http://localhost:3000/dashboard

Installation

npm install @sholajegede/kinde-sync

Add the component to your convex/convex.config.ts:

import { defineApp } from "convex/server";
import kindeSync from "@sholajegede/kinde-sync/convex.config.js";

const app = defineApp();
app.use(kindeSync);

export default app;

Setup

1. Mount the webhook handler in convex/http.ts:

import { httpRouter } from "convex/server";
import { components } from "./_generated/api.js";
import { KindeSync } from "@sholajegede/kinde-sync";

const kindeSync = new KindeSync(components.kindeSync, {
  KINDE_ISSUER_URL: process.env.KINDE_ISSUER_URL!,
});

const http = httpRouter();

http.route({
  path: "/webhooks/kinde",
  method: "POST",
  handler: kindeSync.webhookHandler,
});

export default http;

2. Set your Convex environment variables:

npx convex env set KINDE_ISSUER_URL https://yourapp.kinde.com
npx convex env set KINDE_CLIENT_ID your_client_id
npx convex env set KINDE_CLIENT_SECRET your_client_secret

3. Configure Kinde auth for ctx.auth:

This component handles webhook sync only. To enable ctx.auth in your Convex functions, create convex/auth.config.ts:

const authConfig = {
  providers: [
    {
      domain: process.env.KINDE_ISSUER_URL,
      applicationID: process.env.KINDE_CLIENT_ID,
    },
  ],
};

export default authConfig;

4. Register the webhook in your Kinde dashboard:

  1. Go to your Kinde dashboard → Settings → Webhooks
  2. Click Add webhook
  3. Give it a name e.g. Convex user sync
  4. In the Endpoint URL field, enter your Convex HTTP actions URL:
   https://<your-deployment>.convex.site/webhooks/kinde

You can find your Convex site URL by running npx convex dev and looking for VITE_CONVEX_SITE_URL in your .env.local, or on the Convex dashboard under your deployment settings. 5. Under Event triggers, select:

  • user.created
  • user.updated
  • user.deleted
  1. Click Save

To verify it's working, create a user in your Kinde dashboard and check your Convex dashboard logs — you should see the webhook fire and the user appear in your kindeUsers table instantly.

Usage

Query synced users reactively from your Convex functions:

import { query } from "./_generated/server.js";
import { components } from "./_generated/api.js";
import { v } from "convex/values";

export const getUser = query({
  args: { kindeId: v.string() },
  handler: async (ctx, args) => {
    return await ctx.runQuery(components.kindeSync.lib.getUser, {
      kindeId: args.kindeId,
    });
  },
});

export const listUsers = query({
  args: {},
  handler: async (ctx) => {
    return await ctx.runQuery(components.kindeSync.lib.listUsers, {});
  },
});
// React
const user = useQuery(api.myFunctions.getUser, { kindeId: "kp_..." });
const users = useQuery(api.myFunctions.listUsers, {});

API

KindeSync class

OptionTypeDescription
KINDE_ISSUER_URLstringYour Kinde issuer URL e.g. https://yourapp.kinde.com
PropertyDescription
webhookHandlerHTTP action to mount in convex/http.ts

Reactive queries

FunctionArgsReturns
components.kindeSync.lib.getUser{ kindeId: string }User or null
components.kindeSync.lib.getUserByEmail{ email: string }User or null
components.kindeSync.lib.listUsers{}Array of users

User shape

{
  kindeId: string;
  email: string;
  firstName?: string;
  lastName?: string;
  imageUrl?: string;
  isSuspended: boolean;
  organizations: { code: string; roles?: string; permissions?: string; }[];
  lastSyncedAt: number;
}

Supported webhook events

EventEffect
user.createdInserts user into Convex
user.updatedUpdates existing user
user.deletedRemoves user from Convex

Example app

See example/ for a working Vite + React demo showing live user sync from Kinde into Convex.

Development

npm i
npm run dev

License

Apache-2.0

Keywords