OAuth 2.1 Sample Codes
Want to see these steps in context? Follow the OAuth 2.1 interactive walkthrough.
These sample codes are for reference only and are not intended for production use.
Generate Code Challenge and Code Verifier
'use strict';
const crypto = require('crypto');
function generateCodeVerifier() {
return crypto.randomBytes(32).toString('base64url');
}
function generateCodeChallenge(codeVerifier) {
return crypto.createHash('sha256').update(codeVerifier).digest('base64url');
}
const codeVerifier = generateCodeVerifier();
const codeChallenge = generateCodeChallenge(codeVerifier);
console.log('Code Verifier:', codeVerifier);
console.log('Code Challenge:', codeChallenge);Generate JWKS Endpoint
'use strict';
const jose = require('node-jose');
const crypto = require('crypto');
async function jwks() {
let key = crypto.generateKeyPairSync('ec', {
namedCurve: 'prime256v1',
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
},
});
let cryptoKey = await jose.JWK.asKey(key.privateKey, 'pem');
let publicKeyJSON = cryptoKey.toJSON();
let jwksEndpoint = {
keys: [{
...publicKeyJSON,
use: "sig",
crv: "P-256",
alg: "ES256",
}]
};
console.log("Public keys:");
console.log(publicKeyJSON);
console.log("JWKS Endpoint:");
console.log(jwksEndpoint);
}
jwks();Sample Output
Public keys:
{
"kty": "EC",
"kid": "vyaeBP-ohJ5RF_cEEU1v0h3IEIoWCa24YKZK4ddb4-U",
"crv": "P-256",
"x": "RYvFyXBZLa7TWEDlk3sqqyhxXkTYGkEEl5AuANZ70Ps",
"y": "JKobI-7Z4xBCGDKDubtBF-sHvC69F6sKGbRX3RIaGhY"
}
JWKS Endpoint:
{
"keys": [
{
"kty": "EC",
"kid": "vyaeBP-ohJ5RF_cEEU1v0h3IEIoWCa24YKZK4ddb4-U",
"crv": "P-256",
"x": "RYvFyXBZLa7TWEDlk3sqqyhxXkTYGkEEl5AuANZ70Ps",
"y": "JKobI-7Z4xBCGDKDubtBF-sHvC69F6sKGbRX3RIaGhY",
"use": "sig",
"alg": "ES256"
}
]
}Generate Client Assertion
The client assertion is a JWT signed with your ES256 private key that proves your application’s identity during the token exchange.
'use strict';
const jwt = require('jsonwebtoken');
const fs = require('fs');
const epoch = new Date().getTime();
let payload = {};
let privateKey = fs.readFileSync('./private.key', 'utf8');
let signOptions = {
issuer: 'STG-xxxx', // Your Client ID issued during Initial Setup
subject: 'STG-xxxx', // Your Client ID issued during Initial Setup
audience: 'https://public.api.gov.sg/oauth/cp/v3/token',
jwtid: `session-${epoch}`, // Unique session ID for troubleshooting and preventing replay attacks
keyid: 'key-id1', // Your key ID in JWKS endpoint from Initial Setup
expiresIn: '5m',
algorithm: 'ES256'
};
let clientAssertion = jwt.sign(payload, privateKey, signOptions);
console.log('Client Assertion:', clientAssertion);
| Claim | Value |
|---|---|
iss |
Your Client ID. |
sub |
Your Client ID. |
aud |
The Token Endpoint URL (e.g. https://public.api.gov.sg/oauth/cp/v3/token). |
kid |
Key ID of the signing key in your JWKS endpoint. |
jti |
A unique identifier for this token request (e.g. session ID with epoch). |
exp |
Expiry time — must not exceed 5 minutes from iat. |