Node soap, consume password protected WSDL - node.js

I'm trying to build a SOAP client with Node, I'm using "soap" package (https://www.npmjs.org/package/soap) trying to consume a user/password protected WSDL.
I can't find how to pass those credentials before creating the client by "soap.createClient", and of course, I can't retrieve the WSDL if I don't provide the right credentials.
I've tried doing:
soap.security.WSSecurity('user', 'pass');
and then calling "createClient" but to no avail.
Also, I've tried to do it with the node-soap-client, with this client I (apparently) can connect to the WSDL, but after that, I've no idea where to go (how to invoke methods).
What am I doing wrong?
Thanks for all your help!

Username and password credentials can be passed like this:
var soap = require('soap');
var url = 'your WSDL url';
var auth = "Basic " + new Buffer("your username" + ":" + "your password").toString("base64");
soap.createClient(url, { wsdl_headers: {Authorization: auth} }, function(err, client) {
});
(derived from https://github.com/vpulim/node-soap/issues/56, thank you Gabriel Lucena https://github.com/glucena)

If its password protected you also need to check the correct security mechanism. I spend a day trying to figure out that the service used NTLM security(it was a clients project and I only got username and password to access the wsdl). In that case, you would need to pass the correct wsdl_options object
var wsdl_options = {
ntlm: true,
username: "your username",
password: "your password",
domain: "domain",
workstation: "workstation"
}
soap.createClient(data.credentials[data.type], {
wsdl_options
},
function(err, client) {
console.log(client.describe());
});
Also, you would need to setSecurity on the client before using any service.
the link to complete explanation: https://codecalls.com/2020/05/17/using-soap-with-node-js/

when I added the auth to the headers I still had a problem. After reading the code and a number of articles I found this to work.
// or use local wsdl if security required
let url = 'http://service.asmx?wsdl'
let wsdl = 'wsdl.wsdl';
let soap = require('soap');
let util = require('util')
soap.createClient(wsdl, function(err, client) {
//don't forget to double slash the string or else the base64 will be incorrect
client.setSecurity(new soap.BasicAuthSecurity('admin\\userName', 'password'));
client.MethodFromWSDL(args, function (err, result) {
console.log(util.inspect(result,{depth: null}))
});
});

This worked for me, the API required the auth parameters as
<UserDetails xmlns="http://url/">';
<userName>{$Username}</userName>
<password>{$Password}</password>
<program>{$program}</program>
</UserDetails>
After lots of trial and error - this ended working
const soapHeader = {
UserDetails: {
userName: process.env.userName,
password: process.env.password,
program: process.env.program
}
}
...
soap.createClient(path, function (err, client) {
if (err) {
console.log('Error creating SOAP client: ' + err);
}
client.addSoapHeader(soapHeader, "", "tns", process.env.URN);
client[process.env.FUNCTION](sargs, function (err, result, rawResponse, soapHeader, rawRequest) {
if (err) {
console.log('Error call SOAP function ' + process.env.FUNCTION + ': ', err);
}
else {
console.log(result);
}
...

Related

LDAP get full name and email nodejs

I am writing app in node js. For login I would like use active directory. I found this package. Authentication is ok, but I cannot get user full name and email. There is my code:
var ActiveDirectory = require('activedirectory2');
var ActiveDirectory = require('activedirectory2');
var _ = require('underscore');
var query = 'cn=*Exchange*';
var opts = {
includeMembership : [ 'all' ],
includeDeleted : false
};
var config = {
url: 'ldap://dc.in.domain.cz',
baseDN: 'CN=Users,DC=in,DC=domain,DC=cz',
bindDN: 'CN=searchuser,CN=users,DC=in,DC=domain,DC=cz'
};
var ad = new ActiveDirectory(config);
var username = 'username #in.domain.cz';
var password = 'my_password';
ad.authenticate(username, password, function (err, auth) {
if (auth) {
console.log('Authenticated!');
ad.find(query, function (err, results) {
if ((err) || (!results)) {
console.log('ERROR: ' + JSON.stringify(err));
return;
}
console.log('Users');
_.each(results.users, function (user) {
console.log(' ' + user.cn);
});
});
} else {
console.log('Authentication failed!');
}
});
I get error:
ERROR: {"lde_message":"000004DC: LdapErr: DSID-0C0907C2, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v2580\u0000","lde_dn":null}
Thank you
The authenticate function is just used for testing if credentials are valid. You would use this if, for example, you have a login page and you want to see if the credentials the user gave you are correct. These credentials are not used for the other operations.
In the documentation, it says under the Usage heading:
The username and password specified in the configuration are what are used for user and group lookup operations.
So when you use find(), it's using the credentials you put in config. You have bindDN there, but you don't have password, which is likely why the bind failed. You will need to add the password for that "searchuser" account:
var config = {
url: 'ldap://dc.in.domain.cz',
baseDN: 'CN=Users,DC=in,DC=domain,DC=cz',
bindDN: 'CN=searchuser,CN=users,DC=in,DC=domain,DC=cz',
password: 'something'
};
Note that the docs say that you can also use the username property instead of bindDN, but don't think there is any functional difference except being able to just specify the username and not the whole DN:
var config = {
url: 'ldap://dc.in.domain.cz',
baseDN: 'CN=Users,DC=in,DC=domain,DC=cz',
username: 'searchuser#in.domain.cz',
password: 'something'
};

AWS Cognito Node.JS User Authentication returns unknown problem

I'm using AWS Cognito with Node.JS.
I'm successfully registering and verifying users, but the Authentication is returning "unknown error, the response body from fetch is undefined."
I'm using node-fetch module along with amazon-cognito-identity-js (set as var AWSCognito on code below). User is not in a state of requiring password change and verified.
Have others experienced this and how did you resolve the issue?
Appreciate any guidance in advance....
Here's my code, my complete module is on npm as iditawsutils :
exports.authCognitoUser = function(theUserPoolID, theClientID, userName, userPassword) {
var authenticationData = {
Username : userName,
Password : userPassword
};
var authenticationDetails = new AWSCognito.AuthenticationDetails(authenticationData);
var poolData = { UserPoolId : theUserPoolID,
ClientId : theClientID
};
var userPool = new AWSCognito.CognitoUserPool(poolData);
var userData = {
Username : userName,
Pool : userPool
};
console.log('authentication details: ',authenticationDetails);
var cognitoUser = new AWSCognito.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
console.log('id token + ' + result.getIdToken().getJwtToken());
console.log('refresh token + ' + result.getRefreshToken().getToken());
return result;
},
onFailure: function(err) {
console.log(err.message || JSON.stringify(err));
return err;
},
});
}
//from the console log:
authentication details: AuthenticationDetails {
validationData: {},
authParameters: {},
username: 'thesmarterstuff',
password: 'passW0rd!’ }
Unknown error, the response body from fetch is: undefined
Use the following in your onFailure block to find more details about the error.
onFailure: function(err) {
console.log(new Error().stack);
console.log(err.message || JSON.stringify(err));
},
If you find the error occurring in your fetch line in Client.js, then this could be because currently NodeJS SDK, and most other SDKs do not support the default USER_SRP_AUTH.
You could check by adding a console.log in the Client.js
console.log(this.endpoint);
console.log(options);
Login to your AWS account, and make sure you have checked the option - Enable username-password (non-SRP) flow for app-based authentication (USER_PASSWORD_AUTH)
Then, in your code update it with the following setting.
cognitoUser.setAuthenticationFlowType('USER_PASSWORD_AUTH');

Consuming DynamicsNAV WebService with Node.JS node-soap

I want to consume the WebService from Microsoft Dynamics NAV 2009 with a small node.js application. The Service itself works fine, I am using it with a c# application, now I want to get data into my nodejs/expressjs application but, I always get Invalid WSDL URL as an error message.
Here is the WSDL as my Browser sees it.
Now I tried to connect with node-soap, following the documentation, by normal and by basic auth, but everytime I get an Invalid WSDL URL error.
Here are the methods I tried for a test connection:
var url = "http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDCETA";
var auth = "Basic " + new Buffer("*********" + ":" + ****************").toString("base64");
soap.createClient(url, function(err, client) {
console.log('Without basic out:');
if (err)
{
console.log('[ERROR] -> ');
console.log(err);
}
console.log(client);
});
soap.createClient(url, {wsdl_headers: {Authorization: auth} }, function(err, client) {
console.log('With basic out:');
if (err)
{
console.log('[ERROR] -> ');
console.log(err);
}
console.log(client);
});
And this is the response I get:
Without basic out:
[ERROR] ->
[Error: Invalid WSDL URL: http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDDCETA
Code: 401
Response Body: ]
undefined
With basic out:
[ERROR] ->
[Error: Invalid WSDL URL: http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDDCETA
Code: 401
Response Body: ]
undefined
As it turned out, the build in HTTP-Server from DyanmicsNAV requires SPNEGO or NTLM as authentication. After some tries creating a proper SPNEGO request with nodejs/node-soap I turned off SPNEGO and enabled NTLM.
With the help of soap-ntlm and httpntlm I could retrieve the wsdl.
This is some testing code how I could manage to retrieve the WSDL file. For now I am happy, but I guess when it comes to invoke function there will be some other issues :)
var soap = require('soap-ntlm');
var fs = require('fs');
var httpntlm = require('httpntlm');
var url = 'http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDCETA';
var username = '*******';
var password = '***********';
httpntlm.get({
url: url,
password: password,
username: username
}, function(err, wsdl) {
if (err)
{
console.log('ERR: -> ');
console.log(err);
return;
}
fs.writeFile('wsdl_cache/WDCETA.wsdl', wsdl.body, function() {
soap.createClient(__dirname + '/wsdl_cache/WDCETA.wsdl', function(err, client) {
if (err) {
console.log('SOAP ERR: ->');
console.log(err);
return;
}
client.setSecurity(new soap.NtlmSecurity(username, password));
console.log(client);
});
})
});

Setting Authorization in Node.js SOAP Client

I want to access a WSDL service through SOAP Client in Node.js. I used soap node module. But I can't able to find any documentation to set username and password. I'm not going to create SOAP server, I just want SOAPClient which is similar to PHP's SoapClient, using which I should able to access the WSDL service.
Update:
I had forked and customised the source to support this feature https://github.com/sincerekamal/node-soap
You can provide username and password like this:
var soap = require('soap');
var url = 'your WSDL url';
var auth = "Basic " + new Buffer("your username" + ":" + "your password").toString("base64");
soap.createClient(url, { wsdl_headers: {Authorization: auth} }, function(err, client) {
});
(derived from https://github.com/vpulim/node-soap/issues/56, thank you Gabriel Lucena https://github.com/glucena)
Another option to add basic authentication is using client.addHttpHeader. I tried both setSecurity and setting wsdl_headers but neither worked for me when authenticating to Cisco CUCM AXL.
Here is what worked for me:
var soap = require('soap');
var url = 'AXLAPI.wsdl'; // Download this file and xsd files from cucm admin page
var auth = "Basic " + new Buffer("your username" + ":" + "your password").toString("base64");
soap.createClient(url,function(err,client){
client.addHttpHeader('Authorization',auth);
});
Just to share what I've read from https://github.com/vpulim/node-soap:
var soap = require('soap');
var url = 'your WSDL url';
soap.createClient(url, function(err, client) {
client.setSecurity(new soap.BasicAuthSecurity('your username','your password'));
});
You need to set the username and password by passing the authorisation to the wsdl_headers object e.g
var auth = "Basic " + new Buffer('username' + ':' + 'password').toString("base64");
var client = Soap.createClient('wsdlUrl', { wsdl_headers: { Authorization: auth } }, (err, client) => {
if (err) {
throw err;
} else {
client.yourMethod();
}
});
A small tweak to the existing answers: you can use your security object to create the header for the WSDL request too, e.g.
const security = new soap.BasicAuthSecurity(username, password);
const wsdl_headers = {};
security.addHeaders(wsdl_headers);
soap.createClientAsync(url, { wsdl_headers }).then((err, client) => {
client.setSecurity(security);
// etc.
});
Or if you're using something more complicated than BasicAuthSecurity you may also need to set wsdl_options from the security object, e.g.
const security = new soap.NTLMSecurity(username, password, domain, workstation);
const wsdl_headers = {}, wsdl_options = {};
security.addHeaders(wsdl_headers);
security.addOptions(wsdl_options);
soap.createClientAsync(url, { wsdl_headers, wsdl_options }).then((err, client) => {
client.setSecurity(security);
// etc.
});

how to set headers using node-soap in node.js

I am trying to consume a wsdl service and found node-soap, but I cannot find how to set some headers.
Example :
header = {
"Username": "foo",
"Password" : "bar"
}
The reason I need this is because the wsdl I am trying to consume requires the username and password via the headers.
Thanks in advance
It may not be useful now however inorder to answering this question which is still open, here it goes.
You can make use of the method Client.addSoapHeader. As per the documentation
Client.addSoapHeader(soapHeader[, name, namespace, xmlns]) - add
soapHeader to soap:Header node
Options
soapHeader Object({rootName: {name: "value"}}) or strict xml-string
Optional parameters when first arg is object :
name Unknown parameter (it could just a empty string)
namespace prefix of xml namespace
xmlns URI
So you need to create an object and pass that to this method like:
var soapHeader = {
"Username": "foo",
"Password" : "bar"
};
client.addSoapHeader(soapHeader);
According with the documentation , for aggregate HTTP Headers, you can put headers, example code:
soap.createClient(url,
function (err, client) {
if(err){
console.log(err);
} else{
console.log(client.describe())
var soapHeaders = {
'Channel':'PB',
'RqUID':'1987'
}
client.addHttpHeader('<nameH1>', 'valueH1');
client.addHttpHeader('<nameH2>', 'valueH2');
//then, continue calling the soap operation
}
Reading through the README for node-soap, if what you're trying to do is not WS-Security (I have no idea because I stay far away from SOAP), then you're going to have to file an issue with the author, because I see no way to set custom headers according to the documentation.
If it is WS-Security, then follow the instructions on this part of the README.
soap = require('soap')
parseString = require('xml2js').parseString
soap.createClient('https://api.bingads.microsoft.com/Api/Advertiser/AdIntelligence/v9/AdIntelligenceService.svc?wsdl', function(err, client) {
var soapHeader = {
'AuthenticationToken': process.argv[2],
'DeveloperToken': process.argv[3],
'CustomerId': process.argv[4],
'CustomerAccountId': process.argv[5]
};
client.addSoapHeader(soapHeader);
client.SuggestKeywordsFromExistingKeywords({Keywords: ["Hello world"]}, function(err, result) {
console.log(result.body);
});
});
This won't work. The reply is invalid login credentials. The same credentials work fine with SOAPUI. So, the format of sending the login credentials mentioned in the other answers must be wrong.
This worked for me. The create client method needs the wsdl_header to retrieve the wsdl definition. Once it is created, you need to set the basic auth security.
var url = 'your WSDL url';
var auth = "Basic " + new Buffer("username" + ":" + "password").toString("base64");
soap.createClient( url,{ wsdl_headers: {Authorization: auth} }).then(
function(client){
client.setSecurity(new soap.BasicAuthSecurity('rflhconfort_ws', '6syqxje9'));
client.your_Method(args);
}
I had the same issue and i resolved it in the below is what worked for me
My wsdl with which i inserted data using SOAPUI Client(To see what are the fields required)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:yourUrn">
<soapenv:Header>
<urn:AuthenticationMethod>
<urn:userName>username</urn:userName>
<urn:password>password</urn:password>
</urn:AuthenticationMethod>
</soapenv:Header>
<soapenv:Body>
<urn:SoapFunctionToCall>
<urn:Field1>Text</urn:Field1>
<urn:Field2>Text</urn:Field2>
<urn:Field3>Text</urn:Field3>
<urn:Field14>Text</urn:Field4>
<urn:Field5>Text</urn:Field5>
<urn:Field6>Text</urn:Field6>
</urn:SoapFunctionToCall>
</soapenv:Body>
</soapenv:Envelope>
Below is the method i called in node
function createSoapEntry(){
let url = "your wsdl url"
var credentials = {
AuthenticationMethod:{
userName: "username",
password: "password"
}
}
let args = {
Field1:"Text",
Field2:"Text",
Field3:"Text",
Field4:"Text",
Field5:"Text",
Field6:"Text"
}
soap.createClient(url, function (err, client){
client.addSoapHeader(credentials)
client.SoapFunctionToCall(args, function (err, res) {
if (err) {
console.log("Error is ----->" + err)
} else {
console.log("Response is -----> " + res)
}
})
})
}

Resources