I am trying to use passport.js to set up authorization in an api. I am having trouble checking if a user is already logged. In expressjs I would do something like:
router.get('/is_logged_in',
passport.authenticate('jwt', { session: false }),
function (req, res, err) {
...
}
that is, in expressjs you can add the middleware passport.authenticate(...),
Can this be done with restify?, for instance if I have the route:
server.get('/is_logged_in', (req, res, next) => {
...
});
Where do I put the middleware? (or is this supposed to be done differently?) I can not add it as a second parameter for what I understand.
Related
I use nestjs to build a REST API.
I have a middleware which loads data from redis cache and should save it in the request object to access it in the controller function.
If i use express as engine it works, but with fastify it doesn't work. The data is undefined in the controller function.
The code looks like:
function mymiddleware(req, res, next) => {
req.data = {...};
next();
};
this is a simple working example:
const fastify = require('fastify')({ logger: true })
fastify.use(function (req, res, next) {
console.log('middy')
req.data = { hello: 'world' }
next();
})
fastify.get('/', (req, res) => {
res.send(`hello ${req.raw.data.hello}`)
})
fastify.listen(3000)
I think that your problem is due to the req object: in middleware (registered using .use you will get the standard Node.js request, instead of augmented HTTPRequest in the fastify handler.
So, you can access the low-level Http request with .raw field.
I am using express and pug, there are some values that I would like to pass to pug on every request, for example: req.session and req.path. Passing these values to the render() method every time just seems too redundant.
So instead of doing something like this:
app.get('/', (req, res) => {
res.render('home', {session: req.session})
})
app.get('/profile', (req, res) => {
res.render('profile', {session: req.session})
})
The more routes that get added, the more of those items I need to manage. Is there a global way that I can set them once other than app.locals so they are unique per request?
You can set variables that are available to every template on each request using a bit of custom middleware and locals. This same approach works for all templating systems that Express can use, not just Pug.
Put the following before your routes.
app.use((req, res, next) => {
res.locals.session = req.session
next()
})
Then in your template you can call it like this.
h3= session.name
I cant seem to use the same endpoint in different route files.
index.js:
var users = require('./routes/users.js');
var orders = require('./routes/orders.js');
app.use('/users', users);
app.use('/orders', orders);
routes/users.js:
baseDep.router.get('/', function (req, res) {
res.json("This is the users route");
});
routes/orders.js
baseDep.router.get('/', function (req, res) {
res.json("This is the orders route");
});
localhost:3000/orders --> This is the users route
localhost:3000/users --> This is the users route
The second one works as expected.
The first one seems to using the endpoint in the users route file.
Can someone help figure out what I need to do?
If you have a look at the documentation for express app.use() method, it tells you that you need to use next() function in the middleware so that is can move on: https://expressjs.com/en/4x/api.html#app.use
For example:
baseDep.router.get('/', function (req, res, next) {
res.json("This is the users route");
next();
});
In my node application, I have an admin that can make all requests and the normal user that has the right to make only certain requests.
example:
admin cans make:
post on /root, /user, /tools
simple users can make:
post on /users, /tools
If a simple user tries to make a request on /root, he just receives and error message.
How can I handle this is node js? which package, if possible few examples.
thank
A general approach should be define a custom middleware to verify the authentication
function VerifyUser(req, res, next){
if(user.isAuthenticated){
return next(); //call the next middleware
}
next(err); //call the error middleware
}
error handler
app.use(function(err, req, res, next) {
if(!err) return next();
res.status(500).json(new Error('error happened'));
});
and then for each route that needs authentication bind the VerifyUser middleware before the router middleware.
Since in express the middleware order is relevant, VerifyUser will be called at first, and if the branch reach the next() call your routing function will be triggered.
Authenticated routes:
router.get('/root', VerifyUser, function(req, res){
//if you reach this point means the user has been granted the access
})
Non-authenticated routes:
router.get('/tools', function(req, res){
})
I have a ExpressJS app that is using Passportjs to authenticate with Facebook and everything is working as expected exception for one issue.
I have vehicle.js under /routes/ which contains some routes (router.gets and router.posts) that need authentication and some that don't. If user is logged in then every request handled by vehicle.js causes User de-serialization which is a Mongoose lookup. How can I avoid these unnecessary Mongoose lookups when request is made to a router.get and/or router.post that do not need authentication?
I have already looked up this SO question and it does not address my problem (I have declared static resources above passport, so they are not authenticated).
Passport configs in app.js are shown below:
// Configuring Passport
var passport = require('passport');
var expressSession = require('express-session');
app.use(expressSession({secret: 'thisIsSecret'}));
app.use(passport.initialize());
app.use(passport.session());
// Using the flash middleware provided by connect-flash to store messages in session
// and displaying in templates
var flash = require('connect-flash');
app.use(flash());
// Initialize Passport
var initPassport = require('./passport/init');
initPassport(passport);
//passing passport object could be the reason why all requested that are
//mapped in vehicle cause user de-serialization. Not sure if there is any
//alternative approach than following line that passes passport??
var vehicle = require('./routes/vehicle')(passport);
The following isAuthenticated is in vehicle.js
var isAuthenticated = function (req, res, next) {
if (req.isAuthenticated())
return next();
// if the user is not authenticated then redirect him to the login page
res.redirect('/vehicle/api/login');
}
Followed by a series of routes that handle logging in, logging out, as well as some actions on vehicle.
module.exports = function(passport) {
router.get('/api/login', function(req, res) {
res.render('vehicle/login', { message: req.flash('message') });
});
router.post('/api/login', passport.authenticate('login', {
successRedirect: '/vehicle/api/list/mine',
failureRedirect: '/vehicle/api/list',
failureFlash : true
}));
...
...
...
router.post('/api/upload', isAuthenticated, function(req, res) {
//this route needs to be authenticated, so it works fine,
//deserialization done, mongoose lookup, no problem
});
router.get('/api/image/:vehicleId/:filename', function(req,res) {
//this route does not need authentication, but causes User
//de-serialization and Mongoose lookup
});
return router;
}
Is it because of the following line that every request to vehicle.js causes User de-serialization when a user is logged in?
var vehicle = require('./routes/vehicle')(passport);
One way to avoid such unnecessary de-serialization would be to separate routes that do not need authentication from vehicle.js to a different file and do not pass that passport object to that file (as it is passed to vehicle.js in app.js). I don't know if that is the correct way to resolve this issue.
You can wrap the passport middleware inside a custom middleware that only invokes it for your specified routes. So Instead of:
app.use(passport.session());
you could:
app.use(function(req, res, next){
if(req.url.match('api/image'))
next(); // do not invoke passport
else
passport.session()(req, res, next)
// same as doing == app.use(passport.session())
});
If you use passport.session() middleware, deserialize will happen for every route:
https://github.com/jaredhanson/passport/blob/33075756a626999c6e2efc872b055e45ae434053/lib/strategies/session.js#L53-L69
The solution would be to add it only to ones which use passport.