Giter Site home page Giter Site logo

Comments (1)

FSPinho avatar FSPinho commented on September 28, 2024

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)
	})

from node-azure-ad-jwt.

Related Issues (11)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.