JS
S
JavaScriptThe Identity Provider (IdP): This entity is responsible for authenticating a user and then "issuing" a signed JWT. It holds the private key. The Service Provider (SP): This is our simulated service. It needs to verify incoming JWTs to grant access. It holds the corresponding public key. Prepare the project (Node.js): ```sh mkdir jwt-simulation cd jwt-simulation npm init -y npm install jsonwebtoken ```
1// simulateAuth.js
2// =====================
3// Import necessary libraries
4const jwt = require('jsonwebtoken');
5const crypto = require('crypto');
6
7// --- 1. KEY GENERATION ---
8// In a real-world application, you would generate this key pair once and store it securely.
9// The private key must be kept secret by the Identity Provider.
10// The public key is shared with the Service Provider (e.g., uploaded to AWS OpenSearch).
11console.log('🔑 Generating RSA Public/Private Key Pair...');
12const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
13 modulusLength: 2048, // Standard, secure length
14 publicKeyEncoding: {
15 type: 'spki', // Standard for public keys
16 format: 'pem'
17 },
18 privateKeyEncoding: {
19 type: 'pkcs8', // Standard for private keys
20 format: 'pem'
21 }
22});
23
24console.log('✅ Key pair generated successfully.\n');
25// You can uncomment the lines below to see what the keys look like.
26// console.log('--- Public Key ---');
27// console.log(publicKey);
28// console.log('--- Private Key ---');
29// console.log(privateKey);
30
31
32// --- 2. IDENTITY PROVIDER (IdP) SIMULATION ---
33// This function simulates the IdP creating and signing a JWT for an authenticated user.
34function issueJwtForUser(userId, roles) {
35 console.log(`\n--- Identity Provider (IdP) ---`);
36 console.log(`👤 Authenticated user: ${userId}`);
37 console.log(`📜 User roles: ${roles.join(', ')}`);
38
39 // The payload contains the "claims" about the user.
40 // 'sub' (subject) is a standard claim for the user's ID.
41 // 'exp' (expiration time) is a crucial security feature.
42 const payload = {
43 sub: userId,
44 roles: roles, // Custom claim for our application
45 iss: 'MyAwesomeIdP' // 'iss' (issuer) claim
46 };
47
48 // Sign the token using the private key.
49 // We specify the RS256 algorithm, which corresponds to RSA signing.
50 const signOptions = {
51 algorithm: 'RS256',
52 expiresIn: '1h' // Token will be valid for 1 hour
53 };
54
55 console.log('✍️ Signing a new JWT with the PRIVATE key...');
56 const token = jwt.sign(payload, privateKey, signOptions);
57
58 console.log('✅ JWT issued successfully.');
59 return token;
60}
61
62
63// --- 3. SERVICE PROVIDER (SP) SIMULATION ---
64// This function simulates our service (like OpenSearch) verifying the token and authorizing access.
65function verifyAndAuthorizeRequest(token, servicePublicKey) {
66 console.log(`\n--- Service Provider (SP) ---`);
67 console.log(`➡️ Received a request with a JWT.`);
68
69 try {
70 // The SP uses the PUBLIC key to verify the token's signature.
71 // If the token is invalid, expired, or the signature doesn't match, this will throw an error.
72 const verificationOptions = {
73 algorithms: ['RS256'], // Must match the signing algorithm
74 issuer: 'MyAwesomeIdP' // Optional: verify the issuer
75 };
76
77 console.log('🔎 Verifying JWT signature with the PUBLIC key...');
78 const decodedPayload = jwt.verify(token, servicePublicKey, verificationOptions);
79
80 console.log('✅ Signature is valid!');
81 console.log('👤 Decoded User ID (sub):', decodedPayload.sub);
82 console.log('📜 Decoded Roles:', decodedPayload.roles);
83
84 // --- Authorization Step ---
85 // Now that we trust the token, we can use its contents to make an authorization decision.
86 if (decodedPayload.roles && decodedPayload.roles.includes('admin')) {
87 console.log('👑 Access Granted: User is an admin. Performing privileged action...');
88 } else if (decodedPayload.roles && decodedPayload.roles.includes('reader')) {
89 console.log('📖 Access Granted: User is a reader. Allowing read-only access...');
90 } else {
91 console.log('🚫 Access Denied: User does not have sufficient roles.');
92 }
93
94 } catch (error) {
95 console.error('❌ JWT Verification Failed!', error.message);
96 }
97}
98
99// --- 4. RUN THE SIMULATION ---
100
101// A) Simulate a user with 'admin' rights logging in.
102const adminUser = { id: 'user-123', roles: ['reader', 'admin'] };
103const adminToken = issueJwtForUser(adminUser.id, adminUser.roles);
104console.log('\nGenerated JWT for admin:\n', adminToken);
105verifyAndAuthorizeRequest(adminToken, publicKey);
106
107console.log('\n==================================================\n');
108
109// B) Simulate a user with only 'reader' rights.
110const readerUser = { id: 'user-456', roles: ['reader'] };
111const readerToken = issueJwtForUser(readerUser.id, readerUser.roles);
112console.log('\nGenerated JWT for reader:\n', readerToken);
113verifyAndAuthorizeRequest(readerToken, publicKey);
114
115console.log('\n==================================================\n');
116
117// C) FAILED SIMULATION: Tampering with the token
118console.log(`\n--- Tampering Simulation ---`);
119const tamperedToken = adminToken + 'tamper'; // Add garbage to the end of the token
120verifyAndAuthorizeRequest(tamperedToken, publicKey);
121
122// ** [Coauthored with AI] **
Created on 6/19/2025