signing SOAP XML using node-js using private key - web-services

Am trying to sign the XML using my private key, and using SOAP UI
it gives the proper success response.
to generate the request am using below code
var Authorization = 'Basic ' + new Buffer((sapConfig.sap.username + ':' + sapConfig.sap.password) || '').toString('base64');
soap.createClient(__dirname + '/wsdl/SI_CARWORKZ_Customer_Sen_Sync.wsdl', wsdlOptions, function (err, client) {
client.setSecurity(new soap.WSSecurityCert(privateKey, publicKey, password, 'utf8'));
//client.setSecurity(new soap.ClientSSLSecurity(privateKey, publicKey, ca));
client.SI_CARWORKZ_Customer_Sen_Sync(details, sslOptions, function(err, result, raw, soapHeader) {
console.log('%j', result);
if(_.has(result, "ResponseData") && !_.isEmpty(result.ResponseData.Item)){
var status = _.pluck(result.ResponseData.Item, "Status");
if(status.indexOf('E') != -1){
return callback({status: "error", data: result});
}else{
// insert the user in mongodb
sapLogs.insertCustomers(details.HEADER, function(result){
console.log("customer added");
return callback({status: "success", data: details});
})
}
}else{
return callback({status: "error", data: [], message: "something went wrong." })
}
}, {"Authorization": Authorization});
});
But when am sending the signed xml data using the script it shows me error
Error while valdiating the digital signature. The error was java.lang.NullPointerException while trying to invoke the method com.sap.security.core.ws.wss.tokens.securitytoken.BinarySecurityToken.getSecurityToken()
Is there any issue with my public key or private key?
I have exported them from jks file which is used in SOAP UI.

Related

How to fix "Error unmarshalling response back from AWS, Response Body: Unknown error" in x.io using Unity AWS SDK for DynamoDB

I developed DynamoDB Tables for my application using unity SDK. Authentication is done using Cognito identities. When trying to read/write values to a table it is working in my local machine. But when the application is hosted in x.io I get an error.
I am not able to figure out the issue. There are not many resources to debug this error.
public void PostUserAccountDetails(UserAccounts userInfo)
{
DbContext.LoadAsync<UserAccounts>(userInfo.mailID, (result) =>
{
if (result.Exception == null)
{
var user = result.Result as UserAccounts;
Debug.Log(user == null ? true : false);
if (user == null)
{
Debug.Log("mail id is new");
signupText.text = "The mail id has never been used before";
DbContext.SaveAsync<UserAccounts>(userInfo, (res) =>
{
if (res.Exception == null)
{
Debug.Log("signed up successfully");
signupText.text = "signed up successfully";
}
else
{
Debug.Log("error while signing up");
signupText.text = "error while signing up";
}
});
}
else
{
Debug.Log("This mail id has already been used");
signupText.text = "This mail id has already been used";
}
}
else
{
Debug.Log(result.Exception.Message);
signupText.text = result.Exception.Message;
}
});
}
I get the error message
"Error unmarshalling response back from AWS, Response Body: Unknown error"

AWS lambda - how to use conditionals depending on if query parameters exist?

I want my function to return a list of everything in a table if there are no query parameters, and a single row if the parameter id exists
var mysql = require('mysql');
var config = require('./config.json');
var pool = mysql.createPool({
host : config.host,
user : config.user,
password : config.password,
database : config.database
});
exports.handler = (event, context, callback) => {
var whereClause
if(event.queryStringParameters.id !== null){
let id = event.queryStringParameters.id
whereClause = ' where id='+id
}
context.callbackWaitsForEmptyEventLoop = false;
pool.getConnection(function(err, connection) {
// Use the connection
connection.query('SELECT * from users'+whereClause, function (error, results, fields) {
// And done with the connection.
connection.release();
// Handle error after the release.
if (err) callback(err);
else {
var response = {
"statusCode": 200,
"headers": {
"my_header": "my_value"
},
"body": JSON.stringify(results),
"isBase64Encoded": false
};
callback(null, response);
}
});
});
};
the function fails when no query parameter is present with the error
"Cannot read property 'id' of null"
why is that?
You didn't supply any line number information or a stack trace, so I'm guessing this if statement fails because event.queryStringParameters is null:
if(event.queryStringParameters.id !== null)
let id = event.queryStringParameters.id
whereClause = ' where id='+id
}
And you should instead write:
if (event.queryStringParameters && event.queryStringParameters.id !== null) {
let id = event.queryStringParameters.id;
whereClause = ' where id=' + id;
}
Having said that, you should not inject user-supplied values (such as id) into SQL queries using string concatenation. This opens you up to a SQL Injection attack. Here are ideas for how to write this code more safely: How to prevent SQL Injection in Node.js
Do you use AWS Lambda with Amazon API Gateway?
AWS Lambda with Amazon API Gateway
In this case:
Make sure that you create a body mapping template in API gateway (Integration Request->Body Mapping Templates). As an example here's a body mapping template that would pass along the query parameter email to your lambda function: { "id": "$input.params('id')" }
AWS Developer Forum

How to get PowerBI accesstoken using ADAL.JS

I'm trying to use ADAL.js to authenticate against PowerBI in order to get an access_token and the embed_token needed to embed PowerBI reports/dashboards/tiles in a html/javascript-only "webpart". My adal-config looks like:
config = {
instance: 'https://login.windows.net/common/oauth2/authorize/',
tenant: 'tenant.onmicrosoft.com',
clientId: '05xxxxx-xxx-xxxx-xxxx-xxxxxxxxxxxx',
loginResource: "https://analysis.windows.net/powerbi/api",
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage',
};
But I can't seem to find any access-token etc in the user.profile I get. I am obviously missing something but what.. :) Any help would be much appriciated
Looking at:
https://community.powerbi.com/t5/Developer/get-Access-token-using-js/m-p/350294
and also this:
https://community.powerbi.com/t5/Developer/How-to-Generate-Embed-Token-in-pure-JavaScript/td-p/350056
you can use ADAL.js to get the access token itself
window.config = {
instance: 'https://login.microsoftonline.com/',
tenant: 'common', //COMMON OR YOUR TENANT ID
clientId: 'XXXXX', //This is your client ID
redirectUri: 'XXXXXX', //This is your redirect URI
callback: userSignedIn,
popUp: true
};
var ADAL = new AuthenticationContext(config);
function signIn() {
ADAL.login();
}
function userSignedIn(err, token) {
console.log('userSignedIn called');
if (!err) {
showWelcomeMessage();
ADAL.acquireToken("https://analysis.windows.net/powerbi/api", function (error, token) {
// Handle ADAL Error
if (error || !token) {
printErrorMessage('ADAL Error Occurred: ' + error);
return;
}
}

Error with AWS Lambda salt and hash

I've been using source code from AWS Lambda in Action - Poccia, to create users in a User Pool and Identity Pool. I keep getting the error:
Response:
{
"errorMessage": "RequestId: f6511085-f22c-11e7-be27-534dfc5d6456 Process exited before completing request"
}
Request ID:
"f6511085-f22c-11e7-be27-534dfc5d6456"
Function Logs:
START RequestId: f6511085-f22c-11e7-be27-534dfc5d6456 Version: $LATEST
2018-01-05T15:27:38.890Z f6511085-f22c-11e7-be27-534dfc5d6456 TypeError: Pass phrase must be a buffer
at TypeError (native)
at pbkdf2 (crypto.js:576:20)
at Object.exports.pbkdf2 (crypto.js:558:10)
at computeHash (/var/task/lib/cryptoUtils.js:10:10)
at InternalFieldObject.ondone (/var/task/lib/cryptoUtils.js:19:4)
END RequestId: f6511085-f22c-11e7-be27-534dfc5d6456
REPORT RequestId: f6511085-f22c-11e7-be27-534dfc5d6456 Duration: 113.62 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 33 MB
RequestId: f6511085-f22c-11e7-be27-534dfc5d6456 Process exited before completing request
I'm new to AWS Services and am not sure why this error is occurring. Below is the Lambda function I'm attempting to use and following is the cryptoUtils.js script it's referencing.
console.log('Loading function');
//Loading standard module, such as crypto and the AWS SDK
var AWS = require('aws-sdk');
var crypto = require('crypto');
var cryptoUtils = require('./lib/cryptoUtils.js'); //Loading the cryptoUtils.js module shared code, included in the uploaded ZIP archive
var config = require('./config.json'); //Loading the configuration in the config.json file, included in the uploaded ZIP archive
var dynamodb = new AWS.DynamoDB({
accessKeyId: 'usingKEYfromIAM',
secretAccessKey: 'usingKEYfromIAM',
}); //Getting the Amazon DynamoDB service object
var ses = new AWS.SES(); //Getting Amazon SES service object
function storeUser(email, password, salt, fn) { //The storeUser() function stores the new user in the DynamoDB table.
var len = 128;
crypto.randomBytes(len, function(err, token) { //Arandom token sent in the validation email and used to validate a user
if (err) return fn(err);
token = token.toString('hex');
dynamodb.putItem({ //Putting an item in the DynamoDB table
TableName: config.DDB_TABLE, //The table name is taken from the config.json configuration file.
//Most of the data is string ("S"), but the verifiede attribute is Boollean ("BOOL"),
//new users aren't verified (false), and the randomly generated token is stored in the "verifyToken" attribute
Item: {
email: {
S: email
},
passwordHash: {
S: password
},
passwordSalt: {
S: salt
},
verified: {
BOOL: false
},
verifyToken: {
S: token
}
},
ConditionExpression: 'attribute_not_exists (email)' //This condition avoids overwriting existing users (with the same email).
}, function(err, data) {
if (err) return fn(err);
else fn(null, token); //The storeUser() function returns the randomly generated token.
});
});
}
function sendVerificationEmail(email, token, fn) { //The send-VerificationEmail() funciton sends the verification email to the new user.
var subject = 'Verification Email for ' + config.EXTERNAL_NAME;
//The verification link, to the verify.hrml page, passes the randomly generated token as a query parameter.
var verificationLink = config.VERIFICATION_PAGE + '?email=' + encodeURIComponent(email) + '&verify=' + token;
ses.sendEmail({ //Sending the email in HTML format
Source: config.EMAIL_SOURCE,
Destination: {
ToAddresses: [
email
]
},
Message: {
Subject: {
Data: subject
},
Body: {
Html: {
Data: '<html><head>' + '<meta http-equiv= "Content-Type" content="test/html; charset=UTF-8" />' +
'<title>' + subject + '</title>' + '</head><body>' + 'Please <a href="' + verificationLink +
'">click here to verify your email address</a> or a copy & paste the following link in a browser:' +
'<br><br>' + '' + verificationLink + '' + '</body></html>'
}
}
}
}, fn);
}
exports.handler = (event, context, callback) => { //The function that's exported and can be invoked using AWS Lambda as createUser
//Getting the input parameters (email, password) from the event
var email = event.email;
var clearPassword = event.password;
//Using compute-Hash() from cryptoUtils.js to salt the password.
cryptoUtils.computeHash(clearPassword, function(err, salt, hash) {
if (err) {
callback('Error in hash: ' + err);
} else {
storeUser(email, hash, salt, function(err, token) { //Storing the user via the storeUser()function
if (err) {
if (err.code == 'ConditionalCheckFailedException') { //Checking if the database error is due to the email being already prsent in the database
//userID already found
callback(null, {
created: false
});
} else {
callback('Error in storUser: ' + err);
}
} else {
sendVerificationEmail(email, token, function(err, data) { //Sending the verification email
if (err) {
callback('Error in sendVerificationEmail: ' + err);
} else {
callback(null, {
created: true
});
}
});
}
});
}
});
};
var crypto = require('crypto');
function computeHash(password, salt, fn) {
var len = 512;
var iterations = 4096;
var digest = 'sha512';
if (3 == arguments.length) {
crypto.pbkdf2(password, salt, iterations, len, digest, function(err, derivedKey) {
if (err) return fn(err);
else fn(null, salt, derivedKey.toString('base64'));
});
} else {
fn = salt;
crypto.randomBytes(len, function(err, solat) {
if (err) return fn(err);
salt = salt.toString('base64');
computeHash(password, salt, fn);
});
}
}
module.exports.computeHash = computeHash;
If anybody has any suggestions or needs more information to help me determine why the error is occurring I would greatly appreciate it. Thank you.
The password you're passing is a number?
If so:
Convert it to String.
If you don't want to do that, you can pass a Buffer object:
Pass a Buffer object using the class Method Buffer.from(string[, encoding])
https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_string_encoding
crypto.pbkdf2(Buffer.from(password, 'utf8'), salt, iterations, len, digest, function(err, derivedKey) {
if (err) return fn(err);
else fn(null, salt, derivedKey.toString('base64'));
});
Hope it helps!
var crypto = require('crypto');
function computeHash(password, salt, fn) {
// Bytesize. The larger the numbers, the better the security, but the longer it will take to complete
var len = 512;
var iterations = 4096;
var digest = 'sha512';
if (3 == arguments.length) {
crypto.pbkdf2(Buffer.from(password, 'utf8'), salt, iterations, len, digest, function(err, derivedKey) {
if (err) return fn(err);
else fn(null, salt, derivedKey.toString('base64'));
});
} else {
fn = salt;
crypto.randomBytes(len, function(err, salt) {
if (err) return fn(err);
salt = salt.toString('base64');
computeHash(password, salt, fn);
});
}
}
module.exports.computeHash = computeHash;
Error "TypeError: Pass phrase must be a buffer"
does suggest trying a Buffer conversion of input String
Before your test of Buffer.from(password, 'utf8')
did you verify input value is encoding 'utf8',
and not some other encoding such as base64 or latin1 ?
List of encodings that Node.js supports

Getting error: "Unexpected wrapper element found" when trying to call a webservice function where webservice uses WSSecurityCert

I am using meteor.js. I am trying to call a function of a webservice that uses WSSecurityCert.
I created a signed key pair using openssl and sent the public key to the sever administrator so that they include it in their keystore, which they say they did. They also sent me their public key but I don't know where to include it in my code or application.
My code is as follows:
if (Meteor.isServer) {
Meteor.methods({
getVouchers: function(){
var fs = Npm.require('fs');
var soap = Npm.require('soap');
Npm.require('ursa');
var base = process.env.PWD;
var publicKey = fs.readFileSync(base + "/cert.pem", "utf8");
var privateKey = fs.readFileSync(base + "/key.pem", "utf8");
var password = "myPassPhrase";
var url = 'http://www.smartcallesb.co.za:8091/SmartcallServices2/SmartloadService?wsdl';
try
{
var wsSecurity = new soap.WSSecurityCert(privateKey, publicKey, password, 'utf8');
var client = Soap.createClient(url);
client.setSecurity(wsSecurity);
//var result = client.SmartloadService.SmartloadServicePort.getDealerBalance(); //getAllNetworks
var result = client.getDealerBalance();
console.log(result)
}
catch (err)
{
console.log(err)
}
console.log("reached end")
}
});}
When it is run I get the following error:
{ [Error: Soap method call failed [soap-method]]
error: 'soap-method',
reason: 'Soap method call failed',
reason: 'Soap method call failed',
details:
{ [Error: soap:Client: Unexpected wrapper element getDealerBalance found.
Expected {http://www.smartcall.co.za/2010/12/service}getDealerBalance.]
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy requirement
/200702}AsymmetricBinding: The transform algorithms do not match the
requirement.....
Could this be because the host public key that the server admin sent to me is not included in my application, and if so where do I include it? Or otherwise, how do I fix/correct this?