UNPKG

cybersource-rest-client

Version:

Node.js SDK for the CyberSource REST API

110 lines (96 loc) 4.04 kB
'use strict' const jose = require('node-jose'); const KeyCertificate = require('../jwt/KeyCertificateGenerator'); const forge = require('node-forge'); const Logger= require('../logging/Logger'); const ApiException= require('./ApiException'); const Constants = require('./Constants'); exports.checkIsMLEForAPI = function(merchantConfig, isMLESupportedByCybsForApi, operationId) { //isMLE for an api is false by default var isMLEForAPI = false; //check here useMLEGlobally True or False //if API is part of MLE then check for useMLEGlobally global paramter if (isMLESupportedByCybsForApi === true && merchantConfig.useMLEGlobally === true) { isMLEForAPI = true; } //Control the MLE only from map if (merchantConfig.mapToControlMLEonAPI != null && operationId in merchantConfig.mapToControlMLEonAPI) { if (merchantConfig.mapToControlMLEonAPI[operationId] === true) { isMLEForAPI = true; } if (merchantConfig.mapToControlMLEonAPI[operationId] === false) { isMLEForAPI = false; } } return isMLEForAPI; } exports.encryptRequestPayload = function(merchantConfig, requestBody) { if (requestBody != null) { var logger = Logger.getLogger(merchantConfig, 'MLEUtility'); return generateJWEToken(requestBody, logger, merchantConfig).then(token => { logger.debug(Constants.LOG_REQUEST_BEFORE_MLE + JSON.stringify(requestBody)); let mleRequest = createMLEJsonRequest(token); logger.debug(Constants.LOG_REQUEST_AFTER_MLE + JSON.stringify(mleRequest)); return mleRequest; }); } else { return Promise.resolve(requestBody); } } function generateJWEToken(requestBody, logger, merchantConfig) { //get the MLE cert and verify the expiry of cert let cert = KeyCertificate.getX509CertificateInCert(merchantConfig, logger, merchantConfig.getMleKeyAlias()); let isCertExpired = KeyCertificate.verifyIsCertificateExpired(cert, merchantConfig.getMleKeyAlias(), logger); // if (isCertExpired === true) { // ApiException.ApiException("Certificate for MLE with alias " + merchantConfig.getMleKeyAlias() + " is expired in " + merchantConfig.getKeyFileName() + ".p12", logger); // } const customHeaders = { iat: Math.floor(Date.now() / 1000) //epoch time in seconds }; const serialNumber = getSerialNumberFromCert(cert, merchantConfig, logger); const headers = { alg: "RSA-OAEP-256", enc: "A256GCM", cty: "JWT", kid: serialNumber, ...customHeaders }; if (requestBody !== "{}") { requestBody = JSON.stringify(requestBody, null, 0); } const payload = Buffer.from(requestBody); const publicKeyInJWK = { kty: 'RSA', n: toBase64Url(cert.publicKey.n), e: toBase64Url(cert.publicKey.e), }; return jose.JWE.createEncrypt({ format: 'compact', fields: headers }, { key: publicKeyInJWK, header: { kid: serialNumber } }) .update(payload) .final() .then(result => { return result; }); } function toBase64Url(bi) { const hex = bi.toString(16); const base64 = forge.util.encode64(forge.util.hexToBytes(hex)); return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } function createMLEJsonRequest(jweToken) { const mleJson = { encryptedRequest: jweToken }; return mleJson; } function getSerialNumberFromCert(cert, merchantConfig, logger) { if (!cert.subject || !cert.subject.attributes) { throw new Error("Subject or attributes are missing in MLE cert"); } const serialNumberAttr = cert.subject.attributes.find(attr => attr.name === 'serialNumber'); if (serialNumberAttr) { return serialNumberAttr.value; } else { logger.warn("Serial number not found in MLE certificate for alias " + merchantConfig.getMleKeyAlias() + " in " + merchantConfig.getKeyFileName() + ".p12"); return cert.serialNumber; } }