strong-soap
Version:
A minimal node SOAP client
90 lines (71 loc) • 3.69 kB
JavaScript
;
var g = require('../globalize');
var optional = require('optional');
var ursa = optional('ursa');
var fs = require('fs');
var path = require('path');
var SignedXml = require('xml-crypto').SignedXml;
var uuid = require('uuid');
var Security = require('./security');
var xmlHandler = require('../parser/xmlHandler');
function addMinutes(date, minutes) {
return new Date(date.getTime() + minutes * 60000);
}
function dateStringForSOAP(date) {
return date.getUTCFullYear() + '-' + ('0' + (date.getUTCMonth() + 1)).slice(-2) + '-' + ('0' + date.getUTCDate()).slice(-2) + 'T' + ('0' + date.getUTCHours()).slice(-2) + ":" + ('0' + date.getUTCMinutes()).slice(-2) + ":" + ('0' + date.getUTCSeconds()).slice(-2) + "Z";
}
function generateCreated() {
return dateStringForSOAP(new Date());
}
function generateExpires() {
return dateStringForSOAP(addMinutes(new Date(), 10));
}
function insertStr(src, dst, pos) {
return [dst.slice(0, pos), src, dst.slice(pos)].join('');
}
function generateId() {
return uuid.v4().replace(/-/gm, '');
}
class WSSecurityCert extends Security {
constructor(privatePEM, publicP12PEM, password, encoding) {
super();
if (!ursa) {
throw new Error(g.f('Module {{ursa}} must be installed to use {{WSSecurityCert}}'));
}
this.privateKey = ursa.createPrivateKey(privatePEM, password, encoding);
this.publicP12PEM = publicP12PEM.toString().replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', '').replace(/(\r\n|\n|\r)/gm, '');
this.signer = new SignedXml();
this.signer.signingKey = this.privateKey.toPrivatePem();
this.x509Id = 'x509-' + generateId();
var references = ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/2001/10/xml-exc-c14n#'];
this.signer.addReference('//*[local-name(.)=\'Body\']', references);
this.signer.addReference('//*[local-name(.)=\'Timestamp\']', references);
var _this = this;
this.signer.keyInfoProvider = {};
this.signer.keyInfoProvider.getKeyInfo = function (key) {
var x509Id = _this.x509Id;
var xml = `<wsse:SecurityTokenReference>
<wsse:Reference URI="${x509Id}" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>`;
return xml;
};
}
postProcess(headerElement, bodyElement) {
this.created = generateCreated();
this.expires = generateExpires();
var binaryToken = this.publicP12PEM,
created = this.created,
expires = this.expires,
id = this.x509Id;
var secElement = headerElement.element('wsse:Security').attribute('xmlns:wsse', 'http://docs.oasis-open.org/wss/2004/01/' + 'oasis-200401-wss-wssecurity-secext-1.0.xsd').attribute('xmlns:wsu', 'http://docs.oasis-open.org/wss/2004/01/' + 'oasis-200401-wss-wssecurity-utility-1.0.xsd').attribute('soap:mustUnderstand', '1');
secElement.element('wsse:BinarySecurityToken').attribute('EncodingType', 'http://docs.oasis-open.org/wss/2004/01/' + 'oasis-200401-wss-soap-message-security-1.0#Base64Binary').attribute('ValueType', 'http://docs.oasis-open.org/wss/2004/01/' + 'oasis-200401-wss-x509-token-profile-1.0#X509v3').attribute('wsu:Id', id).text(binaryToken);
var tsElement = secElement.element('wsu:Timestamp').attribute('wsu:Id', '_1');
tsElement.element('wsu:Created', created);
tsElement.element('wsu:Expires', expires);
var xmlWithSec = headerElement.doc().end({ pretty: true });
this.signer.computeSignature(xmlWithSec);
var sig = this.signer.getSignatureXml();
xmlHandler.parseXml(secElement, sig);
}
}
module.exports = WSSecurityCert;