Limit acces to users Node.js - javascript

I want to limit access to the /secrets route only to users
app.get("/secrets", function(req, res){
Post.find({}, function(err, posts){
res.render("secrets", {
posts: posts
});
});
});
I know it should be something like this:
app.get("/secrets", function(req, res){
if (req.isAuthenticated()){
res.render("secrets");
} else {
res.redirect("/login");
}
});
But I don't know how to proceed since I already have a callback function.

You can use middleware it goes something like this.
app.get("/secrets", secretsPermissionCheck, function(req, res){
// do your request processing
}
});
you can write below code in your middleware folder.
module.exports = function secretsPermissionCheck(req, res, next){
if(!isAuthenticated()) {
res.redirect("/login")
}else {
next();
}
}

The second code you gave is the wrapper, because first you check whether the user is authenticated. If so, then you operate normally and send a POST request to find posts, while if not, then you redirect to login.
app.get("/secrets", function(req, res){
if (req.isAuthenticated()){
//start
Post.find({}, function(err, posts){
res.render("secrets", {
posts: posts
});
});
//end
} else {
res.redirect("/login");
}
});

app.get('/secrets', checkAuthentication, function (req, res) {
Post.find({}, function (err, posts) {
res.render("secrets", {
posts: posts
});
});
});
function checkAuthentication(req, res, next) {
if (req.isAuthenticated()) {
next();
} else {
res.redirect("/login");
}
}

Related

How to add "authorization" check to selective API's in NodeJs?

I have a react+node based project where I build all my react based components in a dist/ directory and then upload this directory to the server and serve it via nodeJS express.static() method.
server.use(express.static(__dirname + '/dist'))
I have also written a node middleware which captures every request and checks if auth token is passed to it or not.
users.use(function(req, res, next) {
const token = req.headers.authorization
if (token) {
jwt.verify(token, process.env.SECRET_KEY, function(err) {
if (err) {
res.status(400).json({message : err})
} else {
next();
}
});
} else {
res.status(400).json({message : 'Please send a token'})
}
})
But the issue that now I am facing is that, when I run URL such as http://localhost:3001/dashboard, the node middleware also captures it and check for token instead of rendering my webview.
How do I differentiate between webview requests and other server requests in nodeJS
If you need to check auth for only some specific API you can do in following 3 ways:
Write all the functions(API) that don't use auth above/before your auth check function
`
users.get('/yourAPI1', function(req, res, next) {
//Do your stuff
});
users.get('/yourAPI2', function(req, res, next) {
//Do your stuff
});
users.get('/yourAPI3', function(req, res, next) {
//Do your stuff
});
users.use(function(req, res, next) {
const token = req.headers.authorization
if (token) {
jwt.verify(token, process.env.SECRET_KEY, function(err) {
if (err) {
res.status(400).json({message : err})
} else {
next();
}
});
} else {
res.status(400).json({message : 'Please send a token'})
}
});
//Now those functions which need auth checks
users.post('/yourAPI4', function(req, res, next) {
//Do your stuff
});
users.post('/yourAPI5', function(req, res, next) {
//Do your stuff
});
`
Modify your Auth function to skip all GET API. NOTE: Use this only if you use GET to load HTML page and not to fetch data like search of any other info.
`
users.use(function(req, res, next) {
//Just a check for `GET` API
if(req.method === 'GET') {return next();}
const token = req.headers.authorization
if (token) {
jwt.verify(token, process.env.SECRET_KEY, function(err) {
if (err) {
res.status(400).json({message : err})
} else {
next();
}
});
} else {
res.status(400).json({message : 'Please send a token'})
}
});
`
Call Auth function from only those API which needs to check auth like:
`
function checkAuth (req, res, next) {
const token = req.headers.authorization
if (token) {
jwt.verify(token, process.env.SECRET_KEY, function(err) {
if (err) {
res.status(400).json({message : err})
} else {
next();
}
});
} else {
res.status(400).json({message : 'Please send a token'})
}
});
//Escaping auth check
users.get('/yourAPI6', function(req, res, next) {
//Do your stuff
});
//Need auth for this
users.get('/yourAPI7', checkAuth, function(req, res, next) {
//Do your stuff
});
users.post('/yourAPI8', function(req, res, next) {
//Do your stuff
});
users.post('/yourAPI9', checkAuth function(req, res, next) {
//Do your stuff
});
users.put('/yourAPI10', function(req, res, next) {
//Do your stuff
});
users.put('/yourAPI11', checkAuth function(req, res, next) {
//Do your stuff
});
`
Out of all these I will prefer 3rd one as It gives you flexibility to use as a function and anywhere you need it.
You need to add a redirection for all your routes to point to your index.html or whatever is your start page.
/* route to static files */
server.use('/static-route-here', express.static(__dirname + '/static-folder-here'))
/* multiple definitions of other server routes */
server.get('api/*', authMiddleWare ,(req, res) => {
/*do api stuff here*/
})
/* anything else is redirected to index.html */
server.get('*', (req, res) => {
res.sendFile(__dirname + '/index.html');
})

Passport Js documentation Custom Callback syntax

I am using passport.js for my node app. In the Custom Callback section I found the following code(lets say it Code A):
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);
});
My question is I am not able to understand passing (req, res, next) at the end. How the following code(lets say it Code B):
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);
});
});
});
How Code B is different from Code A ?
If I simplify Code A then it will be like :
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(..){..})(req, res, next);
});
Further
passport.authenticate(..)(req, res, next);
which means expression like
function(..)(req,res, next)
My Question is more about understanding the syntax
function(..)(parameters)
authenticate() function is structured like this:
module.exports = function authenticate(passport, name, options, callback) {
// ...
return function authenticate(req, res, next) {
// ...
strategy.success = function(user, info) {
if (callback) {
return callback(null, user, info);
}
}
// ...
})
};
So it takes two series of parameters:
The first one (in your case 'local' and the callback function) is used to tell passport to authenticate you, and how to do it;
The second handles the function to control your app with req, res and next parameters.
Hope it helps you to understand!

Use condition in express.js server

How I can use condition in my express.js server. If user login I want to change roots and side server rendering my react app. This condition dont work if(!isLoggin) if user login I change it to true, so this should render my index with react. Wher is problem ?
if(typeof(isLoggin)=='undefined'){
var isLoggin = false;
}
//roots
if(!isLoggin){
//index
app.get('/', function(req, res){
res.render("indexNotLogin",{title:''});
})
//funkcje
app.get('/funkcje', function(req, res){
res.render("funkcje",{title:'Funkcje'});
})
//zaloguj
app.get('/zaloguj', function(req, res){
res.render("zaloguj",{title:'Zaloguj siÄ™'});
})
//zaloguj
app.post('/trylogin', function(req, res){
var username = req.body.name;
var password = req.body.password;
connection.query("SELECT * FROM user WHERE username='"+username+"' AND pass='"+password+"'", function(error, rows,fields){
//callback
if(!!error){
console.log('error in query');
}else{
if(rows.length){
res.send('user zalogowany')
isLoggin=true;
}else{
res.send('user nie istnieje')
}
}
})
})
}else{
console.log("to jest true: "+isLoggin);
app.get('/', function(req, res){
res.render("index",{title:'Zaloguj sie'});
})
}
#edit /zaloguj, /funkcje this is my static roots
At first, implement login with session, not a flag.
app.post('/trylogin', function(req, res){
var username = req.body.name;
var password = req.body.password;
connection.query("SELECT * FROM user WHERE username='"+username+"' AND pass='"+password+"'", function(error, rows,fields){
if(!!error){
console.log('error in query');
}else{
if(rows.length){
res.send('user zalogowany')
req.session.user_id = put_user_id_here
}else{
res.send('user nie istnieje')
}
}
})
})
If you want to check if the user is logged in or not in order to restrict an access, it is better to implement your own Express middleware (http://expressjs.com/en/guide/using-middleware.html#middleware.router). With the authentication middleware like below, you don't have to add a condition block which wraps route definitions.
app.use(function(req, res, next) {
if (req.session.user_id) {
next();
} else {
res.status(401).send('Unauthorized')
}
});
Like this ?
function checkAuth(req, res, next) {
console.log('Jakies id: '+req.session.user_id);
if (!req.session.user_id) {
if(req.route.path=='/'){
res.render("indexNotLogin",{title:''});
}else{
res.send('You are not authorized to view this page');
}
} else {
next();
}
}
My root to after success login:
//index
app.get('/', checkAuth, function(req, res){
res.render("index",{title:''});
})

passport - nodejs - returning user to previous page after facebook auth

I'm new to passport and am trying to redirect a user to the page that they were previously on after authenticating with facebook. I am trying to set a "req.session.returnTo" property on the session, but it keeps getting wiped out in the facebook/auth callback (everywhere in that function it turns up as undefined). What is wrong with my approach?
Protected route:
app.post('/api/recipebox', ensureAuthenticated, function (req, res) {
});
ensureAuthenticated:
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
req.session.returnTo = req.path;
res.redirect('/#!/login');
}
//Facebook/Passport.js callback:
app.get('/auth/facebook/callback', function (req, res, next) {
passport.authenticate('facebook', function (err, user, redirectURL) {
// console.log(' in the callback ');
if (err) {
console.log(err);
return res.redirect('/#!/login');
}
if (!user) {
return res.redirect('/#!/signup');
}
if (req.user) {
// console.log("==================== This is the user from routes.js", req.user);
res.cookie('user', JSON.stringify(user));
}
//actually storing the fact that they are logged in:
req.login(user, function (err) {
if (err) {
return res.redirect('/#!/login');
}
// console.log('=========== here!', user);
res.redirect(req.session.returnTo || '/#!');
req.session.returnTo = null;
});
})(req, res, next);
})
I am using the Local strategy for an email and password login. I referred to the following link to setup my passport JS authentication and login: Passport Facebook
Use the Facebook Strategy as seen in the above link.
Use the routing as seen below
app.get('/auth/facebook/callback',passport.authenticate('facebook',
successRedirect: 'whatever-url-you-want',
failureRedirect: '/login' }));
I ended up doing this on the client:
$httpProvider.interceptors.push(function ($q) {
return {
request: function (request) {
// console.log("hello");
// console.log(window.location.href);
request.headers.lastUrl = window.location.href;
return request;
},
responseError: function (response) {
return $q.reject(response);
}
};
});
and this on the server:
app.use(function (req, res, next) {
//req.session.returnTo is available everywhere in router now.
//filter if it not auth/login/signup, then save it. only update return to when it's not one of those.
if (req.get('lastUrl') !== undefined) {
var lastUrl = req.get('lastUrl');
if (lastUrl.indexOf("login") === -1 && lastUrl.indexOf("signup") === -1 && lastUrl !== "http://localhost:3000/#!/") {
req.session.returnTo = lastUrl;
}
console.log(req.session);
}
next();
});
Hope it helps others. I did not have luck with the successRedirect and i don't think it would be that simple if you end up being at pages like login/signup/taken away from the page all together.

Node.js async consistency

I have the following code :
server.use(function(req, res, next) {
users_db.set(req.user, function(err) { // async call to mongodb
if (err) {
console.error(err);
}
});
}
return next();
});
server.get('/', function(req, res) {
req.user.active = true; // this is a new field in user object
res.send(req.user);
}
});
So, As you see, when users_db.set() is called, req.user doesn't have the active=true field. It is being inserted only in the server.get() function.
Is it possible that user.active = true is registered in the db nevertheless because of the asynchronous nature of the call ?
As far as I know (it is like that in Express at least) .get method accepts many middleware functions. So I guess that the following will work:
server.get(
'/',
function(req, res, next) {
req.user.active = true; // this is a new field in user object
res.send(req.user);
next();
},
function(req, res, next) {
users_db.set(req.user, function(err) { // async call to mongodb
if (err) {
console.error(err);
}
});
}
return next();
}
);
Doing the things like that you are sure that req.user.active is populated always before to reach the moment with users_db.set.

Categories