node-azure-ad-jwt
node-azure-ad-jwt copied to clipboard
Why does this error occurs? JsonWebTokenError: invalid signature
Hi. I fixed some outdated things on the code. My code bellow is working:
const jsonwebtoken = require('jsonwebtoken')
const request = require('request')
/** HELPER FUNCTION */
const convertCertificateToBeOpenSSLCompatible = cert => {
var beginCert = "-----BEGIN CERTIFICATE-----";
var endCert = "-----END CERTIFICATE-----";
cert = cert.replace("\n", "");
cert = cert.replace(beginCert, "");
cert = cert.replace(endCert, "");
var result = beginCert;
while (cert.length > 0) {
if (cert.length > 64) {
result += "\n" + cert.substring(0, 64);
cert = cert.substring(64, cert.length);
}
else {
result += "\n" + cert;
cert = "";
}
}
if (result[result.length ] != "\n")
result += "\n";
result += endCert + "\n";
return result;
}
const verifyToken = (token, nonce) => {
return new Promise((accept, reject) => {
/*
* Extract token info without verify
*/
const decodedToken = jsonwebtoken.decode(token, {complete: true})
if (decodedToken && decodedToken.payload && decodedToken.header) {
/** Email will be used to get user info */
const email = decodedToken.payload.email;
const tenantId = decodedToken.payload.tid;
const kid = decodedToken.header.kid;
var tenantOpenIdconfig = {
url: 'https://login.microsoftonline.com/' + tenantId + '/v2.0/.well-known/openid-configuration',
json: true
}
/*
* Loading the open-id configuration for a specific AAD tenant
* from a well known application.
*/
request.get(tenantOpenIdconfig, function(error, response, result) {
if (error) {
reject(error)
} else {
const { jwks_uri } = result;
var jwtSigningKeyRequestOptions = {
url: jwks_uri,
json: true
}
/*
* Download the signing certificates which is the public portion of the
* keys used to sign the JWT token
*/
request.get(jwtSigningKeyRequestOptions, function(error, response, result) {
if (error) {
reject(error)
} else {
var certificates = [];
/** Use KID to locate the public key and store the certificate chain. */
result.keys.find(function(publicKey) {
if (publicKey.kid === kid) {
publicKey.x5c.forEach(function(certificate) {
certificates.push(convertCertificateToBeOpenSSLCompatible(certificate))
});
}
})
const options = {
nonce,
kid,
algorithms: ['RS256']
}
var valid = false;
var lastError = null;
certificates.every(function(certificate) {
/** verify the token */
try {
/** verify the token */
jsonwebtoken.verify(token, certificate, options);
/** set the state */
valid = true;
lastError = null;
/** abort the enumeration */
return false;
} catch(error) {
/** set teh error state */
lastError = error;
/** check if we should try the next certificate */
if (error.message === 'invalid signature') {
return true;
} else {
return false;
}
}
});
/** done */
if (valid) {
accept(email);
} else {
reject(lastError);
}
}
});
}
});
} else {
reject(new Error(-1, 'Not a valid AAD token'))
}
})
}
/** USAGE EXAMPLE */
const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjFMVE16YWtpaGlSbGFfOHoyQkVKVlhlV01xbyJ9.eyJ2ZXIiOiIyLjAiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vOTE4ODA0MGQtNmM2Ny00YzViLWIxMTItMzZhMzA0YjY2ZGFkL3YyLjAiLCJzdWIiOiJBQUFBQUFBQUFBQUFBQUFBQUFBQUFJQUJtSkJ3eW11aXhVcElwZEhPSExNIiwiYXVkIjoiMzc3MDc0Y2YtYjYxNS00NTEyLTg5OGQtODk2NWM4YjdjNzY2IiwiZXhwIjoxNTQ5NjcxNTc0LCJpYXQiOjE1NDk1ODQ4NzQsIm5iZiI6MTU0OTU4NDg3NCwiZW1haWwiOiJmZWxpcGU3Njg1NzY4NUBnbWFpbC5jb20iLCJ0aWQiOiI5MTg4MDQwZC02YzY3LTRjNWItYjExMi0zNmEzMDRiNjZkYWQiLCJub25jZSI6ImFiYyIsImFpbyI6IkRkQjJLZ0xpUW12VipxVkpSdGdLQTZkSXdTV0N1anZvTzdFeHFVeEhITFVhQXdHN0tqQVRFaWVrOURRbldONmZjNk9DMUVBOGJIRHNiQkRPUjFUSHdBTDFBblE3NmRCUm5CTjZFeTgyMWp3MmJKWDgzQ25iRTBQdWd3VmJGcHMxcWckJCJ9.lo3fcLW2tglwuUh5bVAopidS9yLN0hc67jG9rmPlqzol_Lybt8EzQb1P7ZIS0xvgbwMV-Ml6-_NRmFbkhuXd0EWNjWWJocnr6Cm20PvGAfS1GFDlf4oXcJWZ47-Yz8YJwXqhfRuLscOslmhmXo_ODV5R6T2FXpUXfaUGNhS7DZGJOfgv292uyBCMmn5OpLYeDhZOWY0zGfeoyMrd5hrlCK-4qO9tekgN6692pvTh9tay7UtjORWaWCGVLMXwXo_iW7LHdnCgmZ2Tw-oqxRnI3_ULqHEr-DL63GqaPaI9AKH3uROzrP5dd_E6IdDmbYZwet-TErfK33FmaWDCAmXp0w'
const nonce = 'abc'
verifyToken(token, nonce)
.then(email => {
console.log('Cartificate is OK!')
console.log('Find user ' + email + ' and return a valid Firebase token!')
/** TODO: Return a valid firebase token to front */
})
.catch(error => {
console.error(error)
})