how to restrict only admin to add user? - angularjs

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();
});

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!

Email verify in sail.js

I am trying to make a portal for filling up a form for which an applicant needs to create an account before filling out the form. The only issue is how can I stop from spamming the applicant creating account with fake mail. Is it possible to verify email in sail. I have done this in express using node mailer.
var express = require('express');
var nodemailer= require('nodemailer');
var app = express();
var smtpTransport = nodemailer.createTransport("SMTP", {
service: "Gmail",
auth: {
user: "email",
pass: "pass"
}
});
var rand, mailOptions, host, link;
/*---SMTP OVER---*/
/*--Routing Started--*/
app.get('/', function(req , res) {
res.sendfile('index.html');
});
app.get('/send', function(req , res) {
rand=Math.floor((Math.random() * 100) + 54);
host= req.get(host);
link="http://"+req.get('host')+"/verify?id="+rand;
mailOptions={
to : req.query.to,
subject : "Please confirm your Email account",
html : "Hello,<br> Please Click on the link to verify your email.<br>Click here to verify"
}
console.log(mailOptions);
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
res.end("error");
}else{
console.log("Message sent: " + response.message);
res.end("sent");
}
});
});
app.get('/verify',function(req,res){
console.log(req.protocol+":/"+req.get('host'));
if((req.protocol+"://"+req.get('host'))==("http://"+host))
{
console.log("Domain is matched. Information is from Authentic email");
if(req.query.id==rand)
{
console.log("email is verified");
res.end("<h1>Email "+mailOptions.to+" is been Successfully verified");
}
else
{
console.log("email is not verified");
res.end("<h1>Bad Request</h1>");
}
}
else
{
res.end("<h1>Request is from unknown source");
}
});
/*--------------------Routing Over----------------------------*/
app.listen(9999,function(){
console.log("Express Started on Port 3000");
});
Any help will be appreciated Thanks
You should be able to use nodemailer in sails pretty much the same, just change the app.gets into corresponding controller actions.
MailController.js:
module.exports = {
sendVerificationMail: function(req, res) {
// your app.get('/send') code
},
verifyEmail: function(req, res) {
// your app.get('/verify') code
}
}
As a side note, your verifying logic kinda breaks when another user tries to register before the first one has completed his registration:
First user requests for email verification, rand = 34 for example
Second user requests for email verification, rand = 58
First user tries to verify his email with id=34, verification fails since 34 !== 58

Create account with social login (facebook) and authenticate it angular-fullstack generator

I'm facing a problema with social signup because its not logging after its created as in local signup. When redirects, api/users/me is not accessible..is unauthorized (401), different from what i get in local signup, that redirects with user information.
in facebook/index.js I have default gets
.get('/', passport.authenticate('facebook', {
scope: ['email', 'user_about_me'],
failureRedirect: '/signup',
session: false
}))
.get('/callback', passport.authenticate('facebook', {
failureRedirect: '/signup',
session: false
}), auth.setTokenCookie);
and in auth.service.js I have the default functions
function isAuthenticated() {
return compose()
// Validate jwt
.use(function(req, res, next) {
// allow access_token to be passed through query parameter as well
if (req.query && req.query.hasOwnProperty('access_token')) {
req.headers.authorization = 'Bearer ' + req.query.access_token;
}
validateJwt(req, res, next);
})
// Attach user to request
.use(function(req, res, next) {
User.findByIdAsync(req.user._id)
.then(function(user) {
//user here is undefined, it shouldn't be. i want to find out why.
if (!user) {
return res.status(401).end();
}
req.user = user;
next();
})
.catch(function(err) {
return next(err);
});
});
}
function signToken(id, role) {
return jwt.sign({ _id: id, role: role }, config.secrets.session, {
expiresInMinutes: 60 * 5
});
}
/**
* Set token cookie directly for oAuth strategies
*/
function setTokenCookie(req, res) {
if (!req.user) {
return res.status(404).send('Something went wrong, please try again.');
}
var token = signToken(req.user._id, req.user.role);
res.cookie('token', token);
res.redirect('/');
}
Could anyone help me with this...Am I missing something?
Thanks in advance.
I had the similar issue. I had modified Angular full-stack code with a customizable backend URL.
https://github.com/kannach/AFSPhonegap/blob/master/client/components/services/config.service.js
I was testing the facebook login in localhost, whereas my backend url was pointing to my production server. Once I chanded the backed url to localhost, then everything worked as expected

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.

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