5

I'm trying to request this internal service that the team responsible for it said it needs both an Username + Password AND to be encrypted with a certificate.

I thought of using this module node-soap and I found this in the documentation:

1- https://github.com/vpulim/node-soap#wssecurity

2- https://github.com/vpulim/node-soap#wssecuritycert

It explains how to implement WSSecurity, but one rule overwrites the other. So this code won't work:

var wsSecurity = new soap.WSSecurity('username', 'password', options)
client.setSecurity(wsSecurity);

var wsSecurity = new soap.WSSecurityCert(privateKey, publicKey, password);
client.setSecurity(wsSecurity);

What is the proper way of using both strategies?

I'm a newbie on SOAP, any help would be very appreciated

Victor Ferreira
  • 6,151
  • 13
  • 64
  • 120

2 Answers2

1

I'm running into the same requirement. I'm building a custom WSSecurityCertSSL security module, it's not that great but may just work. The best thing would be to modify node-soap so that you can stack multiple securities, since some (ie: ssl) deal with just the connection and others with envelope manipulation (ie: WssSecurity).

loop
  • 87
  • 1
  • 5
1

I'm totally against modifying the source of any 3th party dependencies. It usually leads to future problems ( updates, compatibility, unsuspected bugs etc.) Here is my attempt of stacking securities.

import { IHeaders, ISecurity } from "soap";

export class SecurityStack implements ISecurity {
    private stack: ISecurity[];
    public constructor(...security: ISecurity[]) {
        this.stack = security;

        const hasPostProcessMethod = this.stack.some(s => s["postProcess"]);
        const hasToXmlMethod = this.stack.some(s => s["toXML"]);

        if(hasPostProcessMethod && hasToXmlMethod)
            throw new Error("Security with `postProcess` and those with `toXml` methods cannot be used together");

        if(!hasPostProcessMethod)
            this.postProcess = undefined;
    }

    public addOptions(options: any): void {
        this.stack.forEach(security => {
            if(security["addOptions"])
                security.addOptions(options);
        });
    }

    public toXML(): string {
        let result = "";
        this.stack.forEach(security => {
            if(security["toXML"])
                result += security.toXML();
        });
        return result;
    }

    public addHeaders(headers: IHeaders): void {
        this.stack.forEach(security => {
            if(security["addHeaders"])
                security.addHeaders(headers);
        });
    }

    public postProcess?(xml: any, envelopeKey: any): string {
        let result = xml;
        this.stack.forEach(security => {
            if(security["postProcess"])
                result = security.postProcess(xml, envelopeKey);
        });
        return result;
    }
}

And then usage:

const client =  await soap.createClientAsync(wsdl);
const sslSecurity = new soap.ClientSSLSecurity(xxx, xxx);
const wsSecurity = new soap.WSSecurity("xxx","xxx");
const securityStack = new SecurityStack(sslSecurity, wsSecurity);
client.setSecurity(securityStack);

Keep in mind that not every security methods can be combined.

ZBAGI
  • 128
  • 6