Reputation: 300
I am attempting to connect to a SOAP web service that implements its WS security by means of a SOAP header element using the Loopback SOAP connector.
Unfortunately, documentation regarding how to configure the soap header option of the connector is sparse.
It would be greatly appreciated if you could assist by indicating how the soap header should be constructed in order for the web service to authenticate successfully.
var loopback = require('loopback');
var path = require('path');
var app = module.exports = loopback();
app.set('restApiRoot', '/api');
var myHeader = {
Security:
{
UsernameToken:{
Username: "Staging Integration Store 3",
Password: "WSAUFbw6"
}
}
};
var ds = loopback.createDataSource('soap',
{
connector: require('../index'),
/* security: {
scheme: 'wsse',
created: null,
username: "Staging Integration Store 3",
password: "WSAUFbw6",
passwordType: 'PasswordText'
}, */
soapHeaders: [{
element: myHeader, // The XML element in JSON object format
prefix: 'wsse', // The XML namespace prefix for the header
namespace: 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' // The XML namespace URI for the header
}],
remotingEnabled: true,
// wsdl: 'https://staging.payu.co.za/service/PayUAPI?wsdl' // The url to WSDL
wsdl: path.join(__dirname, './PayUAPI.wsdl')
});
// Unfortunately, the methods from the connector are mixed in asynchronously
// This is a hack to wait for the methods to be injected
ds.once('connected', function () {
// Create the model
// var WeatherService = ds.createModel('WeatherService', {});
var RedirectPaymentService = ds.createModel('RedirectPaymentService', {});
// Refine the methods
RedirectPaymentService.payments = function (api,safekey,transactiontype,additionalInfo,customer,basket,cb) {
RedirectPaymentService.setTransaction({Api: api,Safekey: safekey,TransactionType: transactiontype,AdditionalInformation: additionalInfo,Customer: customer,Basket: basket}, function (err, response) {
console.log('SetTransaction: %j', response);
var result = (!err && response.return.successful.localCompare("true") == 0) ?
response.return.payuReference : response.return.resultMessage;
cb(err, result);
});
};
Response:
SetTransaction: {"statusCode":500,"body":"<soap:Envelope xmlns:soap=\"http://sch
emas.xmlsoap.org/soap/envelope/\"><soap:Body><soap:Fault><faultcode xmlns:ns1=\"
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xs
d\">ns1:InvalidSecurityToken</faultcode><faultstring>An invalid security token w
as provided (An error happened processing a Username Token)</faultstring></soap:
Fault></soap:Body></soap:Envelope>","headers":{"date":"Tue, 17 Nov 2015 12:15:17
GMT","server":"Apache/2.4.12 (Win64) OpenSSL/1.0.2a mod_jk/1.2.40","x-distribut
ed-by":"AHC","content-length":"388","connection":"close","content-type":"text/xm
l;charset=UTF-8"},"request":{"uri":{"protocol":"https:","slashes":true,"auth":nu
ll,"host":"staging.payu.co.za","port":443,"hostname":"staging.payu.co.za","hash"
:null,"search":null,"query":null,"pathname":"/service/PayUAPI","path":"/service/
PayUAPI","href":"https://staging.payu.co.za/service/PayUAPI"},"method":"POST","h
eaders":{"User-Agent":"loopback-connector-soap/2.3.0","Accept":"text/html,applic
ation/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8","Accept-Encoding":"non
e","Accept-Charset":"utf-8","Connection":"close","Host":"staging.payu.co.za","Co
ntent-Length":1128,"Content-Type":"text/xml; charset=utf-8","SOAPAction":"\"\""}
}}
events.js:141
Thanks
Upvotes: 1
Views: 1218
Reputation: 11
Setting the security in datasources.json works, but you probably don't want to save username and password there. There a couple of options: 1) You could use add a vairable which can be pulled from config.json and embed into datasources.json like so: "security": ${security}. And variable security is defined in config.env.json.
2) In a model, eg if you have a Product model, then you could use something like: Product.datasources.settings.security = {'scheme':'WS', 'username':'abc'....}
Upvotes: 1
Reputation: 300
I managed to resolve this by making use of the the connector's security option which creates the relevant SOAP Security header, provided that the relevant data is supplied.
security: {
scheme: 'WS',
username: "Staging Integration Store 3",
password: "WSAUFbw6",
passwordType: 'PasswordText'
},
XML conversion
<soap:Header>
<wsse:Security 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">
<wsu:Timestamp wsu:Id="Timestamp-2015-11-20T08:00:46Z">
<wsu:Created>2015-11-20T08:00:46Z</wsu:Created>
<wsu:Expires>2015-11-20T08:10:46Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-2015-11-20T08:00:46Z">
<wsse:Username>Staging Integration Store 3</wsse:Username>
<wsse:Password>WSAUFbw6</wsse:Password>
<wsu:Created>2015-11-20T08:00:46Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
Upvotes: 0