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');
})
Related
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");
}
}
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!
I'm developing a module which I'm using for passport authentication with ExpressJS, and I came up with this solution to gather all the passports methods I'm using:
// passport-controller-js
exports.signup = (passport) => (req, res, next) => {
// Authenticate methods ================
passport.authenticate('local-signup', function(err, user, info) {
if (err) {
return next(err); // will generate a 500 error
}
// Saving user...
return res.send({ success : true, message : 'signup succeeded' });
})(req, res, next);
};
exports.signin = (passport) => (req, res, next) => {
passport.authenticate('local-login', function(err, user, token, info) {
if (err) {
return next(err); // will generate a 500 error
}
req.login(user, loginErr => {
if (loginErr) {
return next(loginErr);
}
return res.send({ success : true, message : 'signin succeeded' });
});
})(req, res, next);
};
But since this module will increase adding more strategies I'm thinking if there is a way to put all of them inside a module.exports like:
module.exports = (passport) => {
function signin(req, res, next) {
passport.authenticate('local-login', function(err, user, token, info) {
if (err) {
return next(err); // will generate a 500 error
}
req.login(user, loginErr => {
if (loginErr) {
return next(loginErr);
}
return res.send({ success : true, message : 'signin succeeded' });
});
})(req, res, next);
};
I know that dosn't work Im just wondering if there is a possible solution like that so when I need to require those methods on my router file for example I can do this:
// auth.js (passport is passed from index.js)
const passportController = require('../controllers/passport-controller')(passport);
// Process the signup form
router.post('/signup', passportController.signup);
router.post('/signin', passportController.signin);
Instead of:
// auth.js (passport is passed from index.js)
const passportController = require('../controllers/passport-controller');
// Process the signup form
router.post('/signup', passportController.signup(passport));
router.post('/signin', passportController.signin(passport));
As you can see is just matter of looking for the most legible way to code and keep it simpler as possible.
Any help would be appreaciated, thank you very much.
Sounds like you want to make a module that exports a single function which returns an object. The syntax for that is
module.exports = passport => ({
signup(req, res, next) {
…
},
signin(req, res, next) {
…
}
});
Hi am a beginner to Nodejs i have used passportjs token based authentication if the user logins it provides a token for each user i want to perform some operations based for the users who has token values for example if the user want to see the list of registered users they can view it if he has the token value. Now it provides me the token value perfectly in Postman but i don't know how to store it in a variable and call it via FRONT-END. I want do it via Front End(If he clicks the get users button) it should display the list of users.I have done that in POSTMAN it works finely i don't have an idea how to do it via frontend.
My user Code(Login/Logout)
var express = require('express');
var router = express.Router();
var User = require('../models/user');
var passport = require('passport');
var Verify = require('./verify');
/* GET users listing. */
router.route('/')
.get(Verify.verifyOrdinaryUser, function(req, res, next) {
User.find({}, function (err, users) {
if (err) throw err;
res.json(users);
});
});
router.post('/register', function(req, res, next) {
User.register(new User({ username : req.body.username }),req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
user.save(function(err,user) {
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
});
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
var token = Verify.getToken(user);
res.status(200).json({
status: 'Login successful!',
success: true,
token: token
});
});
})(req,res,next);
});
router.get('/logout', function(req, res) {
req.logout();
res.status(200).json({
status: 'Bye!'
});
});
module.exports = router;
Main.js File. In this main.js file i want to send that token in this get method any idea?
$(".get-users-button").click(function() {
$.ajax({
method: "GET",
url: " http://localhost:3000/users"
})
.done(function(msg) {
console.log(msg);
template(msg);
});
});
When you get back a successful response from the POST to your /login endpoint, store the token on client-side (e.g., window.localStorage.setItem('<your-namespace>-user-token', <the token goes here>);)
Then, when user clicks the 'get-users-button', get the token out of storage (e.g., window.localStorage.getItem('<your-namespace>-user-token'); and store it in a variable if you want.
Then, on your request to get users, add your { 'x-access-token': <token variable goes here> } to your request headers.
As per the documentation for Passport:
If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.
Now if I'm understanding your question correctly, you want to pass the token value you obtain from:
var token = Verify.getToken(user)
to the view in which your front-end can do something with. You can pass variables to the view using the following middleware:
app.use((req, res, next) => {
res.locals.token = Verify.getToken(req.user)
next()
}
See the documentation for res.locals for more details.
Example usage:
app.js
const express = require('express')
const app = express()
app.set('view engine', 'pug')
app.use((req, res, next) => {
res.locals.text = 'asdf'
res.locals.token = 'abc'
next()
})
app.get('/', (req, res) => {
res.render('index')
})
app.listen(3000, () => {
console.log('listening on 3000')
})
views/index.pug
doctype html
html
head
title= title
body
h1= text
script.
console.log('#{token}')
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.