How to send userdata from passportjs? - angularjs

Im authenticating with passportjs. I want to send the user, if authenticated, to Angular. So my code :
app.post('/login', function(req, res, next){
passport.authenticate('local', (err, user, info),{
if(err) {
return res.send({err: err, info:info});
}
res.send(user);
})(req, res, next);
});
What am I doing wrong? I want to send the info to angular to log in to the console. I understand a session is created, but i just want to send (res.send) the info for debugging.
Thanks.

You're using the custom callback authenticate method, so you need to handle the login yourself otherwise there will be no user object to send back to the client (AngularJS app).
Right from the passport.js docs:
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
In this example, note that authenticate() is called from within the
route handler, rather than being used as route middleware. This gives
the callback access to the req and res objects through closure.
Note: You'll have to send the user/error to the AngularJS client using the same method as in your code instead of re-directing like this example shows.

Related

Node / Angular Authentication

I'm trying to figure out how to authenticate a user using node.js and angular.js. I have a node server which has a route pointing to api/login. Users can register and log in everything works. But when I get to the client side, I have no idea where to go. I have set up a http interceptor which send the user back to the login page if a session doesn't exist. I am currently using session express. Below are snippets of my code:
Login Route:
router.post('/login', function(req, res, next) {
var username = req.body.username;
var password = req.body.password;
User.findOne({username: username, password: password}, function(err, user) {
if(err) {
console.log(err);
res.status(500).send();
}
if(!user) {
res.status(404).send();
} else {
console.log('Set' + user);
req.session.user = user;
res.status(200).send();
}
});
Protecting this endpoint:
app.get('/api/endpoint', function(req, res) {
if(!req.session.user) {
console.log('Unauthorized');
res.status(401).send();
} else {
console.log('Logged in');
res.status(200).send();
}
});
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use('/api', require('./routes/login'));
app.use('/api', require('./routes/register'));
app.listen(port);
I'm not sure if this is detailed enough but I know there's something really simple going wrong here I just cannot see it haha! Any help would be greatly appreciated!

NodeJs + ExpressJs app routing odd behavior

I am learning ExpressJS. So far I have setup a simple todo app with user authentication using PassportJS. I use Mongoose for repository. There is nothing in the web to explain the odd behavior that I'm seeing with my route setup.
Scenario:
When I hit get /passport it will direct to the passport page
(login/signup)
When I hit get /aslkdjf it will direct to the passport page if
user is not logged in, else it will direct to the file
/public/index.html)
When I hit get / it should direct to the passport page if user
is not logged in, but it goes to /public/index.html instead and
my todo app would fail as req.user.username under /api/todos is
undefiend
Strangely, when I remove the router.get('/*', ... configuration, my app would still go to public/index.html, when I hit base path '/', but not when I hit '/asdfa'.
...
function loggedIn(req, res, next) {
if (req.user) {
next();
} else {
res.redirect('/passport');
}
}
var router = express.Router();
// passport ----------------------------------------------------------------
// get passport page
router.get('/passport', notLoggedIn, function(req, res) {
res.sendfile('./public/passport.html');
});
// post login
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/passport',
failureFlash: true
}));
// post registration
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/passport',
failureFlash: true
}));
router.get('/logout', function(req, res) {
req.session.destroy();
req.logout();
res.redirect('/');
});
// api ---------------------------------------------------------------------
// get all todos
router.get('/api/todos', function(req, res) {
// use mongoose to get all todos in the database
Todo.find({owner: req.user.username}, function(err, todos) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
res.json(todos); // return all todos in JSON format
});
});
// create todo and send back all todos after creation
router.post('/api/todos', function(req, res) {
// create a todo, information comes from AJAX request from Angular
Todo.create({
owner: req.user.username,
text : req.body.text,
done : false
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find({owner: req.user.username}, function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// delete a todo
router.delete('/api/todos/:todo_id', function(req, res) {
Todo.remove({
_id : req.params.todo_id
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find({owner: req.user.username}, function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// application -------------------------------------------------------------
router.all('*', loggedIn);
router.get('/*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
app.use('/', router);
app.listen(3000);
console.log("App listening on port 3000");
Can someone explain to me what is going on? All I want to achieve is to make the app re-route user to the login page when they are not logged in and they go to www.myapp.com/
So apparently the problem is that HTML defaults to finding an index.html file in any folder within the root. When I change the html file to something else like abc.html the problem is solved. Seems like a bug to me.

how to restrict only admin to add user?

Iam new to express.js. I got strucked with problem of adding user only by admin. and also user should not bee add if admin logged out. Here is my code please can any one help me. Iam using express.js, mongodb.
it is server side code
route.js
app.route('/auth/signin').post(users.signin);
app.route('/auth/adduser').post(users.in,users.adduser);
express.js
This is my signin code
exports.signin = function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err || !user) {
res.status(400).send(info);
} else {
// Remove sensitive data before login
user.password = undefined;
user.salt = undefined;
req.login(user, function(err) {
if (err) {
res.status(400).send(err);
} else {
req.session.value = user;
res.jsonp(user);
}
});
}
})(req, res, next);
};
This is adduser code
exports.in=function(req,res,next){
var user=req.session.value;
console.log('user details get from signin page'+JSON.stringify(user));
if(user.username===config.admin.username){
next(); //it goes to add user page
}
else{
res.send('your not a Admin');
}
};
exports.adduser = function(req, res) {
delete req.body.roles;
var user = new User(req.body);
var message = null;
// Add missing user fields
user.provider = 'local';
user.displayName = user.firstName + ' ' + user.lastName;
user.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(user);
console.log('user added');
}
});
};
But, while exceuting the code it gets error that req.session.value is undefined
i.e..,the data is not getting from signin page.
The main aim of posting this code is admin only has to add the user when he login .otherwise should send a message like you are not an admin or please login....
Actually passport sets the user on req object with logIn() method so you dont need this line
req.session.value = user; // remove this
and you can just get user on
console.log(req.user);
To verify this
Add this middleware in server.js or you app.js
app.use(function(req, res, next) {
console.log(req.user);
next();
});
here after the login occurs and authenticate plus logIn() methods are called , refreshing the page will console.log your user
Adding custom object/varaibles to session
to add user object or any thing else on session of passport you can do this as follow
req.session.passport.hi = "hello";
to verify this after adding this to session on subsequent page refresh see console when using following middleware
app.use(function(req, res, next) {
console.log(req.session.passport.hi);
next();
});

How to implement customGet in restangular?

How to implement customGet from restangular?
I wrote some code in a server like this:
user.controller.js:
exports.getRunner = function(req, res) {
User.find({provider: "instagram"}, function (err, users) {
if (err) return res.send(500, err);
res.json(200, users);
});
};
index.js:
router.get('/getRunner', controller.getRunner);
If I try to get data from postman... it responds the right json data, it works properly.
But when I try using Restangular customGet in my client side, I get instead an undefined error.
This is my client side:
Restangular.all('users').customGET('getRunner').then(function(teams) {
$scope.teams = teams;
});

Passport.js Google authentication returns blank error

Trying to use passport.js in my Angular app to use google authentication.
The way I have my express endpoints set up is:
app.set('client-google-signin-path', '/google');
app.route('/auth/google')
.get(function(req, res, next) {
var mobileApp = req.headers.origin;
passport.authenticate('google', { scope: ['profile', 'email'], callbackURL: mobileApp + req.app.get('client-google-signin-path')})(req, res, next);
});
app.route('/auth/google/callback')
.get(function(req, res, next) {
//NEVER MAKES IT HERE
var mobileApp = req.headers.origin;
passport.authenticate('google', {scope: ['profile', 'email'], callbackURL: mobileApp + req.app.get('client-google-signin-path')},
function(err, user, info) {
var profile;
if(err) return next(err);
if(!info || !info.profile) return res.status(400).send("Profile not available.");
// Grab the profile info returned from google.
profile = info.profile._json;
//model logic
User.findOne({ 'email': profile.email }, function(err, user) {
if(err) return next(err);
if(!user) return res.status(400).send("There does not appear to be an account that matches, you may need to create an account and try again.");
req.logIn(user, function(err) {
if(err) return next(err);
return res.status(200).send(user);
});
});
res.status(200);
})(req, res, next);
});
My controller looks like:
$scope.signInGoogle = function() {
return $http.get(backendConst.location + 'auth/google')
.success(function(url) {
// Redirect to google.
$window.location.href = url;
});
};
$scope.signInGoogleCallback = function() {
return $http.get(backendConst.location + 'auth/google/callback', {
params: $location.search()
})
.success(function(user) {
$scope.gRes = 'Success!';
$location.search('code', null);
$location.hash(null);
AuthModel.setUser(user);
$location.path('/');
})
.error(function(err) {
$scope.gRes = 'Authentication failed, redirecting.';
$location.path('/authenticate');
});
And for good measure, my dinky little /google redirect page is:
<div class="container clearfix" ng-init="signInGoogleCallback()">
<h1>Google YO!</h1>
<h4>{{gRes}}</h4>
</div>
So what's happening is that it brings in the "log in with google" page, lets me select my account, then when it calls the callback it quickly flashes the /google view but then kicks me back out into /authenticate, the view I started in. Doing some debugging shows that
return $http.get(backendConst.location + 'auth/google/callback', {
params: $location.search()
})
is throwing a blank "err" even though in my endpoint logs it's saying that /auth/google/callback returned a 200. I'm not sure what's happening. I know this looks needlessly complicated but I do it this way with facebook and passport.js and everything works fine, except my endpoint logs are showing that with facebook the parameter "?code=" is being added to the /auth/facebook/callback url, like I'm trying to do with {params: $location.search()} in my google callback function in my controller. Debugging into the endpoint shows that it never makes it to where I left the //NEVER MAKES IT HERE comment, but when removing the {params: $location.search()} option it makes it passport.authenticate but not beyond. I'm completely stumped. Again I should stress that I handle facebook authentication the exact same way and it works perfectly.

Resources