Skip to content

Conversation

@clairekinde11
Copy link
Contributor

@clairekinde11 clairekinde11 commented Sep 29, 2025

New topic about JWT decoding, referencing the Kinde utils we have to do this.
Needs review by @DanielRivers at minimum.

Summary by CodeRabbit

  • Documentation
    • New public guide on decoding and validating JSON Web Tokens (JWTs) with Kinde libraries.
    • Includes installation steps, basic and type-safe JavaScript/TypeScript examples, and manual decoding approaches for browser, Node, and universal environments.
    • Covers validation workflows, a security checklist, error-handling patterns, TypeScript interfaces, and practical use cases (displaying user info, feature flags, permissions).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 29, 2025

Walkthrough

Adds a new MDX documentation page at src/content/docs/build/tokens/decode-jwts.mdx that documents JWT structure, decoding vs. validation, Kinde decoder/validator usage, manual decoding patterns (Browser/Node/universal/TypeScript), validation checklist, error handling, use cases, and security best practices.

Changes

Cohort / File(s) Summary
Docs — JWT decoding/validation guide
src/content/docs/build/tokens/decode-jwts.mdx
New MDX page with front-matter metadata and comprehensive content covering JWT structure, decoding vs. validation, installation and usage of Kinde libraries (@kinde/jwt-decoder, @kinde/jwt-validator), basic and type-safe examples, manual decoding patterns for Browser/Node/universal, TypeScript interfaces, validation checklist, error handling patterns, practical use cases, and security considerations.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

  • Verify front-matter metadata (page_id, title, topics, languages, updated).
  • Quick pass for technical accuracy of code samples and security recommendations.
  • Check formatting and MDX rendering (links, code blocks, and JSX if present).

Poem

I nibble claims beneath the moon,
I parse the header, hum a tune.
With whiskered logic, tokens freed,
I hop through checks and plant a seed.
A rabbit’s guide — decode with speed. 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat: Guide - Decoding JSON Web Tokens' accurately describes the main change: a new documentation guide on JWT decoding. It is clear, concise, and directly related to the addition of the decode-jwts.mdx documentation page.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Feat/DecodeJWTs

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.

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: 2

🧹 Nitpick comments (8)
src/content/docs/build/tokens/decode-jwts.mdx (8)

30-30: Update the “updated” date to this PR’s timeline.

Current: 2024-01-15. Suggest 2025-09-29 for accuracy.

-updated: 2024-01-15
+updated: 2025-09-29

Please confirm the doc site’s date policy (authored vs updated).


114-125: Show explicit expected algorithms and domain/issuer guidance.

Add recommended options and a note to pin expected algs (e.g., RS256) and issuer.

-const validationResult = await validateToken({
-  token: "eyJhbGc...",
-  domain: "https://your-subdomain.kinde.com"
-});
+const validationResult = await validateToken({
+  token: "eyJhbGc...",
+  domain: "https://your-subdomain.kinde.com",
+  // Optional but recommended hardening:
+  expectedAlgs: ["RS256"],
+  expectedIssuer: "https://your-subdomain.kinde.com",
+});

I can add a short “why pin algorithms” callout if helpful.


166-191: Provide a complete TS implementation rather than a placeholder.

Avoid “Implementation same as above”; include the base64url helper and typed return.

-interface DecodedJWT {
+interface DecodedJWT {
   header: JWTHeader;
   payload: JWTPayload;
   signature: string;
 }
 
-function decodeJWT(token: string): DecodedJWT {
-  // Implementation same as above
-}
+const b64urlToString = (b64url: string): string => {
+  const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
+  const padded = b64 + '==='.slice((b64.length + 3) % 4);
+  // Browser vs Node
+  return typeof atob === 'function'
+    ? decodeURIComponent(escape(atob(padded)))
+    : Buffer.from(padded, 'base64').toString('utf8');
+};
+
+export function decodeJWT(token: string): DecodedJWT {
+  const parts = token.split('.');
+  if (parts.length !== 3) throw new Error('Invalid JWT format');
+  const header = JSON.parse(b64urlToString(parts[0])) as JWTHeader;
+  const payload = JSON.parse(b64urlToString(parts[1])) as JWTPayload;
+  return { header, payload, signature: parts[2] };
+}

197-201: Tighten the security bullets with explicit “don’t trust until validated.”

Clarify sequencing to prevent misinterpretation.

-**Decoding vs. Validation**: Decoding a JWT only extracts the payload - it doesn't verify the token's authenticity or integrity.
-**Always Validate**: After decoding, always validate the token using proper cryptographic verification.
+**Decoding vs. Validation**: Decoding only parses claims; it does not prove authenticity/integrity.
+**Always Validate**: Perform cryptographic validation (signature + claims) and only then trust any decoded data.

204-212: Expand the validation checklist (alg, kid/JWKS, nbf/leeway, issuer, audience).

Add commonly missed checks and adjust terminology.

-When validating JWTs, ensure you:
+When validating JWTs, ensure you:
 - Verify the token signature using the public key
 - Check the `iss` (issuer) claim matches your Kinde domain
 - Validate the `aud` (audience) claim
 - Verify the `exp` (expiration) claim
 - Check the `iat` (issued at) claim is reasonable
 - Validate any custom claims specific to your application
+- Enforce expected `alg` (e.g., RS256) and reject `none` or unexpected algorithms
+- Use `kid` to select the correct key from JWKS and cache JWKS with rotation in mind
+- Check `nbf` (not before) and allow small clock skew (e.g., ±60s leeway)
+- For OIDC ID tokens, also verify `nonce` when applicable

I can add a short JWKS caching callout if you want.


245-260: Harden feature‑flag access with nullish chaining and typing.

Avoid runtime errors when claims are absent.

-function checkFeatureFlag(token, flagName) {
+function checkFeatureFlag(token, flagName) {
   try {
     const decoded = jwtDecoder(token);
-    const featureFlags = decoded.payload.feature_flags;
-    
-    if (featureFlags && featureFlags[flagName]) {
-      return featureFlags[flagName].v; // 'v' is the value
-    }
-    
-    return false;
+    const v = decoded?.payload?.feature_flags?.[flagName]?.v;
+    return v ?? false;
   } catch (error) {
     console.error('Failed to check feature flag:', error);
     return false;
   }
 }

306-308: Rephrase “Validate Before Decoding.”

You must parse to validate; intent is “don’t trust decoded contents until validated.”

-**Validate Before Decoding**: Always validate the token's signature and claims before trusting the decoded payload.
+**Validate before trusting**: Parse, validate signature and claims, then trust the decoded payload.

68-75: Add explicit JWTDecoded import and tighten the decoded payload example

Import the exported JWTDecoded type and pass a concrete payload shape to jwtDecoder:

-import { jwtDecoder } from "@kinde/jwt-decoder";
+import { jwtDecoder, type JWTDecoded } from "@kinde/jwt-decoder";

Define a custom payload type and apply it:

-const decodedToken = jwtDecoder("eyJhbGc...");
+type MyClaims = JWTDecoded["payload"] & {
+  custom_claim?: string;
+  feature_flags?: Record<string, { v: unknown }>;
+};
+
+const decodedToken = jwtDecoder<MyClaims>("eyJhbGc...");

Apply the same pattern in the example at lines 79–90.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d88d65d and 94210b3.

📒 Files selected for processing (1)
  • src/content/docs/build/tokens/decode-jwts.mdx (1 hunks)
🔇 Additional comments (2)
src/content/docs/build/tokens/decode-jwts.mdx (2)

5-11: Inspect front-matter in decode-jwts.mdx
Please confirm presence and naming of sdk or sdks key in the front-matter once we have the file’s first lines.


112-112: Remove unused type import
jwtValidationResponse isn’t referenced in this file; drop it to avoid confusion.

-import { validateToken, type jwtValidationResponse } from "@kinde/jwt-validator";
+import { validateToken } from "@kinde/jwt-validator";

@tamalchowdhury tamalchowdhury changed the title New topic - Decode JWTs feat: Guide - Decoding JSON Web Tokens Nov 27, 2025
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: 1

🧹 Nitpick comments (1)
src/content/docs/build/tokens/decode-jwts.mdx (1)

304-304: Minor style: Replace "only" with more varied language.

To improve readability and flow, consider rephrasing "should only be used for display purposes" with an alternative structure.

Apply this diff for improved style:

-- **Never Trust Client-Side Decoding**: Client-side decoding should only be used for display purposes, not for security decisions.
+- **Never Trust Client-Side Decoding**: Client-side decoding is intended for display purposes only and must not be used for security decisions.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94210b3 and 9ff2fe2.

📒 Files selected for processing (1)
  • src/content/docs/build/tokens/decode-jwts.mdx (1 hunks)
🧰 Additional context used
🪛 LanguageTool
src/content/docs/build/tokens/decode-jwts.mdx

[style] ~304-~304: Consider replacing ‘only’ with a different word to let your writing stand out.
Context: ...Decoding**: Client-side decoding should only be used for display purposes, not for s...

(ONLY_EXCLUSIVELY_STYLE)

🔇 Additional comments (2)
src/content/docs/build/tokens/decode-jwts.mdx (2)

3-4: ✓ Terminology corrected from previous review feedback.

Title and keywords now properly use "Decoding and validating" terminology instead of "Decrypting," avoiding confusion between JWS (signed) and JWE (encrypted) tokens. This aligns with the previous review guidance.

Also applies to: 16-16, 24-24, 33-33


1-415: Documentation comprehensively covers JWT decoding patterns with strong security guidance.

The document provides:

  • Clear introduction distinguishing decoding from validation
  • Two production-ready Kinde library options (Decoder & Validator) with installation and usage examples
  • Three manual decoding implementations (browser, Node.js, universal) with proper error handling
  • TypeScript types and interfaces for type-safe implementations
  • Practical use cases (user info, feature flags, permissions extraction)
  • Security considerations and validation checklist
  • Error handling patterns and best practices

This is a solid foundation for developers learning JWT handling. The previous review's terminology and base64 decoding concerns have been substantially addressed.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 27, 2025

Deploying kinde-docs-preview with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7d07033
Status: ✅  Deploy successful!
Preview URL: https://5bca755c.kinde-docs-preview.pages.dev
Branch Preview URL: https://feat-decodejwts.kinde-docs-preview.pages.dev

View logs

@tamalchowdhury tamalchowdhury self-assigned this Nov 27, 2025
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: 0

🧹 Nitpick comments (1)
src/content/docs/build/tokens/decode-jwts.mdx (1)

311-311: Minor: Consider rewording to strengthen impact.

The phrase "should only be used for display purposes" is clear, but you can strengthen it by restructuring to emphasize the security principle: "Client-side decoding is suitable only for display; do not make security decisions based on client-side decoded payloads."

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ff2fe2 and c803483.

📒 Files selected for processing (1)
  • src/content/docs/build/tokens/decode-jwts.mdx (1 hunks)
🧰 Additional context used
🪛 LanguageTool
src/content/docs/build/tokens/decode-jwts.mdx

[style] ~311-~311: Consider replacing ‘only’ with a different word to let your writing stand out.
Context: ...Decoding**: Client-side decoding should only be used for display purposes, not for s...

(ONLY_EXCLUSIVELY_STYLE)

🔇 Additional comments (6)
src/content/docs/build/tokens/decode-jwts.mdx (6)

1-34: Front matter looks good.

Terminology has been correctly aligned to "decoding" and "validating" (not "decrypting"), and metadata is well-structured.


36-43: Clear introduction with appropriate emphasis on JWS.

The distinction between signed (JWS) and encrypted (JWE) tokens is clarified upfront, and the JWT structure explanation is well-presented.


44-121: Kinde libraries section is well-structured and practical.

Installation instructions and usage examples for both decoder and validator are clear and easy to follow.


262-279: Align TypeScript base64UrlDecode encoding to match cross-platform version.

The TypeScript implementation (line 273) uses .toString('binary') while the cross-platform version (line 230) uses .toString('utf-8'). For consistency and clarity, both should use 'utf-8', which is semantically correct since JWT payloads are UTF-8 encoded before base64url encoding.

Apply this diff to align with the cross-platform approach:

 function base64UrlDecode(str: string): string {
   // Replace Base64URL characters with Base64 characters
   let base64 = str.replace(/-/g, '+').replace(/_/g, '/');
   
   // Add padding if needed (Base64 strings must be multiples of 4)
   while (base64.length % 4) {
     base64 += '=';
   }
   
   // Use Buffer in Node.js, atob in browser
   if (typeof globalThis.Buffer !== 'undefined') {
-    return globalThis.Buffer.from(base64, 'base64').toString('binary');
+    return globalThis.Buffer.from(base64, 'base64').toString('utf-8');
   } else if (typeof globalThis.atob !== 'undefined') {
     return globalThis.atob(base64);
   } else {
     throw new Error('Neither Buffer nor atob is available in this environment');
   }
 }

305-324: Security section is comprehensive and appropriate.

The validation checklist, security notes, and emphasis on validation before trusting the payload are well-articulated and important.


388-422: Error handling and best practices sections are solid.

The examples demonstrate defensive programming, and the best practices provide clear, actionable guidance for developers.

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: 0

🧹 Nitpick comments (1)
src/content/docs/build/tokens/decode-jwts.mdx (1)

311-311: Minor style: Consider rewording to avoid "only."

Line 311 states "Client-side decoding should only be used for display purposes." Per style guidance, this could be rephrased as "Client-side decoding is suitable for display purposes" or "Client-side decoding should be limited to display purposes" for variety, but the current phrasing is clear and acceptable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c803483 and 7892c55.

📒 Files selected for processing (1)
  • src/content/docs/build/tokens/decode-jwts.mdx (1 hunks)
🧰 Additional context used
🪛 LanguageTool
src/content/docs/build/tokens/decode-jwts.mdx

[style] ~311-~311: Consider replacing ‘only’ with a different word to let your writing stand out.
Context: ...Decoding**: Client-side decoding should only be used for display purposes, not for s...

(ONLY_EXCLUSIVELY_STYLE)

🔇 Additional comments (6)
src/content/docs/build/tokens/decode-jwts.mdx (6)

1-34: Front matter and metadata look solid.

The documentation page is well-structured with comprehensive front matter, clear topic categorization, and appropriate audience/complexity settings. Content across the page correctly uses "decoding and validating" terminology and avoids earlier "decrypting" confusion.


44-121: Kinde library sections are clear and actionable.

Installation instructions, basic usage, and validation workflows are well-documented with type-safe examples. Examples correctly reference the Kinde packages (@kinde/jwt-decoder, @kinde/jwt-validator) and show both synchronous and async patterns.


132-235: Cross-platform manual decoding implementations are correct.

The browser (atob), Node.js (Buffer), and universal approaches all properly handle base64url padding and character replacement. The progression from environment-specific to universal is pedagogically sound for the audience.


262-279: TypeScript implementation properly handles cross-platform environments.

The function correctly checks for Buffer availability via globalThis and falls back to atob in browser contexts, with an error fallback for unexpected environments. Type annotations on interfaces and function parameters are accurate.


305-323: Security section appropriately emphasizes validation over decoding.

The distinction between "decoding vs. validation" is clearly stated, and the validation checklist covers signature, issuer, audience, expiration, and custom claims—all critical for production use.


325-414: Use cases and error handling patterns provide practical guidance.

Examples for displaying user info, feature flags, and permissions are realistic; error handling uses try-catch with graceful fallbacks. The safeDecodeJWT helper properly validates token structure before decoding.

@Arobce
Copy link
Contributor

Arobce commented Nov 27, 2025

@tamalchowdhury.

A few changes. I noticed the code is a bit outdated in some places.

image

Here, a normal JWT decoder would return.

// Output: { header: {...}, payload: {...}, signature: "..." }

But, Kinde's library just returns the payload. So, it would be best to get ride of that comment here.

image

For Validation and Decoding, the validation doesn't return a payload that can be used it just returns a { valid: true, message: 'Token is valid' }. So, the correct snipped would be:

import { validateToken } from "@kinde/jwt-validator";
import { jwtDecoder } from "@kinde/jwt-decoder";

const token = "ey..."; // your JWT here

const validateAndDecode = async () => {
  try {
    // Validate the token
    const result = await validateToken({
      token,
      domain: "https://your-subdomain.kinde.com",
    });

    if (result.valid) {
      console.log("Token is valid");

      // Decode after validation
      const decoded = jwtDecoder(token);
      console.log("Decoded payload:", decoded);
    } else {
      console.log("Token validation failed:", result.message);
    }

  } catch (error) {
    // The validator throws for JWKS or validation errors
    console.error("Token is invalid:", error);
  }
};

validateAndDecode();
  1. Under Common Usecases

The attributes shown their in the use cases aren't available by default. So, it would be better to make a note of that.

A message like "Just a heads-up: the example attributes aren’t part of the default setup. You will need to enable them from the Kinde dashboard." would be perfect.

i. Display user information

A separate payload object from jwtDecoder is not returned anymore. So, the correct implementation would be:

import { jwtDecoder } from "@kinde/jwt-decoder"

function displayUserInfo(token) {
  try {
    const payload = jwtDecoder(token);

    console.log(`User: ${payload.name || payload.email}`);
    console.log(`Organization: ${payload.org_code}`);
    console.log(`Permissions: ${payload.permissions?.join(', ')}`);

    return {
      name: payload.name,
      email: payload.email,
      organization: payload.org_code,
      permissions: payload.permissions || []
    }
  } catch (error) {
    console.error('Failed to decode token:', error);
    return null;
  }
}

ii. Checking Feature Flags

This is same as above.

import { jwtDecoder } from "@kinde/jwt-decoder"

function checkFeatureFlag(token, flagName) {
  try {
    const payload = jwtDecoder(token);

    const featureFlags = payload.feature_flags;

    if (featureFlags && featureFlags[flagName]) {
      return featureFlags[flagName].v;
    }

    return false;
  } catch (error) {
    console.error('Failed to check feature flag:', error);
    return false;
  }
}

iii. Extracting Permissions

Same as above.

import { jwtDecoder } from "@kinde/jwt-decoder"

export function getUserPermissions(token) {
  try {
    const payload = jwtDecoder(token)
    return payload.permissions || []
  } catch (error) {
    console.error('Failed to extract permissions:', error)
    return []
  }
}

Rest of it is perfect! Please, let me know if you need any help with this.

@tamalchowdhury
Copy link
Collaborator

Hi @Arobce thanks a lot for checking the code for accuracy. Would you be able to check the correctness of the 3 functions used for manual decoding?

@Arobce
Copy link
Contributor

Arobce commented Nov 27, 2025

@tamalchowdhury did that along with my other tests.

Its working perfectly.

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/build/tokens/decode-jwts.mdx (1)

402-420: Minor: Rephrase to avoid overuse of "only" (optional refactor).

Line 408 uses "only" in a way that can be strengthened for clarity. Consider:

-  - **Never Trust Client-Side Decoding**: Client-side decoding should only be used for display purposes, not for security decisions.
+  - **Never Trust Client-Side Decoding**: Use client-side decoding exclusively for display purposes; never rely on it for security decisions.

The security checklist and best practices sections are otherwise comprehensive and well-structured.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7892c55 and a976789.

📒 Files selected for processing (1)
  • src/content/docs/build/tokens/decode-jwts.mdx (1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.29.1)
src/content/docs/build/tokens/decode-jwts.mdx

[high] 69-69: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🪛 LanguageTool
src/content/docs/build/tokens/decode-jwts.mdx

[style] ~408-~408: Consider replacing ‘only’ with a different word to let your writing stand out.
Context: ...Decoding**: Client-side decoding should only be used for display purposes, not for s...

(ONLY_EXCLUSIVELY_STYLE)

🔇 Additional comments (5)
src/content/docs/build/tokens/decode-jwts.mdx (5)

1-42: Terminology and structure are correct.

Front matter and introduction properly use "decoding/validation" terminology and accurately describe JWT structure. Prior terminology feedback has been appropriately addressed.


44-90: jwtDecoder behavior correctly documented.

The example output (line 75) correctly shows the payload only, not header and signature. This accurately reflects Kinde's jwtDecoder implementation per the PR feedback.


92-141: Validation and decoding flow is correct.

The example properly separates concerns: validateToken returns { valid, message } (not payload), flow checks result.valid before calling jwtDecoder, and error handling wraps with try/catch. This implements the recommended pattern from PR feedback.


143-323: Manual decoding implementations are cross-platform and correct.

Browser, Node.js, universal, and TypeScript implementations all properly handle environment detection and base64url decoding with padding. TypeScript version correctly uses globalThis.Buffer with browser fallback. Prior feedback on cross-platform support has been addressed.


69-69: Gitleaks flag is expected for documentation examples.

The example JWT on line 69 is a standard token used to demonstrate jwtDecoder output in documentation. This is not a real secret or credential and does not represent a security risk in this context. The alert is a false positive for documentation examples.

@tamalchowdhury
Copy link
Collaborator

@Arobce would you be willing to have another look at the overall structure of this guide? thanks.

@Arobce
Copy link
Contributor

Arobce commented Dec 9, 2025

@tamalchowdhury I am on it.

Sorry for the late reply. I missed your mention.

@Arobce
Copy link
Contributor

Arobce commented Dec 9, 2025

@tamalchowdhury looks perfect!

Thanks for the edits.

@tamalchowdhury tamalchowdhury requested a review from a team as a code owner December 15, 2025 13:21
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: 0

🧹 Nitpick comments (1)
src/content/docs/build/tokens/decode-jwts.mdx (1)

436-436: Minor style suggestion: consider varying word choice for "only."

The phrase "Client-side decoding should only be used for display purposes" is clear and correct, but LanguageTool suggests varying the word "only" for stylistic diversity. This is entirely optional but could read as: "Client-side decoding should be used exclusively for display purposes" or "Client-side decoding is appropriate only for display purposes."

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a976789 and 7d07033.

📒 Files selected for processing (1)
  • src/content/docs/build/tokens/decode-jwts.mdx (1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.30.0)
src/content/docs/build/tokens/decode-jwts.mdx

[high] 69-69: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🪛 LanguageTool
src/content/docs/build/tokens/decode-jwts.mdx

[style] ~436-~436: Consider replacing ‘only’ with a different word to let your writing stand out.
Context: ...Decoding**: Client-side decoding should only be used for display purposes, not for s...

(ONLY_EXCLUSIVELY_STYLE)

🔇 Additional comments (10)
src/content/docs/build/tokens/decode-jwts.mdx (10)

1-34: Front matter and metadata look comprehensive.

The page metadata is well-structured with appropriate sidebar order, related articles, topics, and keywords. All required disclaimers about optional JWT claims (email, org_code, permissions, feature_flags) have been properly added throughout the document.


44-91: Excellent alignment with Kinde library documentation.

The jwtDecoder section correctly documents that it returns only the decoded payload (not header/signature). The example output at lines 72–75 accurately shows payload-only structure, and the type-safe decoding pattern is well-presented.


109-141: Validation and decoding flow is correct and properly addresses prior feedback.

The example correctly demonstrates:

  • Calling validateToken({ token, domain }) and awaiting the result
  • Checking result.valid before proceeding
  • Calling jwtDecoder(token) separately to obtain the payload
  • Wrapping the flow in try/catch for error handling

This matches the corrected pattern recommended in PR review feedback.


143-254: Manual decoding implementations are complete and cross-platform.

All three implementations (Browser, Node.js, Universal) are provided and appropriate:

  • Browser version (lines 152–162) uses atob() for browser environments
  • Node.js version (lines 198–208) uses Buffer with UTF-8 encoding
  • Universal version (lines 239–254) intelligently detects and uses the appropriate runtime API

The progression from simplest (browser-only) to most robust (universal) is pedagogically clear.


257-323: TypeScript implementation is robust with proper cross-platform and error handling.

The TypeScript version correctly:

  • Uses globalThis.Buffer and globalThis.atob for cross-runtime compatibility
  • Includes comprehensive error handling with explicit Error type checking
  • Defines clear interfaces (JWTHeader, JWTPayload, DecodedJWT)
  • Throws a descriptive error if neither Buffer nor atob is available

This matches and extends the universal pattern appropriately for a TypeScript context.


327-370: User information example correctly incorporates all corrected patterns and disclaimers.

The displayUserInfo() function:

  • Decodes using jwtDecoder(token)
  • Includes safe defaults (optional chaining, fallback values)
  • Returns structured object or null on error
  • Has disclaimers for email, org_code, and permissions requirements

All feedback from prior review has been addressed.


372-404: Feature flags example includes proper error handling and disclaimer.

The checkFeatureFlag() function correctly:

  • Decodes the payload
  • Checks for feature flag existence before accessing nested value
  • Returns false on missing flag or error
  • Includes disclaimer that feature_flags must be enabled in Kinde dashboard

406-429: Permissions example properly handles optional claim with fallback and disclaimer.

The getUserPermissions() function:

  • Decodes using jwtDecoder(token)
  • Returns payload.permissions || [] for safe fallback
  • Handles errors gracefully
  • Includes complete disclaimer about when permissions are included

430-485: Security, error handling, and best practices sections are well-written and complete.

Clear separation of validation vs. decoding, comprehensive validation checklist, robust error handling example, and actionable best practices. The "Use Kinde Libraries" guidance appropriately recommends production-ready approaches while documenting manual implementations for educational purposes.


69-69: Gitleaks warning about example JWT is a false positive.

The JWT token at line 69 (eyJhbGciOiJIUzI1NiIs...) is a well-known example token commonly used in JWT documentation and tests. It is not a real secret and poses no security risk. No action needed.

@onderay
Copy link
Member

onderay commented Dec 17, 2025

@tamalchowdhury please address the CR comments

@tamalchowdhury
Copy link
Collaborator

@onderay CR issue resolved earlier.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants