I am trying to create a JWT and then verify it using AWS KMS Node API. Below is my code, which represents my understanding of the AWS documentation. However calling KMS verify throws KMSInvalidSignatureException
process.env.AWS_REGION = '...';
process.env.AWS_ACCOUNT_ID = '...';
process.env.AWS_PROFILE = '...';
process.env.KEY_ID = '...id of RSA 2048 bytes key stored in AWS KMS...';
const aws = require('aws-sdk');
const kms = new aws.KMS();
const base64url = require('base64url');
async function createToken() {
const iat = Math.floor(Date.now() / 1000);
const tomorrow = new Date()
tomorrow.setDate(tomorrow.getDate() + 1)
const exp = Math.floor(tomorrow.getTime() / 1000);
const header = base64url.encode(JSON.stringify({
alg: 'RS256',
typ: 'JWT'
}));
const payload = base64url.encode(JSON.stringify({
iat,
exp,
code: '123'
}));
const message = Buffer.from(`${header}.${payload}`);
const signResponse = await kms.sign({
KeyId: process.env.KEY_ID,
Message: message,
MessageType: 'RAW',
SigningAlgorithm: 'RSASSA_PKCS1_V1_5_SHA_256'
}).promise();
const signature = signResponse.Signature.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
return `${header}.${payload}.${signature}`;
}
async function verifyToken(token) {
const [header, payload, signature] = token.split('.');
const message = Buffer.from(`${header}.${payload}`);
return await kms.verify({
KeyId: process.env.KEY_ID,
Message: message,
MessageType: 'RAW',
Signature: signature,
SigningAlgorithm: 'RSASSA_PKCS1_V1_5_SHA_256'
}).promise();
}
async function main() {
const token = await createToken();
const verification = await verifyToken(token);
console.log(verification);
}
main();
What am I doing wrong ?
At least with V3 of the aws-sdk, verify
expects Signature
to be a Buffer/Uint8Array.
Possibly fixed verifyToken function (also removed obsolete async/await
):
function verifyToken(token) {
const [header, payload, signature] = token.split('.');
const message = Buffer.from(`${header}.${payload}`);
return kms.verify({
KeyId: process.env.KEY_ID,
Message: message,
MessageType: 'RAW',
Signature: Buffer.from(signature, 'base64'),
SigningAlgorithm: 'RSASSA_PKCS1_V1_5_SHA_256'
}).promise();
}