ngx-hybrid-soap
Version:
SOAP service for Angular
88 lines • 15 kB
JavaScript
"use strict";
// var crypto = require('crypto');
import sha1 from 'crypto-js/sha1';
import Base64 from 'crypto-js/enc-base64';
// var passwordDigest = require('../utils').passwordDigest;
import { passwordDigest } from '../utils';
var validPasswordTypes = ['PasswordDigest', 'PasswordText'];
export function WSSecurity(username, password, options) {
options = options || {};
this._username = username;
this._password = password;
//must account for backward compatibility for passwordType String param as well as object options defaults: passwordType = 'PasswordText', hasTimeStamp = true
if (typeof options === 'string') {
this._passwordType = options ? options : 'PasswordText';
options = {};
}
else {
this._passwordType = options.passwordType ? options.passwordType : 'PasswordText';
}
if (validPasswordTypes.indexOf(this._passwordType) === -1) {
this._passwordType = 'PasswordText';
}
this._hasTimeStamp = options.hasTimeStamp || typeof options.hasTimeStamp === 'boolean' ? !!options.hasTimeStamp : true;
/*jshint eqnull:true */
if (options.hasNonce != null) {
this._hasNonce = !!options.hasNonce;
}
this._hasTokenCreated = options.hasTokenCreated || typeof options.hasTokenCreated === 'boolean' ? !!options.hasTokenCreated : true;
if (options.actor != null) {
this._actor = options.actor;
}
if (options.mustUnderstand != null) {
this._mustUnderstand = !!options.mustUnderstand;
}
}
WSSecurity.prototype.toXML = function () {
// avoid dependency on date formatting libraries
function getDate(d) {
function pad(n) {
return n < 10 ? '0' + n : n;
}
return d.getUTCFullYear() + '-'
+ pad(d.getUTCMonth() + 1) + '-'
+ pad(d.getUTCDate()) + 'T'
+ pad(d.getUTCHours()) + ':'
+ pad(d.getUTCMinutes()) + ':'
+ pad(d.getUTCSeconds()) + 'Z';
}
var now = new Date();
var created = getDate(now);
var timeStampXml = '';
if (this._hasTimeStamp) {
var expires = getDate(new Date(now.getTime() + (1000 * 600)));
timeStampXml = "<wsu:Timestamp wsu:Id=\"Timestamp-" + created + "\">" +
"<wsu:Created>" + created + "</wsu:Created>" +
"<wsu:Expires>" + expires + "</wsu:Expires>" +
"</wsu:Timestamp>";
}
var password, nonce;
if (this._hasNonce || this._passwordType !== 'PasswordText') {
// nonce = base64 ( sha1 ( created + random ) )
// var nHash = crypto.createHash('sha1');
// nHash.update(created + Math.random());
// nonce = nHash.digest('base64');
nonce = Base64.stringify(sha1(created + Math.random(), ''));
}
if (this._passwordType === 'PasswordText') {
password = "<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" + this._password + "</wsse:Password>";
if (nonce) {
password += "<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + nonce + "</wsse:Nonce>";
}
}
else {
password = "<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + passwordDigest(nonce, created, this._password) + "</wsse:Password>" +
"<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + nonce + "</wsse:Nonce>";
}
return "<wsse:Security " + (this._actor ? "soap:actor=\"" + this._actor + "\" " : "") +
(this._mustUnderstand ? "soap:mustUnderstand=\"1\" " : "") +
"xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" +
timeStampXml +
"<wsse:UsernameToken xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"SecurityToken-" + created + "\">" +
"<wsse:Username>" + this._username + "</wsse:Username>" +
password +
(this._hasTokenCreated ? "<wsu:Created>" + created + "</wsu:Created>" : "") +
"</wsse:UsernameToken>" +
"</wsse:Security>";
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV1NTZWN1cml0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zb2FwL3NyYy9saWIvc29hcC9zZWN1cml0eS9XU1NlY3VyaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQztBQUViLGtDQUFrQztBQUNsQyxPQUFPLElBQUksTUFBTSxnQkFBZ0IsQ0FBQztBQUNsQyxPQUFPLE1BQU0sTUFBTSxzQkFBc0IsQ0FBQztBQUUxQywyREFBMkQ7QUFDM0QsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUUxQyxJQUFJLGtCQUFrQixHQUFHLENBQUMsZ0JBQWdCLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFFNUQsTUFBTSxVQUFVLFVBQVUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLE9BQU87SUFDcEQsT0FBTyxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUM7SUFDeEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUM7SUFDMUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUM7SUFDMUIsaUtBQWlLO0lBQ2pLLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDO1FBQ3hELE9BQU8sR0FBRyxFQUFFLENBQUM7SUFDZixDQUFDO1NBQU0sQ0FBQztRQUNOLElBQUksQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDO0lBQ3BGLENBQUM7SUFFRCxJQUFJLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMxRCxJQUFJLENBQUMsYUFB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QUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUNELElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxjQUFjLEVBQUUsQ0FBQztRQUMxQyxRQUFRLEdBQUcsMEhBQTBILEdBQUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQztRQUM1SyxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsUUFBUSxJQUFJLDhIQUE4SCxHQUFHLEtBQUssR0FBRyxlQUFlLENBQUM7UUFDdkssQ0FBQztJQUNILENBQUM7U0FBTSxDQUFDO1FBQ04sUUFBUSxHQUFHLDRIQUE0SCxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxrQkFBa0I7WUFDM00sOEhBQThILEdBQUcsS0FBSyxHQUFHLGVBQWUsQ0FBQztJQUM3SixDQUFDO0lBRUQsT0FBTyxpQkFBaUIsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ25GLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMxRCxvTUFBb007UUFDcE0sWUFBWTtRQUNaLDhJQUE4SSxHQUFHLE9BQU8sR0FBRyxLQUFLO1FBQ2hLLGlCQUFpQixHQUFHLElBQUksQ0FBQyxTQUFTLEdBQUcsa0JBQWtCO1FBQ3ZELFFBQVE7UUFDUixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsZUFBZSxHQUFHLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzNFLHVCQUF1QjtRQUN2QixrQkFBa0IsQ0FBQztBQUN2QixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcblxuLy8gdmFyIGNyeXB0byA9IHJlcXVpcmUoJ2NyeXB0bycpO1xuaW1wb3J0IHNoYTEgZnJvbSAnY3J5cHRvLWpzL3NoYTEnO1xuaW1wb3J0IEJhc2U2NCBmcm9tICdjcnlwdG8tanMvZW5jLWJhc2U2NCc7XG5cbi8vIHZhciBwYXNzd29yZERpZ2VzdCA9IHJlcXVpcmUoJy4uL3V0aWxzJykucGFzc3dvcmREaWdlc3Q7XG5pbXBvcnQgeyBwYXNzd29yZERpZ2VzdCB9IGZyb20gJy4uL3V0aWxzJztcblxudmFyIHZhbGlkUGFzc3dvcmRUeXBlcyA9IFsnUGFzc3dvcmREaWdlc3QnLCAnUGFzc3dvcmRUZXh0J107XG5cbmV4cG9ydCBmdW5jdGlvbiBXU1NlY3VyaXR5KHVzZXJuYW1lLCBwYXNzd29yZCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgdGhpcy5fdXNlcm5hbWUgPSB1c2VybmFtZTtcbiAgdGhpcy5fcGFzc3dvcmQgPSBwYXNzd29yZDtcbiAgLy9tdXN0IGFjY291bnQgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgZm9yIHBhc3N3b3JkVHlwZSBTdHJpbmcgcGFyYW0gYXMgd2VsbCBhcyBvYmplY3Qgb3B0aW9ucyBkZWZhdWx0czogcGFzc3dvcmRUeXBlID0gJ1Bhc3N3b3JkVGV4dCcsIGhhc1RpbWVTdGFtcCA9IHRydWUgICBcbiAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnc3RyaW5nJykge1xuICAgIHRoaXMuX3Bhc3N3b3JkVHlwZSA9IG9wdGlvbnMgPyBvcHRpb25zIDogJ1Bhc3N3b3JkVGV4dCc7XG4gICAgb3B0aW9ucyA9IHt9O1xuICB9IGVsc2Uge1xuICAgIHRoaXMuX3Bhc3N3b3JkVHlwZSA9IG9wdGlvbnMucGFzc3dvcmRUeXBlID8gb3B0aW9ucy5wYXNzd29yZFR5cGUgOiAnUGFzc3dvcmRUZXh0JztcbiAgfVxuXG4gIGlmICh2YWxpZFBhc3N3b3JkVHlwZXMuaW5kZXhPZih0aGlzLl9wYXNzd29yZFR5cGUpID09PSAtMSkge1xuICAgIHRoaXMuX3Bhc3N3b3JkVHlwZSA9ICdQYXNzd29yZFRleHQnO1xuICB9XG5cbiAgdGhpcy5faGFzVGltZVN0YW1wID0gb3B0aW9ucy5oYXNUaW1lU3RhbXAgfHwgdHlwZW9mIG9wdGlvbnMuaGFzVGltZVN0YW1wID09PSAnYm9vbGVhbicgPyAhIW9wdGlvbnMuaGFzVGltZVN0YW1wIDogdHJ1ZTtcbiAgLypqc2hpbnQgZXFudWxsOnRydWUgKi9cbiAgaWYgKG9wdGlvbnMuaGFzTm9uY2UgIT0gbnVsbCkge1xuICAgIHRoaXMuX2hhc05vbmNlID0gISFvcHRpb25zLmhhc05vbmNlO1xuICB9XG4gIHRoaXMuX2hhc1Rva2VuQ3JlYXRlZCA9IG9wdGlvbnMuaGFzVG9rZW5DcmVhdGVkIHx8IHR5cGVvZiBvcHRpb25zLmhhc1Rva2VuQ3JlYXRlZCA9PT0gJ2Jvb2xlYW4nID8gISFvcHRpb25zLmhhc1Rva2VuQ3JlYXRlZCA6IHRydWU7XG4gIGlmIChvcHRpb25zLmFjdG9yICE9IG51bGwpIHtcbiAgICB0aGlzLl9hY3RvciA9IG9wdGlvbnMuYWN0b3I7XG4gIH1cbiAgaWYgKG9wdGlvbnMubXVzdFVuZGVyc3RhbmQgIT0gbnVsbCkge1xuICAgIHRoaXMuX211c3RVbmRlcnN0YW5kID0gISFvcHRpb25zLm11c3RVbmRlcnN0YW5kO1xuICB9XG59XG5cbldTU2VjdXJpdHkucHJvdG90eXBlLnRvWE1MID0gZnVuY3Rpb24oKSB7XG4gIC8vIGF2b2lkIGRlcGVuZGVuY3kgb24gZGF0ZSBmb3JtYXR0aW5nIGxpYnJhcmllc1xuICBmdW5jdGlvbiBnZXREYXRlKGQpIHtcbiAgICBmdW5jdGlvbiBwYWQobikge1xuICAgICAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4gOiBuO1xuICAgIH1cbiAgICByZXR1cm4gZC5nZXRVVENGdWxsWWVhcigpICsgJy0nXG4gICAgICArIHBhZChkLmdldFVUQ01vbnRoKCkgKyAxKSArICctJ1xuICAgICAgKyBwYWQoZC5nZXRVVENEYXRlKCkpICsgJ1QnXG4gICAgICArIHBhZChkLmdldFVUQ0hvdXJzKCkpICsgJzonXG4gICAgICArIHBhZChkLmdldFVUQ01pbnV0ZXMoKSkgKyAnOidcbiAgICAgICsgcGFkKGQuZ2V0VVRDU2Vjb25kcygpKSArICdaJztcbiAgfVxuICB2YXIgbm93ID0gbmV3IERhdGUoKTtcbiAgdmFyIGNyZWF0ZWQgPSBnZXREYXRlKG5vdyk7XG4gIHZhciB0aW1lU3RhbXBYbWwgPSAnJztcbiAgaWYgKHRoaXMuX2hhc1RpbWVTdGFtcCkge1xuICAgIHZhciBleHBpcmVzID0gZ2V0RGF0ZSggbmV3IERhdGUobm93LmdldFRpbWUoKSArICgxMDAwICogNjAwKSkgKTtcbiAgICB0aW1lU3RhbXBYbWwgPSBcIjx3c3U6VGltZXN0YW1wIHdzdTpJZD1cXFwiVGltZXN0YW1wLVwiK2NyZWF0ZWQrXCJcXFwiPlwiICtcbiAgICAgIFwiPHdzdTpDcmVhdGVkPlwiK2NyZWF0ZWQrXCI8L3dzdTpDcmVhdGVkPlwiICtcbiAgICAgIFwiPHdzdTpFeHBpcmVzPlwiK2V4cGlyZXMrXCI8L3dzdTpFeHBpcmVzPlwiICtcbiAgICAgIFwiPC93c3U6VGltZXN0YW1wPlwiO1xuICB9XG5cbiAgdmFyIHBhc3N3b3JkLCBub25jZTtcbiAgaWYgKHRoaXMuX2hhc05vbmNlIHx8IHRoaXMuX3Bhc3N3b3JkVHlwZSAhPT0gJ1Bhc3N3b3JkVGV4dCcpIHtcbiAgICAvLyBub25jZSA9IGJhc2U2NCAoIHNoYTEgKCBjcmVhdGVkICsgcmFuZG9tICkgKVxuICAgIC8vIHZhciBuSGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGExJyk7XG4gICAgLy8gbkhhc2gudXBkYXRlKGNyZWF0ZWQgKyBNYXRoLnJhbmRvbSgpKTtcbiAgICAvLyBub25jZSA9IG5IYXNoLmRpZ2VzdCgnYmFzZTY0Jyk7XG4gICAgbm9uY2UgPSBCYXNlNjQuc3RyaW5naWZ5KHNoYTEoY3JlYXRlZCArIE1hdGgucmFuZG9tKCksICcnKSk7XG4gIH1cbiAgaWYgKHRoaXMuX3Bhc3N3b3JkVHlwZSA9PT0gJ1Bhc3N3b3JkVGV4dCcpIHtcbiAgICBwYXNzd29yZCA9IFwiPHdzc2U6UGFzc3dvcmQgVHlwZT1cXFwiaHR0cDovL2RvY3Mub2FzaXMtb3Blbi5vcmcvd3NzLzIwMDQvMDEvb2FzaXMtMjAwNDAxLXdzcy11c2VybmFtZS10b2tlbi1wcm9maWxlLTEuMCNQYXNzd29yZFRleHRcXFwiPlwiICsgdGhpcy5fcGFzc3dvcmQgKyBcIjwvd3NzZTpQYXNzd29yZD5cIjtcbiAgICBpZiAobm9uY2UpIHtcbiAgICAgIHBhc3N3b3JkICs9IFwiPHdzc2U6Tm9uY2UgRW5jb2RpbmdUeXBlPVxcXCJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3MvMjAwNC8wMS9vYXNpcy0yMDA0MDEtd3NzLXNvYXAtbWVzc2FnZS1zZWN1cml0eS0xLjAjQmFzZTY0QmluYXJ5XFxcIj5cIiArIG5vbmNlICsgXCI8L3dzc2U6Tm9uY2U+XCI7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHBhc3N3b3JkID0gXCI8d3NzZTpQYXNzd29yZCBUeXBlPVxcXCJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3MvMjAwNC8wMS9vYXNpcy0yMDA0MDEtd3NzLXVzZXJuYW1lLXRva2VuLXByb2ZpbGUtMS4wI1Bhc3N3b3JkRGlnZXN0XFxcIj5cIiArIHBhc3N3b3JkRGlnZXN0KG5vbmNlLCBjcmVhdGVkLCB0aGlzLl9wYXNzd29yZCkgKyBcIjwvd3NzZTpQYXNzd29yZD5cIiArXG4gICAgICBcIjx3c3NlOk5vbmNlIEVuY29kaW5nVHlwZT1cXFwiaHR0cDovL2RvY3Mub2FzaXMtb3Blbi5vcmcvd3NzLzIwMDQvMDEvb2FzaXMtMjAwNDAxLXdzcy1zb2FwLW1lc3NhZ2Utc2VjdXJpdHktMS4wI0Jhc2U2NEJpbmFyeVxcXCI+XCIgKyBub25jZSArIFwiPC93c3NlOk5vbmNlPlwiO1xuICB9XG5cbiAgcmV0dXJuIFwiPHdzc2U6U2VjdXJpdHkgXCIgKyAodGhpcy5fYWN0b3IgPyBcInNvYXA6YWN0b3I9XFxcIlwiICsgdGhpcy5fYWN0b3IgKyBcIlxcXCIgXCIgOiBcIlwiKSArXG4gICAgKHRoaXMuX211c3RVbmRlcnN0YW5kID8gXCJzb2FwOm11c3RVbmRlcnN0YW5kPVxcXCIxXFxcIiBcIiA6IFwiXCIpICtcbiAgICBcInhtbG5zOndzc2U9XFxcImh0dHA6Ly9kb2NzLm9hc2lzLW9wZW4ub3JnL3dzcy8yMDA0LzAxL29hc2lzLTIwMDQwMS13c3Mtd3NzZWN1cml0eS1zZWNleHQtMS4wLnhzZFxcXCIgeG1sbnM6d3N1PVxcXCJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3MvMjAwNC8wMS9vYXNpcy0yMDA0MDEtd3NzLXdzc2VjdXJpdHktdXRpbGl0eS0xLjAueHNkXFxcIj5cIiArXG4gICAgdGltZVN0YW1wWG1sICtcbiAgICBcIjx3c3NlOlVzZXJuYW1lVG9rZW4geG1sbnM6d3N1PVxcXCJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3MvMjAwNC8wMS9vYXNpcy0yMDA0MDEtd3NzLXdzc2VjdXJpdHktdXRpbGl0eS0xLjAueHNkXFxcIiB3c3U6SWQ9XFxcIlNlY3VyaXR5VG9rZW4tXCIgKyBjcmVhdGVkICsgXCJcXFwiPlwiICtcbiAgICBcIjx3c3NlOlVzZXJuYW1lPlwiICsgdGhpcy5fdXNlcm5hbWUgKyBcIjwvd3NzZTpVc2VybmFtZT5cIiArXG4gICAgcGFzc3dvcmQgK1xuICAgICh0aGlzLl9oYXNUb2tlbkNyZWF0ZWQgPyBcIjx3c3U6Q3JlYXRlZD5cIiArIGNyZWF0ZWQgKyBcIjwvd3N1OkNyZWF0ZWQ+XCIgOiBcIlwiKSArXG4gICAgXCI8L3dzc2U6VXNlcm5hbWVUb2tlbj5cIiArXG4gICAgXCI8L3dzc2U6U2VjdXJpdHk+XCI7XG59O1xuXG4vLyBtb2R1bGUuZXhwb3J0cyA9IFdTU2VjdXJpdHk7XG4iXX0=