How does passport's authenticate function know which request to authenticate? - node.js

The passport docs use this to protect a route:
app.get('/api/me',
passport.authenticate('basic', { session: false }),
function(req, res) {
res.json(req.user);
});
How does authenticate() know which request to authenticate? I don't pass the request to it.

The passport.authenticate returns a function.
You can try this
console.log(passport.authenticate('basic', { session: false }));
and it will print something like
function(req, res, next){ ... }
This means that the app.get will look something like this after your app starts
app.get('/api/me',
function(req, res, next){
// now passport has access to the "req" even though you didn't pass request to it
// passport's authentication logic here
},
function(req, res) {
res.json(req.user);
});

Related

From callback url, how do I get the last req and res after callback?

User accesses to /search url then I authenticate user.
Once it's logged in, it redirects to /login/callback.
Then I want to redirect the user to www.myproxy/search.
Currently, it's redirecting to www.myproxy/login/callback. I can't find any way to get the previous res and req.
How do I get the previous res and req after the callback?
app.get('/login',
function (req, res, next) {
console.log('-----------------------------');
console.log('/Start login callback ');
next();
},
passport.authenticate('samlStrategy'),
);
app.post('/login/callback',
function (req, res, next) {
console.log('-----------------------------');
console.log('/Start login callback ');
next();
},
passport.authenticate('samlStrategy'),
function (req, res) {
console.log('-----------------------------');
console.log('login call back dumps');
console.log(req.user);
console.log('-----------------------------');
apiProxy.web(req, res, {target: serviceProvider})
}
);
app.all('*',
function (req, res, next) {
console.log('-----------------------------');
console.log('/Start login callback ');
next();
},
passport.authenticate('samlStrategy'),
function(req, res) {
console.log('passing source!')
apiProxy.web(req, res, {target: serviceProvider})
}
);
okay the thing is http is a stateless protocol, so what I mean by stateless is
you cannot know what happened in earlier request and response, and can neither keep a track of future req and resp, it has to be done explicitly somewhere in your app(only if you want to track the reqs and resps).
But here in your case I suggest you to add an additional parameter to your req body with a redirect route and if it is null or default, set a default route, and add the route to your response url.

Passport.js: how to protect ALL routes?

I followed the documentation for passport.js with passport-local: http://www.passportjs.org/docs/authorize/
When I send my users to /login they are authenticated, but nowhere in that document can I find how to authorise my users.
I've tried this, but that gives me a bad request:
router.get('/somepage', passport.authenticate('local'), function(req, res, next) {
});
I'm looking for way to protect all my pages at once. I'm working with Express 4.16 and use different route files to split up my routes.
Sam
you can use middleware with a small trick to switch between strategies
example:
const allowUrl = ['public', 'nonprivate','home'];
const authenticationMiddleware = (whiteList =[]) => (req, res, next) => {
if(whiteList.find(req.baseUrl)) {
next();
}
if (req.isAuthenticated()) {
return next()
}
res.redirect('/');
}
app = express();
app.use(passort.initialize());
app.use(authenticationMiddleware(allowUrl));
app.use(apiRouter);
app.listen(3000, ()=> console.log('hello internet');
you can add your middleware code like below
router.get('/', isAuthenticated, function(req, res) {
//your next function
});
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
As I wanted ALL routes (except for login routes off course) to pass authorization, I solved it as follows:
var ensureAuthenticated = function(req, res, next) {
if (req.isAuthenticated()) return next();
else res.redirect('/login')
}
// usersRouter contains all open routes like '/login':
app.use('/', usersRouter);
// From here on, all routes need authorization:
app.use(ensureAuthenticated);
app.use('/', indexRouter);
app.use('/api/foo', fooRouter);
app.use('/api/bar', barRouter);
I'm not sure what do you mean by "but nowhere in that document can I find how to authorise my users". Passportjs won't authorize any user. It is an authentication middleware. Authorization is different from authentication.
I think you are looking for application level middleware. You have to use app.use to make authentication work for each request to the server.
You can read more about it here. https://expressjs.com/en/guide/using-middleware.html#middleware.application

Passport JS authentication returning false when logging in from front-end side

I am currently developing a website using MERS stack. I am using express-session and passport.js for my back-end authentication. When I try to log in from my back-end server, the API works fine. However, when I try to send a POST request from my client-side (React), it is not authenticated.
I have tried to console.log the request from front-end and back-end, and the request is identical. One thing I notice is when I do not put an authentication middleware in my API, my front-end gets the data after being redirected to the API; the opposite happens when I put the middleware.
//This is my POST code
router.post(
"/userLogin",
passport.authenticate("local", {
successRedirect: "/api/user",
failureRedirect: "/api/user/asktologin"
}),
(req, res) => {}
);
//This is my middleware
const isLoggedIn = (req, res, next) => {
if (req.isAuthenticated()) {
console.log(req.isAuthenticated);
} else {
console.log(req);
}
};
Your isLoggedIn middleware is not calling the next function in the stack. It should look like this
const authenticationMiddleware = (req, res, next) => {
if (req.isAuthenticated()) {
console.log(req.isAuthenticated);
next()
} else {
console.log(req);
res.send(400);
}
};
// Then you configure it like so
app.use(authenticationMiddleware);
// Your "router" config goes here
post("/userLogin",
passport.authenticate("local", {
successRedirect: "/api/user",
failureRedirect: "/api/user/asktologin"
}),
(req, res) => {
// Do stuff
}
);
For more detailed information on how to use middlewares, make sure you check out the docs.

Differnce in Ajax post

I have one post like this
app.post('/auth', passport.initialize(), passport.authenticate('local', { session: false,scope: [] }), serialize, generateToken, respond);
this is working correctly.
Now I have made above post as a function and calling from different page
accesstokenController.auth = function(req, res) {
console.log('Here auth called');
passport.initialize(), passport.authenticate(
'local', {
session: false,
scope: []
}), serialize, generateToken, respond
};
and calling this method from differnt rout page.
This is not working means passport.intialize() or passport.authenticate is not being called
Router calling method
var oauth = require("../oauth/accesstoken");
router.post('/auth', function(req, res) {
oauth.auth(req, res);
});
What's wrong there
Thanks
See the express reference for
app.method
and
passing middleware arguments.
You can export an array of handler functions like so:
// ./oauth.js
exports.init = [
// express_session({secret: 'use express-session if you like'),
// passport.session(),
passport.initialize()
];
exports.login = [
passport.authenticate('local', options),
serialize,
generateToken,
(req, res) => res.send('you are logged in')
];
and use them in your app/router:
// ./app.js
const auth = require('./oauth');
app.use(auth.init);
app.post('/login', auth.login);
To follow the passport docs,
you should configure the module and call passport.initalize (a function returning an express middleware function, hence the brackets) separately with app.use

Adding middleware after app.router

I have a server with the following defined :
app.get('/', function(req, res) {
// gets something
}
app.post('/', function(req, res) {
// updates something, need to be authenticated
}
Now I want the post action to be only for authenticated users, so I want to add a auth middleware between them like this :
app.get('/', function(req, res) {
// gets something
}
app.use('/', function(req, res) {
// check for authentication
}
app.post('/', function(req, res) {
// updates something, need to be authenticated
}
This way, GET gets through and for POST, user has to be authenticated.
The problem is that express doesn't go in to my app.use middleware. If i put the app.use middleware before all of the app.VERB routes, it works.
Is there any way to do it like I want ?
When you declare your first route, Express automatically inserts app.router into the middleware chain. Since the router gets to handle any following routes, any middleware that you declare after that first route will not get to handle your routes.
But instead of using app.use, you can use the fact that route-handlers are very similar to middleware:
app.get('/', function(req, res) {
// gets something
});
app.all('/', function(req, res, next) { // catches GET, POST, ... to '/'
// check for authentication
});
app.post('/', function(req, res) {
// updates something, need to be authenticated
});
But if you only have a single route that needs to be passed through the middleware, it makes sense to follow the advise of #hiattp and add the middleware to the route declaration immediately.
I like to put this type of check in a reuseable method and pass it into the route handler:
function ensureAuth(req, res, next){
if(req.user) next(); // Auth check
else res.redirect('/');
}
app.post('/', ensureAuth, function(req,res){
// User is authenticated
}

Resources