I'm following along in the MEAN machine book and in chapter 9 about Node authentication. I have routes for all users, get, post, put and delete working.
Setup the authenticate route below:
// route to authenticate a user (POST http://localhost:8615/api/authenticate)
apiRouter.post('/authenticate', function(req, res) {
// find the user
// select the name, username and password explicitly
User.findOne({
username: req.body.username
}).select('name username password').exec(function(err, user) {
console.log(user);
if (err) throw err;
// no user with that username was found
if (!user) {
res.json({ success: false, message: 'Authentication failed. User no found.'});
} else {
// if user is found and password is right
// create a token
var token = jwt.sign({
name: user.name,
username: user.username
}, superSecret, {
expiresInMinutes: 1440 // expires in 24 hours
});
}
});
});
My full server.js file here:
https://github.com/leongaban/awesome-test/blob/865714ade6b2f15ffcd8f1fc72ad0ad18836604b/server.js
I created a new user chris / supersecret
Then tried to authenticate him using Postman and it always hangs up :(
Any idea what could be causing it to get stuck?
You're not sending a response when the user is found and the password matches. You create the token but don't do anything (with it) afterwards.
Related
I'm having issues authentication authenticate an user for an ldap server. I'm pasting the important code below. Can anyone tell me what are the missing pieces of this or whether this nodejs module is able to do what I want to do? I've been trying this for two days now and couldn't find a solution.
const passport = require('passport');
const ldapStrategy = require('passport-ldapauth').Startegy;
var LDAP_OPTS = {
usernameField: 'myAccountUsername',
passwordField: 'myPassword',
server: {
url: 'ldap://xx.xx.x.xx:389',
bindDN: 'dn related data',
bindCredentials: 'adminAccountPassword',
searchBase: 'dc=xyz,dc=com',
searchFilter: '(sAmAccountName={{myUserNameForTheAccount}})'
},
};
passport.use(new ldapStrategy(LDAP_OPTS));
app.use(passport.initialize());
module.exports.login = function(req, res, next){
passport.authenticate('ldapauth', function(err, user, info){
console.log('inside authent '+JSON.stringify(info))
if(err){
return next(err);
}
if(!user){
res.status(401).json({ success: false, message: 'authentication failed' })
// res.send({success: false})
console.log('inside user: '+user)
} else {
res.status(200).json({success: true})
// res.send({success: true})
}
console.log('after response..')
})(req, res, next)
When I run this I get a {"message":"Missing credentials"}. I googled for many resources but haven't found a proper one. There are examples using "passport-local" but I couldn't find "passport-ldapauth" example that has authenticating an user with his username & password. Even in this exapmle, we just sent a request to ldap server to check the existence of an user but I don't know how to validate his password after returning the information of that user.
The github page of passport-ldapauth links to ldapauth-fork project. According to the documentation it says that you need to add the property bindProperty to your configuration object.
ldapauth-fork says that bindProperty is
/**
* Property of the LDAP user object to use when binding to verify
* the password. E.g. name, email. Default: dn
*/
bindProperty?: string;
Hope that can help
I'm learning Passport, using local strategy and Mongoose, through passport-local-mongoose plugin.
It makes sense to me in a /login for example, but I don't understand why passport.authenticate is needed in a registration, right after it having already taken place...
Can anyone explain me, please? Also, what if it fails?
The following code was taken from a tutorial, but I have found similar constructions all over.
router.post('/register', function(req, res) {
User.register(new User({ username : req.body.username }),
req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
if (req.body.firstname) {
user.firstname = req.body.firstname;
}
if (req.body.lastname) {
user.lastname = req.body.lastname;
}
user.save(function(err,user) {
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
});
The password isn't used to authenticated the user inside this snipped.
Call User.register
Creates a new User Object with the username, and needs the password to do
some magic with it. Probably build a hash which gets added to your 'user' object.
Call user.save
Saves this 'user' object inside your Storage, if this is successful the user gets authenticated, and returns HTTP 200 which ends the registration process.
Error Handling isn't implemented in this save method, for that you will have an exception on error.
Hope this helps to understand, your snippet.
To use your /login method your new user can use his username and password which he gave to you during the registration process.
I'm creating an application learn for my self. So at the moment i need to authenticate an user using with jsonwebtoken and i know how to create a token to authenticate a user. So actually i need to know how can i retrieve logged users's information later by using the token created by the user when logged into the system. i searched everywhere for a good answer but i couldn't find a good answer
apiRoutes.post('/authenticate', function(req, res) {
// find the user
User.findOne({
name: req.body.name
}, function(err, user) {
if (err) throw err;
if (!user) {
res.json({ success: false, message: 'Authentication failed. User not found.' });
} else if (user) {
// check if password matches
if (user.password != req.body.password) {
res.json({ success: false, message: 'Authentication failed. Wrong password.' });
} else {
// if user is found and password is right
// create a token
var token = jwt.sign(user, app.get('superSecret'));
// return the information including token as JSON
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
}
});
});
this is the user login and token creation process
and the below router i need to retrieve all the user information if the user logged into the system and created the token
apiRoutes.get('/users', function(req, res) {
if(!loggedinUser){
//throw err
}
else {
User.find({}, function(err, users) {
res.json(users);
});
});
}
so please help me to understand this and i hope you guys provide me a good answer for this question
thank you
Once your authorisation token is generated you need to send that token in all requests through client side.
On the the server side you need to implement a authentication middleware in this you will check the authentication token. and process that request further
check this link
How to use the middleware to check the authorization before entering each route in express?
Add User login token in to req.session.token then check it in jwt middle ware .
I'am using JWT to authenticate users but I want also to add some informations to the token like the username.
This is how I create the tokens after I've authenticated the user :
app.post('/authenticate', function(req, res){
User.findOne({
username: req.body.username
}, function(err, user){
if(!user){
console.log('Authentication failed. User not found');
}
else if(user){
if(user.password != req.body.password){
console.log('Authentication failed. Wrong password');
}
else{
var token = jwt.sign(user, app.get('secretWord'), {
expiresIn : 10800,
});
res.send({
token: token
});
}
}
})
});
How can I associate a username to the token? I tried :
var token = jwt.sign(user, app.get('secretWord'), {
expiresIn : 10800,
username : user.username
});
But that throws an error : "ValidationError: "username" is not allowed.
You can simply add details you want like this
var token = jwt.sign(user.name,user.email, app.get('secretWord'), {
expiresIn : 10800,
});
don't pass the user object in jwt.sign because it contains crucial information like password, session_tokens etc. so Sign only the information which is necessary like name, email, role, user_type etc. like above I have given the solution
The simplest solution would be to insert the username into jwt's payload as an independent variable.
However better practice is to use the user object to generate the token. With this approach you can easily find the user if you have a token taken that the token will contain information about user's properties. Check this link on how to do this easily:
https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens
You can skip straight to "Authenticating and Creating a Token", there's a good example on how to do this in node.js.
Please , I have setup passport ldapauth which works fine with all parameters, the problem is if the username or password is wrong, the it does not execute further to the verify callback function at all. It just stops. Due to this I cannot give feedback to the users to indicate what is actually wrong. Is there any clue what I am missing?. This is the structure
passport.use('ldapStudent', new LdapStrategy({
usernameField: 'username',
passReqToCallback:true,
server: {
url: '..........',
bindDn: '.............',
bindCredentials: '..........',
searchBase: '..............',
searchFilter: '.............',
searchAttributes: ['givenName','sn'],
tlsOptions: {
ca: [fs.readFileSync('./ssl/server.crt', 'utf8')]
}
}
},
function (req, user, done) {
//now check from the DB if user exist
if(user){
//check if user email exist;
User.findOne({'EmailAddress': user}, function (err, userdata) {
// In case of any error, return using the done method
if (err)
return done(err);
//user exist redirect to home page and send user object to session
if (userdata) {
//userActivity(PostActivity);
console.log(userdata);
return done(null, userdata);
}else {
//new user, add them to the user model
var newUser = new User();
newUser.EmailAddress = req.body.username,
newUser.JoinedDate = Date.now(),
newUser.UserType = 'Student'
newUser.save(function (err, result) {
if (err) {
console.log('Error in Saving NewUser: ' + err);
} else {
console.log(result);
var PostActivity = {
ActivityName: req.res.__('Student Joined'),
ActivityDate: Date.now(),
UserID: result._id,
UserIP: (req.header('x-forwarded-for') || req.connection.remoteAddress ) + ' Port: ' + req.connection.remotePort
};
userActivity(PostActivity);
console.log('User Registration successful');
return done(null, newUser, req.flash('SuccessMessage', req.res.__('You have been successfully Registered')));
}
})
}
});
}else{
return done(null, false, req.flash('ValidationError', req.res.__('Wrong password and/or email address')));
}}));
This is where i actually do the login
router.post('/login', passport.authenticate('ldapStudent', {
successRedirect: '/',
failureRedirect: '/userlogin',
failureFlash: true
}));
The code works well , just as I expect, the parameters for the ldap option object are intentionally omitted.
The problem is when the user credential are not correct, the verify callback does not get executed at all and so, I can not return a flash message for the user to know what is happening
passport-ldapauth does not execute the verify callback if there is nothing to verify which is the case if the credentials are incorrect and the user is not received. This is in general how the strategies tend to work, e.g. passport-local does not execute verify callback if the username or password is missing.
Strategies, passport-ldapauth included, also usually include a (configurable) message for the failure flash. General configurable login failure messages for passport-ldapauth are listed in the documentation. Each of the messages also has a default value so even when not configured the failure flash message is set (given of course that you have flash middleware in use)
Also, you are not supposed to use req.flash() in the callback of the verify function but to supply an info message.