メインコンテンツまでスキップ

Node.js JWT Validation Example

⚠️ Important Notice: This is a basic example for demonstration purposes only. For production use, please research and implement best practices specific to your software stack, security requirements, and deployment environment. Always follow your organization's security guidelines and consider using established JWT libraries and frameworks.

📝 Note: This example demonstrates JWKS downloading and file caching for educational purposes. In production environments, you may choose to implement JWKS key management differently based on your infrastructure - such as using configuration management, environment variables, or your preferred caching strategy.

This example demonstrates how to validate Rokt JWT tokens using Node.js.

Prerequisites

Install the required packages:

npm install jose jsonwebtoken

Complete Example

const { jwtVerify, importJWK } = require('jose');
const jwt = require('jsonwebtoken');

// Sample JWT token from Rokt
// Copy the test token from the Overview page
const SAMPLE_JWT_TOKEN = "PASTE_TEST_TOKEN_HERE";

// JWKS endpoint URL
const JWKS_URL = "https://public-api.rokt.com/.well-known/jwks.json";
const JWKS_CACHE_FILE = "jwks_cache.json";

/**
* Validate JWT token using jose library (recommended)
*/
async function validateReferralTokenJose(jwtToken, jwksJson) {
try {
// Parse JWKS
const jwks = typeof jwksJson === 'string' ? JSON.parse(jwksJson) : jwksJson;

if (!jwks.keys || jwks.keys.length === 0) {
throw new Error('No keys found in JWKS');
}

// Get the first key
const jwk = jwks.keys[0];

// Import JWK to create public key
const publicKey = await importJWK(jwk, 'ES256');

// Verify and decode JWT token
const { payload } = await jwtVerify(jwtToken, publicKey, {
algorithms: ['ES256'],
clockTolerance: 999999999 // Disable expiration check for demo - using sample token
});

return {
isValid: true,
campaignID: payload.cid,
creativeID: payload.crid,
rclid: payload.rclid,
issuedAt: new Date(payload.iat * 1000)
};
} catch (error) {
return {
isValid: false,
error: error.message
};
}
}

/**
* Alternative implementation using jsonwebtoken library
*/
function validateReferralTokenJWT(jwtToken, jwksJson) {
try {
// Parse JWKS
const jwks = typeof jwksJson === 'string' ? JSON.parse(jwksJson) : jwksJson;

if (!jwks.keys || jwks.keys.length === 0) {
throw new Error('No keys found in JWKS');
}

// Get the first key
const jwk = jwks.keys[0];

// For jsonwebtoken, you would need to convert JWK to PEM format
// This is a simplified example - in practice, you'd need proper JWK to PEM conversion
const publicKeyPem = `-----BEGIN PUBLIC KEY-----
YOUR_PUBLIC_KEY_PEM_HERE
-----END PUBLIC KEY-----`;

// Verify and decode JWT token
const decoded = jwt.verify(jwtToken, publicKeyPem, {
algorithms: ['ES256']
});

return {
isValid: true,
campaignID: decoded.cid,
creativeID: decoded.crid,
rclid: decoded.rclid,
issuedAt: new Date(decoded.iat * 1000)
};
} catch (error) {
return {
isValid: false,
error: error.message
};
}
}

/**
* Main function to demonstrate token validation
*/
async function downloadAndCacheJWKS(jwksUrl, cacheFile) {
const fs = require('fs');
const path = require('path');

// Check if cache file exists and is recent (less than 1 hour old)
if (fs.existsSync(cacheFile)) {
const stats = fs.statSync(cacheFile);
const fileAge = Date.now() - stats.mtime.getTime();
if (fileAge < 3600000) { // 1 hour in milliseconds
console.log(`Using cached JWKS from: ${cacheFile}`);
return fs.readFileSync(cacheFile, 'utf8');
}
}

// Download JWKS
console.log(`Downloading JWKS from: ${jwksUrl}`);
const response = await fetch(jwksUrl);
if (!response.ok) {
throw new Error(`Failed to download JWKS: HTTP ${response.status}`);
}

const jwksJson = await response.text();

// Cache the JWKS
fs.writeFileSync(cacheFile, jwksJson);
console.log(`JWKS cached to: ${cacheFile}`);

return jwksJson;
}

async function main() {
console.log('=== Node.js JWT Validator ===');
console.log(`Token: ${SAMPLE_JWT_TOKEN.substring(0, 50)}...`);
console.log(`JWKS URL: ${JWKS_URL}`);
console.log('');

try {
// Download and cache JWKS
const jwksJson = await downloadAndCacheJWKS(JWKS_URL, JWKS_CACHE_FILE);
console.log("JWKS downloaded and cached successfully");

// Parse JWKS and extract key coordinates
const jwks = JSON.parse(jwksJson);
if (!jwks.keys || jwks.keys.length === 0) {
throw new Error("No keys found in JWKS");
}

const key = jwks.keys[0];

// Validate using jose library (recommended)
console.log('Using jose library:');
const resultJose = await validateReferralTokenJose(SAMPLE_JWT_TOKEN, jwksJson);

if (resultJose.isValid) {
console.log('✅ Token validation successful!');
console.log(`Campaign ID: ${resultJose.campaignID}`);
console.log(`Creative ID: ${resultJose.creativeID}`);
console.log(`RCLID: ${resultJose.rclid}`);
console.log(`Issued At: ${resultJose.issuedAt.toISOString()}`);
} else {
console.error(`❌ Token validation failed: ${resultJose.error}`);
}

console.log('');

// Show alternative method
console.log('Alternative method using jsonwebtoken:');
console.log('Note: Requires proper JWK to PEM conversion');
const resultJWT = validateReferralTokenJWT(SAMPLE_JWT_TOKEN, jwksJson);
console.log(`Result: ${resultJWT.isValid ? 'Valid' : 'Invalid'}`);
} catch (error) {
console.error(`❌ Error: ${error.message}`);
}
}

// Export functions for use in other modules
module.exports = {
validateReferralTokenJose,
validateReferralTokenJWT
};

// Run example if this file is executed directly
if (require.main === module) {
main().catch(console.error);
}

Input/Output Example

Input

  • JWT Token: Copy the test token from the Overview page
  • Public Key Source: https://public-api.rokt.com/.well-known/jwks.json

Output

=== Node.js JWT Validator ===
Token: eyJhbGciOiJFUzI1NiIsImtpZCI6InJva3Qtc2lnbmluZy1rZXkiLCJ0eXAiOiJKV1QifQ...
JWKS URL: https://public-api.rokt.com/.well-known/jwks.json

Downloading JWKS from: https://public-api.rokt.com/.well-known/jwks.json
JWKS cached to: jwks_cache.json
JWKS downloaded and cached successfully

Using jose library:
✅ Token validation successful!
Campaign ID: 3436085368692408324
Creative ID: 3437732754935906308
RCLID: 7db958dbd232247a4a8285a34d22fe0f4e9affa463bf5ee54e26721ab0df0e23
Issued At: 2025-08-20T05:10:01.000Z

Alternative method using jsonwebtoken:
Note: Requires proper JWK to PEM conversion
Result: Invalid

How to Run

  1. Save the code to rokt_jwt_validator.js
  2. Install dependencies: npm install jose jsonwebtoken
  3. Run: node rokt_jwt_validator.js

Alternative Implementation with ES Modules

If you prefer ES modules, you can use this syntax:

import { jwtVerify, importJWK } from 'jose';

// ... rest of the code remains the same

Notes

  • The jose library is recommended for modern Node.js applications

  • The public key is retrieved from Rokt's JWKS endpoint

  • The example uses ECDSA-256 (ES256) algorithm for signature verification

  • Consider caching the public key for performance

  • The jose library handles JWK to public key conversion automatically

この記事は役に立ちましたか?