Skip to content

fix: update Kinde and Convex guide for better integration#669

Open
tamalchowdhury wants to merge 7 commits intomainfrom
tamal/update/convex-auth-update
Open

fix: update Kinde and Convex guide for better integration#669
tamalchowdhury wants to merge 7 commits intomainfrom
tamal/update/convex-auth-update

Conversation

@tamalchowdhury
Copy link
Collaborator

@tamalchowdhury tamalchowdhury commented Feb 22, 2026

Description (required)

Restructured the guide for complete integration. Removed dependency from 3rd party adapter. Add clarity to user sync and add advance sync using Kinde webhooks.

Related issues & labels (optional)

  • Closes #
  • Suggested label:

Summary by CodeRabbit

Release Notes

  • Documentation
    • Added comprehensive Kinde + Convex integration guide with quickstart and step-by-step setup instructions.
    • Included real-time messaging example demonstrating live data synchronization.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 22, 2026

Walkthrough

The Kinde + Convex integration documentation is significantly expanded from a brief overview to a comprehensive step-by-step tutorial, including project setup, OAuth authentication wiring, Convex backend schemas with webhook syncing, and a real-time message board example with styling. The guide now provides end-to-end code examples and implementation patterns.

Changes

Cohort / File(s) Summary
Integration Tutorial Documentation
src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx
Major documentation rework adding Quickstart section, project setup instructions, React + Vite scaffolding, and Kinde app configuration. Updated metadata with table of contents and current timestamp.
Authentication Integration
src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx (auth section)
Added useAuthFromKinde hook for token retrieval, auth.config.ts for Convex Kinde provider setup, and KindeProvider + ConvexProviderWithAuth component composition examples.
Backend Data Models & Sync
src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx (backend section)
Introduced convex/schema.ts with users table and by_kinde_id index, convex/users.ts with upsert mutation, and App.tsx integration for syncing user data on sign-in.
Webhook Handling
src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx (webhook section)
Added webhook.ts for handling Kinde events (user.updated, user.deleted), http.ts routing for /kinde-users-webhook endpoint, and HTTP action implementation for event processing.
Real-time UI & Styling
src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx (messages section)
Added convex/messages.ts with list query and sendMessage mutation, MessageBoard.tsx component, App.tsx message board integration, and App.css with layout, message board, and Kinde UI token styling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 With Kinde's keys and Convex's might,
Auth flows swift through webhook's night,
Users sync, real-time chats do bloom,
Documentation lights the room!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: updating the Kinde and Convex integration guide with restructured instructions, webhook-based sync, and improved clarity.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch tamal/update/convex-auth-update

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tamalchowdhury tamalchowdhury changed the title fix: update Kinde and Convex guide for better implementation fix: update Kinde and Convex guide for better integration Feb 22, 2026
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Feb 22, 2026

Deploying kinde-docs-preview with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8555a00
Status: ✅  Deploy successful!
Preview URL: https://c7fdc4f7.kinde-docs-preview.pages.dev
Branch Preview URL: https://tamal-update-convex-auth-upd.kinde-docs-preview.pages.dev

View logs

@tamalchowdhury tamalchowdhury marked this pull request as ready for review February 26, 2026 19:04
@tamalchowdhury tamalchowdhury requested a review from a team as a code owner February 26, 2026 19:04
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx (1)

423-425: Consider adding an explicit KINDE_DOMAIN guard in the webhook code example for clarity.

Line 423 in the webhook handler calls decodeWebhook(jwt, process.env.KINDE_DOMAIN) without first validating that the environment variable is set. While the guide documents setting KINDE_DOMAIN as a prerequisite step, adding an explicit guard would make the example more robust and educate developers on handling missing environment variables:

Suggested documentation improvement
-        const decoded = await decodeWebhook(jwt, process.env.KINDE_DOMAIN); // https://<your_kinde_business>.kinde.com
+        const kindeDomain = process.env.KINDE_DOMAIN;
+        if (!kindeDomain) {
+          return new Response("Server misconfiguration: KINDE_DOMAIN is not set", { status: 500 });
+        }
+        const decoded = await decodeWebhook(jwt, kindeDomain); // https://<your_kinde_business>.kinde.com
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx` around
lines 423 - 425, Add an explicit guard that validates process.env.KINDE_DOMAIN
before calling decodeWebhook(jwt, process.env.KINDE_DOMAIN): check that the
environment variable is present and non-empty (e.g., in the webhook handler
function where jwt is used), and if missing return an early Response with an
appropriate error status and message (so the call to decodeWebhook is never made
with an undefined domain); reference the decodeWebhook call, the jwt variable,
and process.env.KINDE_DOMAIN when adding this conditional check and early
return.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx`:
- Around line 296-306: The one-time upsert guard incorrectly sets
hasUpserted.current = true before storeUser completes and never resets on
sign-out; update the useEffect that references hasUpserted, isAuthenticated,
user, and storeUser so that: (1) when !isAuthenticated || !user you reset
hasUpserted.current = false, and (2) only set hasUpserted.current = true after
the Promise returned by storeUser resolves successfully (handle errors without
flipping the flag). This ensures retries on failure and re-syncs after a new
sign-in.
- Around line 54-58: The quickstart step currently installs only "convex" but
the guide later imports "@kinde-oss/kinde-auth-react" (seen in imports like
`@kinde-oss/kinde-auth-react`), causing module-not-found errors; update the
install instruction (the step that runs npm install convex) to also install
"@kinde-oss/kinde-auth-react" (e.g., npm install convex
`@kinde-oss/kinde-auth-react`) so fresh setups have both dependencies available.
- Around line 138-139: The auth flow in useAuthFromKinde() is using
getAccessToken() but Convex custom auth requires the ID token; update
useAuthFromKinde() to call getIdToken() instead of getAccessToken(), pass that
ID token where the Convex auth payload is constructed (the value used for
applicationID/aud checks), and ensure any variable names or comments reflect
that this token is the ID token used for identity/authentication.

---

Nitpick comments:
In `@src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx`:
- Around line 423-425: Add an explicit guard that validates
process.env.KINDE_DOMAIN before calling decodeWebhook(jwt,
process.env.KINDE_DOMAIN): check that the environment variable is present and
non-empty (e.g., in the webhook handler function where jwt is used), and if
missing return an early Response with an appropriate error status and message
(so the call to decodeWebhook is never made with an undefined domain); reference
the decodeWebhook call, the jwt variable, and process.env.KINDE_DOMAIN when
adding this conditional check and early return.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa98d8f and 8555a00.

📒 Files selected for processing (1)
  • src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx

Comment on lines +54 to +58
4. Install the Convex dependencies:

![kinde callback urls](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/d5d0489d-019f-488d-ecaa-b08f4d2e5800/public)
```bash
npm install convex
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the file to see the actual content at the specified lines
cat -n src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx | sed -n '50,80p'

Repository: kinde-oss/documentation

Length of output: 1414


🏁 Script executed:

# Check all import statements and npm install commands in the file
rg -n 'npm install|import.*kinde|from.*kinde' src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx

Repository: kinde-oss/documentation

Length of output: 763


🏁 Script executed:

# Let's also check what Kinde packages are documented elsewhere in the repo
fd -e mdx -e md | head -20 | xargs rg -h 'npm install.*kinde|@kinde-oss|kinde/' | sort | uniq

Repository: kinde-oss/documentation

Length of output: 9342


🏁 Script executed:

# Check all npm install commands in the repo to see package naming patterns
rg -n 'npm install.*kinde' src/content/docs --type mdx -A 2 -B 2 | head -100

Repository: kinde-oss/documentation

Length of output: 94


🏁 Script executed:

# Look for package.json files or NPM registry info about kinde packages
find . -name "package.json" -type f | head -5 | xargs cat 2>/dev/null | grep -A 5 -B 5 'kinde' | head -50

Repository: kinde-oss/documentation

Length of output: 49


🏁 Script executed:

# Search for references to the auth react package across the docs
rg '@kinde.*auth.*react|kinde.*auth.*react' src/content/docs --type mdx | cut -d: -f2 | sort | uniq

Repository: kinde-oss/documentation

Length of output: 94


🏁 Script executed:

# Check all npm install commands mentioning kinde across docs
rg 'npm install.*kinde' src/content/docs -A 2 -B 2

Repository: kinde-oss/documentation

Length of output: 1814


🏁 Script executed:

# Search all mdx files for kinde package references to see patterns
rg '@kinde' src/content/docs

Repository: kinde-oss/documentation

Length of output: 50379


🏁 Script executed:

# Look at other integration guides to see what packages they recommend
fd '\.mdx$' src/content/docs/integrate | head -10 | xargs rg 'npm install' -A 1

Repository: kinde-oss/documentation

Length of output: 406


Quickstart is missing required dependency install.

Line 57 installs only convex, but lines 74, 106, and 158 import @kinde-oss/kinde-auth-react. Fresh setups will fail with module not found errors.

🔧 Proposed fix
-    npm install convex
+    npm install convex `@kinde-oss/kinde-auth-react`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
4. Install the Convex dependencies:
![kinde callback urls](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/d5d0489d-019f-488d-ecaa-b08f4d2e5800/public)
```bash
npm install convex
```
4. Install the Convex dependencies:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx` around
lines 54 - 58, The quickstart step currently installs only "convex" but the
guide later imports "@kinde-oss/kinde-auth-react" (seen in imports like
`@kinde-oss/kinde-auth-react`), causing module-not-found errors; update the
install instruction (the step that runs npm install convex) to also install
"@kinde-oss/kinde-auth-react" (e.g., npm install convex
`@kinde-oss/kinde-auth-react`) so fresh setups have both dependencies available.

Comment on lines +138 to +139
// domain must match the ID token's "iss"; applicationID must match the ID token's "aud".
// Decode your ID token at jwt.io to confirm (use getIdToken() and paste the string).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx | sed -n '100,150p'

Repository: kinde-oss/documentation

Length of output: 1941


🌐 Web query:

Convex custom auth config applicationID JWT audience claim

💡 Result:

In Convex Custom JWT auth, applicationID in convex/auth.config.ts is the value Convex expects to see in the JWT’s aud (audience) claim:

  • If you set applicationID, Convex will verify jwt.aud === applicationID (exact match). [1]
  • If you omit applicationID, Convex does not validate aud, which Convex warns is often insecure (a token minted for another app/service could be replayed against yours). [1]

Example:

export default {
  providers: [
    {
      type: "customJwt",
      applicationID: "your-application-id", // must match JWT `aud`
      issuer: "https://your.issuer.url.com", // must match JWT `iss`
      jwks: "https://your.issuer.url.com/.well-known/jwks.json",
      algorithm: "RS256",
    },
  ],
};

Source: Convex “Custom JWT Provider” docs. [1]


🌐 Web query:

Kinde getAccessToken vs getIdToken Convex integration

💡 Result:

For a Convex auth integration, you almost always want Kinde’s ID token, not the access token.

  • getIdToken (OIDC ID token): Proves who the user is (identity). Convex authentication is based on OpenID Connect ID tokens (JWTs). Use this token as the value you pass to Convex (e.g., via ConvexProviderWithAuth / client.setAuth(...)). [1][2]
  • getAccessToken (OAuth access token): Proves what the user can access (authorization) for a specific API/resource (often a different aud). It’s meant to be sent to your APIs, not used as your app’s “who is logged in” token. [3][4]

Rule of thumb:

  • If the token is for Convex user auth → use getIdToken. [1]
  • If the token is for calling your backend/API → use getAccessToken. [3]

If you really want to authenticate Convex using an access token, you must ensure its JWT claims match what Convex validates (notably iss, sub, exp, plus aud/applicationID, and iat for refresh behavior) and configure Convex accordingly (OIDC provider or custom JWT provider). [2]

Sources:
[1] Convex Authentication overview (OIDC ID tokens as JWTs) — https://docs.convex.dev/auth
[2] Convex Custom JWT provider requirements (sub,iss,exp,iat,aud) — https://docs.convex.dev/auth/advanced/custom-jwt
[3] Kinde: About access tokens — https://docs.kinde.com/build/tokens/about-access-tokens/
[4] Kinde: About ID tokens — https://docs.kinde.com/build/tokens/about-id-tokens/


The code at lines 110-115 should use getIdToken() instead of getAccessToken() for Convex authentication.

The comments at lines 138-139 are correct: Convex custom auth validates the ID token's aud claim against applicationID. However, the code uses getAccessToken(), which provides a different token with different claims. For Convex user authentication, the ID token must be used. The getAccessToken() method is for API authorization, not identity authentication.

Update useAuthFromKinde() to call getIdToken() instead of getAccessToken().

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx` around
lines 138 - 139, The auth flow in useAuthFromKinde() is using getAccessToken()
but Convex custom auth requires the ID token; update useAuthFromKinde() to call
getIdToken() instead of getAccessToken(), pass that ID token where the Convex
auth payload is constructed (the value used for applicationID/aud checks), and
ensure any variable names or comments reflect that this token is the ID token
used for identity/authentication.

Comment on lines +296 to +306
const hasUpserted = useRef(false);

useEffect(() => {
if (!isAuthenticated || !user || hasUpserted.current) return;
hasUpserted.current = true;
storeUser({
givenName: user.givenName,
familyName: user.familyName,
email: user.email,
}).catch(console.error);
}, [isAuthenticated, user, storeUser]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx | sed -n '290,310p'

Repository: kinde-oss/documentation

Length of output: 888


The one-time upsert guard prevents retries and blocks user syncs across sessions.

Line 300 sets hasUpserted.current = true before storeUser completes, blocking retries if the call fails. More critically, the flag is never reset on sign-out—when the user signs back in, hasUpserted.current remains true from the previous session, causing the new login to skip the upsert entirely.

The proposed fix correctly addresses both issues by resetting the flag when the user is not authenticated or present, and setting it only after storeUser succeeds.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/docs/integrate/third-party-tools/kinde-and-convex.mdx` around
lines 296 - 306, The one-time upsert guard incorrectly sets hasUpserted.current
= true before storeUser completes and never resets on sign-out; update the
useEffect that references hasUpserted, isAuthenticated, user, and storeUser so
that: (1) when !isAuthenticated || !user you reset hasUpserted.current = false,
and (2) only set hasUpserted.current = true after the Promise returned by
storeUser resolves successfully (handle errors without flipping the flag). This
ensures retries on failure and re-syncs after a new sign-in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant