Node / Angular Authentication - angularjs

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!

Related

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

How to protect static folder in express with jwt

I have application which is build on nodejs and angularjs ,where i am using jwt token based authentication to authenticate and the api calls that is working fine
Even when the user is not login now application is service all the static resources how to avoid loading the application if the user is not login and redirect the user to login page
Finally i was able to fiqure it out in the app.js floder add the code sinpet
app.use('/app/view/*', function(req, res, next) {
if (!req.headers['authorization'] ) {
res.sendfile('app/views/Error.html');
} else {
next();
}
});
this mean for the request coming with /app/view/ check if the header of the request contains the token generated with jwt
If your JWT is stored in a cookie you can use a road like this one :
router.all('/*', function(req, res, next){
if (!req.cookies.session) {
return res.json("ERROR");
}
else {
ValidateCookieFunction(req.cookies.session, function(auth_state) {
if (!auth_state)
return res.json("ERROR");
else
next();
});
}
});
else you can provide your JWT in an HTTP-Header
router.all('/*', function(req, res, next){
if (!req.headers['x-access-token']) {
return res.json("ERROR");
}
else {
ValidateJWTFunction(req.headers['x-access-token'], function(auth_state) {
if (!auth_state)
return res.json("ERROR");
else
next();
});
}
});

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

Resources