Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
310 changes: 310 additions & 0 deletions src/content/docs/build/tokens/decode-jwts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
---
page_id: 7a8b9c0d-1e2f-3456-7890-123456789abc
title: Decrypting JSON Web Tokens
description: Learn how to decrypt and decode JSON Web Tokens (JWTs) using Kinde's JWT libraries, including validation methods, security considerations, and practical implementation examples.
Comment on lines +3 to +4
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

Use “Decoding and validating” (not “Decrypting”) and align terms across page.

“Decrypting” implies JWE. Most Kinde tokens are signed JWS. To avoid security confusion, rename the title/sections/keywords and wording that suggest decryption, and keep a brief note about JWE as an edge case.

Apply this diff to front matter and section headings/phrasing shown in this file:

-title: Decrypting JSON Web Tokens
-description: Learn how to decrypt and decode JSON Web Tokens (JWTs) using Kinde's JWT libraries, including validation methods, security considerations, and practical implementation examples.
+title: Decoding and validating JSON Web Tokens
+description: Learn how to decode and validate JSON Web Tokens (JWTs) using Kinde’s libraries, with security considerations and practical examples.

 topics:
   - tokens
   - security
   - jwt
-  - decryption
+  - validation

 keywords:
-  - JWT decryption
+  - JWT decoding
   - token decoding
   - JWT validation
   - token security
   - JWT libraries
   - token parsing
-ai_summary: Comprehensive guide to decrypting and decoding JSON Web Tokens using Kinde's JWT libraries, including validation methods, security considerations, and practical implementation examples.
+ai_summary: Guide to decoding and validating JSON Web Tokens using Kinde’s libraries, with security considerations and practical examples.

And in body:

-Before decrypting a JWT, it's important to understand its structure.
+Before decoding a JWT, it's important to understand its structure.

-## Methods for Decrypting JWTs
+## Methods for decoding and validating JWTs

-When decrypting JWTs, ensure you:
+When validating JWTs, ensure you:

Optional JWE note near the intro:

+Note: If you actually receive encrypted JWTs (JWE), you must decrypt them before decoding/validation. Kinde issues signed JWTs (JWS) by default.

Also applies to: 12-16, 24-29, 46-46, 40-40, 204-204, 33-33

🤖 Prompt for AI Agents
In src/content/docs/build/tokens/decode-jwts.mdx around lines 3-4 (and also
ensure changes at 12-16, 24-29, 33-33, 40-40, 46-46, 204-204), replace the
front-matter title and any section headings or copy that use “Decrypting” with
“Decoding and validating” and update related keywords/description to reflect
decoding/validation of JWS (signed JWTs) rather than decryption; revise body
text to avoid implying JWE unless explicitly noting it, and add a brief
clarifying note near the introduction that JWE (encrypted JWTs) is an edge case
and requires different handling with a pointer to a dedicated page; ensure all
occurrences of “decrypt/decrypting/decryption” are changed to
“decode/decoding/decoding and validating” or equivalent context-appropriate
phrasing and update examples and headings accordingly.

sidebar:
order: 9
relatedArticles:
- 4ed081b0-7853-49be-b5fd-22a84a86bdad
- cf687bce-9732-4b67-9da5-580953c8549f
- d8069575-dfef-421d-8f3a-8f3efe9ad2f3
- c58b1c76-349a-40a1-a539-3b1da3ccb239
topics:
- tokens
- security
- jwt
- decryption
sdk: []
languages:
- javascript
- typescript
audience: developers
complexity: intermediate
keywords:
- JWT decryption
- token decoding
- JWT validation
- token security
- JWT libraries
- token parsing
updated: 2024-01-15
featured: false
deprecated: false
ai_summary: Comprehensive guide to decrypting and decoding JSON Web Tokens using Kinde's JWT libraries, including validation methods, security considerations, and practical implementation examples.
---

JWT decryption involves parsing and validating JSON Web Tokens to extract their payload information securely. While JWTs are typically signed (not encrypted), the term "decryption" in this context refers to the process of decoding and validating the token structure and claims.

## Understanding JWT Structure

Before decrypting a JWT, it's important to understand its structure. A JWT consists of three parts separated by dots (`.`):

1. **Header** - Contains metadata about the token (algorithm, type)
2. **Payload** - Contains the claims (user data, permissions, etc.)
3. **Signature** - Used to verify the token's authenticity

## Methods for Decrypting JWTs

### Using Kinde JWT Decoder

The [@kinde/jwt-decoder](https://github.com/kinde-oss/jwt-decoder) library provides a simple, type-safe way to decode JWT tokens:

#### Installation

```bash
# npm
npm install @kinde/jwt-decoder

# yarn
yarn add @kinde/jwt-decoder

# pnpm
pnpm install @kinde/jwt-decoder
```

#### Basic Usage

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

// Simple decode
const decodedToken = jwtDecoder("eyJhbGc...");

console.log(decodedToken);
// Output: { header: {...}, payload: {...}, signature: "..." }
```

#### Type-Safe Decoding

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

// Decode with extended type
const decodedToken = jwtDecoder<
JWTDecoded & {
// Extra attributes here
custom_claim?: string;
feature_flags?: Record<string, any>;
}
>("eyJhbGc...");
```

### Using Kinde JWT Validator

The [@kinde/jwt-validator](https://github.com/kinde-oss/jwt-validator) library provides comprehensive JWT validation with support for mobile and edge environments:

#### Installation

```bash
# npm
npm install @kinde/jwt-validator

# yarn
yarn add @kinde/jwt-validator

# pnpm
pnpm install @kinde/jwt-validator
```

#### Validation and Decoding

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

const validationResult = await validateToken({
token: "eyJhbGc...",
domain: "https://your-subdomain.kinde.com"
});

if (validationResult.isValid) {
console.log("Token is valid");
console.log("Decoded payload:", validationResult.payload);
} else {
console.log("Token validation failed:", validationResult.error);
}
```

## Manual JWT Decoding

If you need to decode JWTs without using Kinde's libraries, you can implement manual decoding:

### Base64 URL Decoding

```javascript
function decodeJWT(token) {
try {
// Split the token into its three parts
const parts = token.split('.');

if (parts.length !== 3) {
throw new Error('Invalid JWT format');
}

// Decode header and payload (base64url)
const header = JSON.parse(atob(parts[0].replace(/-/g, '+').replace(/_/g, '/')));
const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));

return {
header,
payload,
signature: parts[2]
};
} catch (error) {
throw new Error('Failed to decode JWT: ' + error.message);
}
}
Comment on lines +134 to +155
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

Base64url decoding needs padding and Node support; current snippet breaks outside browsers and with unicode.

atob isn’t available in Node and base64url often needs '=' padding. Provide a cross‑runtime helper.

-function decodeJWT(token) {
+function b64urlToString(b64url) {
+  const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
+  const padded = b64 + '==='.slice((b64.length + 3) % 4);
+  if (typeof atob === 'function') {
+    // Browser
+    return decodeURIComponent(escape(atob(padded)));
+  }
+  // Node
+  return Buffer.from(padded, 'base64').toString('utf8');
+}
+
+function decodeJWT(token) {
   try {
     // Split the token into its three parts
     const parts = token.split('.');
     
     if (parts.length !== 3) {
       throw new Error('Invalid JWT format');
     }
     
     // Decode header and payload (base64url)
-    const header = JSON.parse(atob(parts[0].replace(/-/g, '+').replace(/_/g, '/')));
-    const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
+    const header = JSON.parse(b64urlToString(parts[0]));
+    const payload = JSON.parse(b64urlToString(parts[1]));
     
     return {
       header,
       payload,
       signature: parts[2]
     };
   } catch (error) {
     throw new Error('Failed to decode JWT: ' + error.message);
   }
 }
📝 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
function decodeJWT(token) {
try {
// Split the token into its three parts
const parts = token.split('.');
if (parts.length !== 3) {
throw new Error('Invalid JWT format');
}
// Decode header and payload (base64url)
const header = JSON.parse(atob(parts[0].replace(/-/g, '+').replace(/_/g, '/')));
const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
return {
header,
payload,
signature: parts[2]
};
} catch (error) {
throw new Error('Failed to decode JWT: ' + error.message);
}
}
function b64urlToString(b64url) {
const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
const padded = b64 + '==='.slice((b64.length + 3) % 4);
if (typeof atob === 'function') {
// Browser
return decodeURIComponent(escape(atob(padded)));
}
// Node
return Buffer.from(padded, 'base64').toString('utf8');
}
function decodeJWT(token) {
try {
// Split the token into its three parts
const parts = token.split('.');
if (parts.length !== 3) {
throw new Error('Invalid JWT format');
}
// Decode header and payload (base64url)
const header = JSON.parse(b64urlToString(parts[0]));
const payload = JSON.parse(b64urlToString(parts[1]));
return {
header,
payload,
signature: parts[2]
};
} catch (error) {
throw new Error('Failed to decode JWT: ' + error.message);
}
}
🤖 Prompt for AI Agents
In src/content/docs/build/tokens/decode-jwts.mdx around lines 134 to 155, the
snippet uses atob and raw base64url decoding which fails in Node and for UTF-8
content; replace the inline atob usage with a small cross-runtime base64url
decode helper that (1) converts base64url chars to base64, (2) adds required '='
padding, (3) decodes using Buffer.from(..., 'base64') when
Buffer/globalThis.Buffer exists or falls back to globalThis.atob in browsers,
and (4) handles UTF-8 by percent-decoding the binary string to a Unicode string
before JSON.parse; then call this helper for both header and payload and surface
the original error message on failure.


// Usage
const token = "eyJhbGc...";
const decoded = decodeJWT(token);
console.log(decoded.payload);
```

### TypeScript Implementation

```typescript
interface JWTHeader {
alg: string;
typ: string;
kid?: string;
}

interface JWTPayload {
iss: string;
sub: string;
aud: string | string[];
exp: number;
iat: number;
jti?: string;
[key: string]: any;
}

interface DecodedJWT {
header: JWTHeader;
payload: JWTPayload;
signature: string;
}

function decodeJWT(token: string): DecodedJWT {
// Implementation same as above
}
```

## Security Considerations

### Important Security Notes

- **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.
- **Never Trust Client-Side Decoding**: Client-side decoding should only be used for display purposes, not for security decisions.
- **Check Expiration**: Always verify the `exp` claim to ensure the token hasn't expired.

### Validation Checklist

When decrypting 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

## Common Use Cases

### Displaying User Information

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

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

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;
}
}
```

### Checking Feature Flags

```javascript
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;
} catch (error) {
console.error('Failed to check feature flag:', error);
return false;
}
}
```

### Extracting Permissions

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

## Error Handling

### Common Decoding Errors

```javascript
function safeDecodeJWT(token) {
try {
if (!token) {
throw new Error('Token is required');
}

if (typeof token !== 'string') {
throw new Error('Token must be a string');
}

const parts = token.split('.');
if (parts.length !== 3) {
throw new Error('Invalid JWT format - must have 3 parts');
}

return jwtDecoder(token);
} catch (error) {
console.error('JWT decoding error:', error.message);
return null;
}
}
```

## Best Practices

- **Use Kinde Libraries**: Prefer Kinde's JWT libraries for production applications as they handle edge cases and provide type safety.
- **Validate Before Decoding**: Always validate the token's signature and claims before trusting the decoded payload.
- **Handle Errors Gracefully**: Implement proper error handling for malformed or invalid tokens.
- **Log Security Events**: Log failed decoding attempts for security monitoring.
- **Keep Libraries Updated**: Regularly update JWT libraries to get security patches and improvements.