UNPKG

strong-soap

Version:
90 lines (71 loc) 3.69 kB
'use strict'; 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;