I am using session.socket.io in my node.js application. I am using this to manage my sessions in socket functions.
sessionSockets.on('connection', function (err, socket, session) {
session.save(); //here its working
socket.on('check_username',function(username) {
if(username in clients) {
socket.emit('error', 'Username not available');
} else {
clients[username] = session.id;
session.sockets.push(socket.id);
session = { 'username': username };
session.save();
socket.emit('success', 'Welcome to chat');
}
});
My problem is I can access and update session values before the check_username function but I can't access it with in the check_username function. I don't know how to resolve this...
I got the issue. The below line overwrites all previous values in session variable.
session = { 'username': username };
So then i have changed this line to below. Then its working
session.username - username;
Related
I have created an authentication service using the following code in Node.js and ldapjs.
var when = require ('when');
var AuthenticationError = require('../errors/AuthenticationError');
var SessionManagerService = require('./SessionManagerService');
var ldap = require('ldapjs');
var client = ldap.createClient({
url: 'ldaps://ad.mycompany.com:636',
tlsOptions: {'rejectUnauthorized': false}
});
module.exports = {
signIn: function (email, password) {
return this.ldapBind(email, password).then(
function () {
return SessionManagerService.createSessionHash({email: email});
}
);
},
ldapBind: function (email, password) {
var deferred = when.defer();
client.bind(email, password, function(err) {
if (err) {
deferred.reject (new AuthenticationError('Invalid username and/or password!', 'Authentication.signIn.error'));
} else {
client.unbind();
deferred.resolve(true);
}
});
return deferred.promise;
},
};
When I authenticate my user for the first time, it works perfectly but it fails starting from the second attempt.
The error message is: 'write after end'.
When I restart the node server it works again for the first attempt.
It looks like something is hanging but I don't know what. Any idea?
I solved this problem a few days ago for creating ldap-client every time in ldapBind function (in your case).
The session variable is created when user logs in to the system. Then I load session variable in my authorization code. I want to destroy that variable when user logs out. Here is some simplified code
store = new express.session.MemoryStore();
var parseCookie = express.cookieParser('secret');
app.use(parseCookie);
app.use(express.session({store: store, key:'sid'}));
app.post('/login', function(req,res){
var post = req.body;
if (post.user == 'hugo' && post.password == '123')
{
req.session.user_name = post.user;
res.redirect('/mypage');
}
else res.send('wrong user or pass');
});
io.set('authorization', function (data, callback) {
parseCookie(data, {}, function(prserr) {
var sess = (data.secureCookies && data.secureCookies['sid']);
store.load(sess, function(err, session){
if (err || !session ) { callback('not logged in', false); }
else {
data.session = session; // save session
callback(null, true);
}
});
});
});
and finally
app.get('/logout', function (req, res) {
req.session.destroy();
/* Here I want to destroy session variable that is declared in
authorization code (see above: data.session = session )*/
res.redirect('/');
});
while destroying session via req.session.destroy() the variable
socket.handshake.session.user_name still exists. I want to destroy it too. But I have no idea how to access desired variable in above mentioned place (in logout code).
Have you considered using Passport? It might be quicker (and more efficient) than trying to roll your own authentication solution.
I'm writing a nodejs server that combine a login function and real-time chat. The problem came when I try to get all the users that logged in and connected with my real-time chat server then return to the client (so they can choose a specific user to chat with).
This is my code for log in function. I declared a variable so when client request the /doLogin, the username will be stored in it
var userLogged = {name: null, socketid: null};
app.post('/doLogin', function(req,res){
db.users.findOne({username: req.body.username}, function(err, user) {
if( err ) {
console.log("Login fail");
}
else if (user != null) {
if (req.body.password == user.password) {
req.session.user_role = "user";
userLogged.name = req.body.username;
} else {
req.session.user_role = "null";
}
}
res.send({redirect: "/"});
});
});
And in real-time chat function (using Socket.io), when user connect (after logged in), I will store the socket.id into the variable before, and save that variable in mongodb.
io.sockets.on('connection', function(socket){
var address = socket.handshake.address;
userLogged.socketid = socket.id;
db.clientList.save({name: userLogged.name, socketid: userLogged.socketid}, function(err, saved){
});
console.log("Connection " + address.address + " accepted.");
//
//
socket.on('disconnect', function(){
db.clientList.remove({socketid: userLogged.socketid});
});
});
And the problem is, when other users log in, the variable change so I cannot save the right information in to database.
Please help me!
socket.io allow you to read cookies:
// app.js
io = io.listen(server);
io.set('authorization', function (handshakeData, accept) {
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
});
the right way to do is:
cookies --> sessionID --> user --> username
document: http://howtonode.org/socket-io-auth
More simple:
if security is not important to you, you can set username to cookie, then you read username in easily in server: cookies->username
// login handler
res.cookie('username', username)
res.send({redirect: "/"});
// io connection handler
io = io.listen(server);
io.set('authorization', function (handshakeData, accept) {
console.log(handshakeData.headers.cookie)
}
note that, any web user can change their own cookie to fake your name, so this is for test, you should NOT use this for production.
I've got a working node app where I need to connect to different DBs based on what user is connecting to the app via basicAuth.
Here's a sample:
// Authenticating function
var sgAuth = express.basicAuth(function(user, pass, callback){
if(config.credentials.clients[user] === undefined) {
callback(null, false);
} else {
callback(null, config.credentials.clients[user].password == pass);
}
});
// This function needs to know what user has authenticated
function putEvents(req, res) {
//How do I know what user authenticated in this request?
var authUser = ???;
var table = getUserTable(authUser);
...
}
app.post('/put', sgAuth, putEvents);
Storing username in sgAuth to some var surely won't work, because there can be many incoming connections from different users, so you can't guarantee that its the same user, right? Can this info be retrieved from the request header somehow?
The basicAuth() middleware will set req.user and req.remoteUser once authorized.
Though, note that the 2nd argument to the callback is expected to be the user, not simply an authorized boolean. But, it can be any truthy value you desire, including the user name.
callback(null, config.credentials.clients[user].password == pass ? user : null);
After that, you should be able to retrieve it with:
var authUser = req.user;
Note that: basicAuth is deprecated
Here the code:
app.use(express.basicAuth(function(user, pass, callback){
if(config.credentials.clients[user] === undefined) {
callback('user not found!!!');
} else {
if(config.credentials.clients[user].password === pass) {
callback(null, config.credentials.clients[user]);
} else {
callback('wrong pass!!!');
}
}
});
app.post('/put', function putEvents(req, res) {
console.log(req.user.name)
res.end();
});
Guys I am trying to get myself authenticated and for this I am using node.js and mongo DB.But the thing is that after registarion the user is not able to authenticate himself.Here is my snippet
app.post('/login',function(req,res){
ContactProvider.findAll(function(error, posts) {
var aut = req.body;
if (aut.user == posts.user && aut.pass == posts.pass) {
req.session.name = {name:aut.user};
res.redirect('/home');
} else {
res.send('Bad user/pass');
}
});
});
Below is my snippet for registering the user
app.post('/register',function(req, res) {
var post=req.body;
if(post.pass!=post.cpass) {
res.send("Error:Password doesnt match");
} else {
ContactProvider.save({
user: req.param('user'),
pass: req.param('pass'),
cpass: req.param('cpass'),
email: req.param('email')
}, function(error, docs) {
res.redirect('/');
});
}
});
The ContactProvider is the one below where post provider is a different file where all the mongoose things happen
var ContactProvider = require('./PostProvider').ContactProvider;
var ContactProvider= new ContactProvider();
This is the finone query in the postprovider file
ContactProvider.prototype.findone = function(name,pass, callback) {
Post.findOne({name:name},{pass:pass}, function (err, post) {
callback(null, post);
});
};
Something's seriously wrong with your code ( why you use name posts for an array of ContactProvider? ). You have to search for ContactProvider based on username and password. Something like this:
app.post('/login',function(req,res){
var aut = req.body;
ContactProvider.findOne(
{
user: aut.user,
pass: aut.pass
},
function(err, usr) {
if (error || !usr) {
res.send('Bad user/pass');
} else {
// we have a user, authenticate!
req.session.name = {name:aut.user};
res.redirect('/home');
}
}
);
});
SIDE NOTE: This is a very simple way of authenticating users, but it is not secure at all. You should read more about authentication and security in the internet. Very useful knowledge indeed.
EDIT: There's also an issue with your registration. Your data is stored in post variable, so use it on ContactProvider as well:
// some other code
ContactProvider.save({
user: post.user,
pass: post.pass,
cpass: post.cpass, // no need to store the same thing twice
email: post.email