What's the best way to create an LDAP connection to an OpenLDAP server using ldapjs? - ldap

I'm getting an error when attempting to create a client connection to an OpenLDAP server. The error message isn't helpful. Am I missing something in the OpenLDAP setup or configuration?
function createLDAPClient () {
return new Promise(function (resolve, reject) {
if(client.connected) return resolve();
client = ldap.createClient({
url: 'ldap://localhost:389',
strictDN: false,
timeout: 10000,
connectTimeout: 10000
//disableQueue: true
});
client.on('connect', function () {
// console.log("LDAP connected");
resolve();
});
client.on('error', function (err) {
// console.log("ldap client error", err);
// idle timeout
if(err.code === 'ECONNRESET') {
return reject();
}
reject();
});
});
}
Getting error
{ InvalidDnSyntaxError: invalid DN
at messageCallback (D:\Sites\Hermes\opt\node_modules\ldapjs\lib\client\client.js:1419:45)
at Parser.onMessage (D:\Sites\Hermes\opt\node_modules\ldapjs\lib\client\client.js:1089:14)
at Parser.emit (events.js:198:13)
at Parser.write (D:\Sites\Hermes\opt\node_modules\ldapjs\lib\messages\parser.js:111:8)
at Socket.onData (D:\Sites\Hermes\opt\node_modules\ldapjs\lib\client\client.js:1076:22)
at Socket.emit (events.js:198:13)
at addChunk (_stream_readable.js:288:12)
at readableAddChunk (_stream_readable.js:269:11)
at Socket.Readable.push (_stream_readable.js:224:10)
at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17) lde_message: 'invalid DN', lde_dn: null
}

The problem was eluding me because I didn't see where the error was being thrown. The answer is to solve the username in the bind function shown here:
function bind (user) {
return new Promise(function (resolve, reject) {
return createLDAPClient()
.then(function () {
//console.log("client should be bound", !client.unbound);
// client.bind(user.username, user.password, function (err) {
// console.log("attempting bind", user);
var ldapuser = user.username;
if( config.ldap.type == 'OpenLDAP'){
ldapuser = 'cn=' + user.username + ',' + config.ldap.dc;
}
client.bind(ldapuser, user.password, function (err) {
//console.log("user bind callback, err:", !!err);
if(err) {
// console.log("error type", typeof err, Object.keys(err), err.stack);
console.error(err);
// bad password
if(err.stack.indexOf("InvalidCredentialsError") !== -1) {
console.log("bad password", user);
reject({
msg: 'Invalid credentials - 101'
});
}
reject({
msg: 'Error connecting to LDAP server',
error: err
});
}
resolve();
});
});
});
}

Related

Node JS emit socket after error in SQL query

**Hello, please do you know how can I send message to client via socket when I have error in my SQl query on server side ? **
Server side
io.on('connect', (socket) => {
console.log("User connected: " + socket.id);
socket.on('disconnet', () => {
console.log("disconnected");
})
.post('/addDiel', (req, res) => { //Pridanie dielu do DB
pool.getConnection((err, connection) => {
if(err) throw err
console.log(`Pripojene ako ID ${connection.threadId}`)
const params = req.body;
res.send({
MenoDielures: params.MenoDielu,
DruhDielures: params.DruhDielu,
ProjektNameres: params.ProjektName
})
ProjektNameDB = params.ProjektName.split('.').join("_");
connection.query('INSERT INTO `Skener_db`.`?` (`MenoDielu`, `DruhDielu`, `DatumCas`) VALUES (?, ?, NOW())', [ProjektNameDB, params.MenoDielu, params.DruhDielu],(err, rows)=> {
connection.release()
if(!err) {
res.send(console.log(`Hodnota ${params.MenoDielu} bola pridana.`))
} else {
console.log(err);
if (err.code == ('ER_DUP_ENTRY')) {
//send message to client
}
//res.send({alertMessage: 'Diel už bol oskenovaný. Oskenuj ďaľší.'})
}
})
console.log(req.body)
})
})
})
My client side:
socket.on('connect', () => {
$('#skuska').html("Socket pripojeny");
})
socket.on('receiveDUPmessage', message => {
$('#skuska').html(message);
})
The code here is just for example. I didnt find solution for my problem, so I'm asking here
You have to emit events and socket is locally scoped. io.sockets is not, So you can do it like this on the server-side:
if(!err) {
res.send(console.log(`Hodnota ${params.MenoDielu} bola pridana.`))
} else {
console.log(err);
if (err.code == ('ER_DUP_ENTRY')) {
//send message to client
io.sockets.emit('my error', 'Some error happened');
}
//res.send({alertMessage: 'Diel už bol oskenovaný. Oskenuj ďaľší.'})
}
And on the client-side do this:
socket.on('my error', function (text) {
console.log(text);
});
Here is some sort of posts that may help you:
How to emit error to be possible catch it on error handler on client-side?
How to emit a socket.io response within post request in NodeJS

Express passport.authenticate() not working properly

I'm having some issues with setting up passport. The information gets to the console.log(req.body) before passport.authenticate and then console.log(req.user) will return undefined afterwards. I will not hit the console.log inside of passport.use() function that is after the new LocalStrategy code. This does not though an error, nothing seems to happen. It will just enter the second if statement if(!user) and return me the status and error I outlined there. I have been trying to debug this for awhile and alas I'm no longer sure what the deal is.
this is what my auth file looks like
router.post("/login", (req, res, next) => {
console.log(req.body);
passport.authenticate("local", function (err, user, info) {
//console.log(req);
//console.log(user);
if (err) {
//console.log("cp1");
return res.status(400).json({ errors: err });
}
if (!user) {
return res.status(400).json({ errors: "No user found" });
}
req.logIn(user, function (err) {
console.log("cp1");
if (err) {
//console.log("cp3");
return res.status(400).json({ errors: err });
}
return res.status(200).json({ success: `logged in ${user.id}` });
});
})(req, res, next);
});
and this is what my passport.js file looks like
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(null, user);
});
});
passport.use(
new LocalStrategy((email, password, done) => {
console.log(`${email} , ${password}`);
db.User.findOne({ email: email })
.then((user) => {
if (!user) {
} else {
if (user.password === password) {
return done(null, user);
} else {
return done(null, false, { message: "Wrong Password" });
}
}
})
.catch((err) => {
return done(null, false, { message: err });
});
})
);
passport.initialize();
passport.session();
There is no such thing as req.user, I suppose you meant req.body.user or req.body.username depending on the JSON you send in the request.
I advice you to look at my repo below where I recently successfuly implemented Passport in Express:
https://github.com/fromb2b/saas

passing Tedious connection as parameter

I am trying to use a simple suite of functions built utilizing the Tedious library to access a Microsoft SQL Server. Here is my "tools" file:
'use strict';
const tedious = require('tedious');
const q = require('q');
var Connection = tedious.Connection;
var Request = tedious.Request;
module.exports = {
connectSQL : function(config) {
var connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
console.log('FAIL ON CONNECT');
console.log(err);
} else {
try {
/* ----- */
return connection;
} catch (err) {
console.log(err);
return;
}
}
});
connection.on('error', function(err) {
if (err) {
console.log('FAIL ON ERROR');
console.log(err);
} else {
console.log("Error called with no err object.");
}
});
},
executeSQL: function(connection, requestString) {
var results = [];
var request = new Request( requestString , function(err, data) {
if (err) {
console.log(err);
} else {
console.log( data );
}
});
request.on('row', function(row) {
//console.log(row);
results.push( row );
});
request.on('requestCompleted', function(){
console.log('Finished');
return results;
});
connection.execSql(request);
}
}
I call these functions as follows in my server file.
const sqlTools = require('./sqlTools.js');
var connection = sqlTools.connectSQL(config);
sqlTools.executeSQL(connection, "select * from dbo.test");
However, I get the error "TypeError: Cannot read property 'execSql' of undefined", even if I make the program sleep for 10 seconds before calling my function sqlTools.executeSQL (obviously not ideal).
I was able to get this to work by calling the request within the sqlTools.connectSQL function (at the "/* ----- */"), but I want to re-use the Tedious connection to make multiple calls. Any suggestions? Thanks!
~~~~~~~EDIT~~~~~~~~~~
With help from akinjide I was able to implement callbacks that allow me to make a single call to my SQL database. However, I am struggling to implement promises to make subsequent calls. I changed my "tools" file as such:
'use strict';
const tedious = require('tedious');
const q = require('q');
var Connection = tedious.Connection;
var Request = tedious.Request;
module.exports = {
connectSQL: function(config) {
var deferred = q.defer();
var connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
deferred.reject( err );
} else {
deferred.resolve( connection );
}
});
connection.on('error', function(err) {
deferred.reject(err);
});
return deferred.promise;
},
executeSQL: function(connection, requestString, callback) {
var results = [];
const request = new Request(requestString, function(err) {
callback(err);
});
request.on('row', function(row) {
results.push(row);
});
request.on('requestCompleted', function() {
console.log('request completed!');
callback(null, results);
});
connection.execSql(request);
}
}
and I call this code like this...
var promise = sqlTools.connectSQL(config);
promise.then(function (connection) {
sqlTools.executeSQL(connection, "select * from dbo.test", function(err, results) {
if (err) {
console.log(err);
}
console.log(results);
});
}).catch(function (err) {
console.log(err);
}).then(function (connection) {
sqlTools.executeSQL(connection, "select * from dbo.test2", function(err, results) {
if (err) {
console.log(err);
}
console.log(results);
});
}).catch(function(err) {
console.log(err);
});
This returns the first call's results correctly, but unfortunately returns this error "TypeError: Cannot read property 'execSql' of undefined" for the second call as it is not recognizing the connection the second time around. Any suggestions?
A better approach would be to pass a node.js callback style function as an argument to connectSQL.
return keyword won't work within an asynchronous program.
'use strict';
const tedious = require('tedious');
const Connection = tedious.Connection;
const Request = tedious.Request;
module.exports = {
connectSQL: function(config, callback) {
const connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
callback(err);
} else {
callback(null, connection);
}
});
connection.on('error', function (err) {
callback(err);
});
},
executeSQL: function(connection, requestString, callback) {
let results = [];
const request = new Request(requestString, function(err) {
callback(err);
});
request.on('row', function(row) {
results.push(row);
});
request.on('requestCompleted', function(){
console.log('Finished');
callback(null, results);
});
connection.execSql(request);
}
}
Then you can require, use sqlTools.connectSQL passing two parameters config and function(err, connection) {}
const sqlTools = require('./sqlTools');
sqlTools.connectSQL(config, function(err, connection) {
if (err) {
console.log('FAIL ON CONNECT');
console.log(err);
}
sqlTools.executeSQL(connection, "select * from dbo.test", function (err, results) {
if (err) {
console.log(err);
}
console.log(results);
});
});

Resetting password using express and JWT token

I am trying to reset the user password using the following code and Postman.
But what I realised is that there is no user after I generate the token. the console is saying null;
// Reset User Password
exports.resetPassword = function (req, res) {
User.findOne({
reset_password_token: req.body.token,
reset_password_expires: {
$gt: Date.now()
}
}).exec(function (err, user) {
console.log('this user: ' + user)
if (!err && user) {
if (req.body.newPassword === req.body.verifyPassword) {
user.hash_password = bcrypt.hashSync(req.body.newPassword, 10);
user.reset_password_token = undefined;
user.reset_password_expires = undefined;
user.save(function (err) {
if (err) {
return res.status(422).send({
message: err
});
} else {
console.log(user.hash_password)
}
});
} else {
return res.status(422).send({
message: 'Passwords do not match'
});
}
} else {
return res.status(400).send({
message: 'Password reset token is invalid or has expired.'
});
}
});
};
This is how I use it in Postman
{
"newPassword": "cocacola",
"verifyPassword": "cocacola",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YjI3NjAyNDAwOWI1NDA5ZjMwNzAzZWYiLCJpYXQiOjE1MzA5NjA2NDEwOTN9.1LjroayiTWDNevShnH30n3LxUGCrazmTaJlHgOUNvJ0"
}
and the response in Postman is message from status 400

Node js: mssql [ConnectionError: Connection is closed.] name: 'ConnectionError', message: 'Connection is closed.', code: 'ECONNCLOSED'

i am getting error in npm mssql 3.0.0 with sqlserver 2012
i am creating single page application where i used restful using express .
there are 4 method which executing the query and returning the data to response.
for each method i am opening the connection and closing the connection.
but when savedquery is calling then connection close error occurs.
each method code is similar to savedquery method (copy pasted code only queries are changed) but they are executing savedquery is not executing
{ [ConnectionError: Connection is closed.]
name: 'ConnectionError',
message: 'Connection is closed.',
code: 'ECONNCLOSED' }
var savedquery=function(req,res){
dbConfig= {
user: 'XXX',
password: 'XXXXXXXXXX',
server: 'localhost', // You can use 'localhost\\instance' to connect to named instance
database: 'DEMO_ODS',
options: {
encrypt: true
}
};
sql.connect(dbConfig).then(function (err) {
var sqlrequest = new sql.Request();
sqlrequest.query("SELECT * from SavedQuery").then(function (recordset) {
sql.close(function (value) {
console.log("connection6 closed");
});
return res.status(200).send(recordset);
}).catch(function (err) {
console.log(err);
});
}).catch(function (err) {
console.log(err);
});
};
}
I know it is an old questionm but this answer is for the others who are facing the same isue. I had the same problem, What I did is, used promises as below.
function getData() {
try {
sqlInstance.connect(setUp)
.then(function () {
// Function to retrieve all the data - Start
new sqlInstance.Request()
.query("select * from Course")
.then(function (dbData) {
if (dbData == null || dbData.length === 0)
return;
console.dir('All the courses');
console.dir(dbData);
})
.catch(function (error) {
console.dir(error);
});
// Function to retrieve all the data - End
// To retrieve specicfic data - Start
var value = 1;
new sqlInstance.Request()
.input("param", sqlInstance.Int, value)
.query("select * from Course where CourseID = #param")
.then(function (dbData) {
if (dbData == null || dbData.length === 0)
return;
console.dir('Course with ID = 1');
console.dir(dbData);
})
.catch(function (error) {
console.dir(error);
});
// To retrieve specicfic data - End
}).catch(function (error) {
console.dir(error);
});
} catch (error) {
console.dir(error);
}
}
This solved my issue. You can find the fix here.
You should remove
options: {
encrypt: true
}
from your dbConfig
I just use promise to handle concurrent request:
const executeQuery = function (res, query, dbName) {
dbConfig = {
user: "********",
password: "********",
server: "*******",
database: dbName
}
sql.connect(dbConfig).then(pool => {
return pool.request().query(query)
}).then(result => {
res.send(result);
}).catch(err => {
res.send(err);
});
}
Hope it's help someone.