how passport local strategy vs custom code
// passport involved code
app.post('/login',
passport.authenticate('local'),
function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
I can also call my local function which can check the same thing which passport local strategy checks so therefore why to create local strategy
// custom checking function
app.post('/login',
customfunctionhere,
function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
Yes, you can write your own local strategy function. However, passport gives you extras like persisting the login (cookies), easily handing success and failure, and more.
Plus, if you are using other strategies like OAuth or google/fb/twitter single sign-on, then using passport for all authentication makes sense.
Note: you do not pass a validation function to passport.authenticate(). Check the passport-local docs for more info: https://github.com/jaredhanson/passport-local
Related
I am using multiple passport stratergy across my app.
Now, since I am using multiple passport strategy to connect (and not to just sign-in), I decided to Google things on how to do it.
This is where I stumbled upon this code
passport.authenticate('meetup', (err, user, info) => {
if (err) { return next(err); }
if (!user) { return res.redirect(process.env.CLIENT_ADDRESS); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect(process.env.CLIENT_ADDRESS);
});
Here I am unable to comprehend what is happening, like for first question, what is if (!user), Does it mean req.user
Second, there is req.logIn()
According to passport docs,
Passport exposes a login() function on req (also aliased as logIn())
that can be used to establish a login session.
and
When the login operation completes, user will be assigned to req.user.
Then what is the difference between using serializer/deserializer when compared with req.login?
Also in the callback, we can always do this
passReqToCallback: true
}, (req, accessToken, refreshToken, params, profile, cb) => {
to get req
To summarize can someone please help me comprehend the above code snippet?
At a high level Passport.js is a middleware that "serializes" a user identity in a request/response header (usually a session cookie). This serializing step means that it's taking the login information that identifies a user and produces a new object that represents the user. Think of this object as a key 🔑 card that only Passport will know how to interpret.
When a user makes additional API requests they pass that same identification header back. Passport auths the request by "deserializing" it to identify what user is making that request.
req.login() is the magic that is generating a session for a user. This session represents how long a login is good for without having to re-authenticate.
Let's take a look at the beginning of your snippet:
passport.authenticate('meetup', (err, user, info) => {
...
if (!user) { return...
In this snippet, passport is being set up as middleware. When a request comes through, passport behind the scenes has already interpreted the request header by deserializing the cookie and determines if it represents a user. If there is not a user or the request header does not represent a user, the request is not authorized.
req.login aliased as req.logIn
Passport exposes a login() function on req (also aliased as logIn()) that can be used to establish a login
session.
When the login operation completes, user will be assigned to req.user
Note: passport.authenticate() middleware invokes req.login() automatically.
Use a lower version of passport for this feature v0.4.1
You can install this with
npm install passport#^0.4.1
Your req.login function should work with that version.
Using passport.js, what is the recommended way to check if a user isAuthenticated?
I see examples of people doing things like this:
app.get('/', isAuthenticated, function(req,res){});
How does this even work, app.get only accepts two arguments?
What about when I use express.Router()?
What's the correct syntax for router.get?
More generally, checking isAuthenticated at every route seems inefficient. Is there a better way to check authentication in an Express app?
Thanks.
app.get accepts as many middlewares as you need. According to the documentation:
router.METHOD(path, [callback, ...] callback)
...
You can provide multiple callbacks, and all are treated equally, and behave just like middleware, except that these callbacks may
invoke next('route') to bypass the remaining route callback(s). You
can use this mechanism to perform pre-conditions on a route then pass
control to subsequent routes when there is no reason to proceed with
the route matched.
This is how your authentication middlware function may look like:
function isAuthenticated(req, res, next) {
if(/*check authentification*/) {
return next();
}
res.send('auth failed');
}
On the other hand passport.js provides a built-in function that can be used as Express middleware.
app.post('/login',
passport.authenticate('local'),
function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
Authenticating requests is as simple as calling passport.authenticate() and specifying which strategy to employ. Strategies must be configured prior to using them in a route. Continue reading the chapter on configuration for details.
I'm trying to figure out how to integrate a Oauth strategy(github) to my application which uses express and websockets.
I'm following this guide which explains how to use JWT tokens instead of using the default passport sessions
https://blog.hyphe.me/token-based-authentication-with-node/
this is the code i have so far
app.use(passport.initialize())
app.get('/auth/github',passport.authenticate('github',{session:false}),serialize, generateToken, respond)
app.get('/auth/github/callback',passport.authenticate('github',{failureRedirect:'/'}),
function(req,res){
res.redirect('/')
}
)
When i try to login via github - i get the below error
Error: Failed to serialize user into session
at pass (/home/avernus/Desktop/experiments/oauth/node_modules/passport/lib/authenticator.js:271:19)
at Authenticator.serializeUser (/home/avernus/Desktop/experiments/oauth/node_modules/passport/lib/authenticator.js:289:5)
at IncomingMessage.req.login.req.logIn (/home/avernus/Desktop/experiments/oauth/node_modules/passport/lib/http/request.js:50:29)
at Strategy.strategy.success (/home/avernus/Desktop/experiments/oauth/node_modules/passport/lib/middleware/authenticate.js:235:13)
at verified (/home/avernus/Desktop/experiments/oauth/node_modules/passport-oauth2/lib/strategy.js:177:20)
at Strategy._verify (/home/avernus/Desktop/experiments/oauth/passport.js:13:12)
at /home/avernus/Desktop/experiments/oauth/node_modules/passport-oauth2/lib/strategy.js:193:24
at /home/avernus/Desktop/experiments/oauth/node_modules/passport-github/lib/strategy.js:174:7
at passBackControl (/home/avernus/Desktop/experiments/oauth/node_modules/oauth/lib/oauth2.js:125:9)
at IncomingMessage.<anonymous> (/home/avernus/Desktop/experiments/oauth/node_modules/oauth/lib/oauth2.js:143:7)
I'm not sure where exactly the problem is
this is my github strategy
passport.use(new githubStrategy({
clientID:'********',
clientSecret:'*******',
callbackURL:'http://localhost:3000/auth/github/callback'
},
function(accessToken,refreshToken,profile,done){
console.log('accessToken: ',accessToken,' refreshToken: ',refreshToken,' profile: ',profile)
return done(null,profile)
}
))
I'm able to successfully get the profile from github
the serialize function
function serialize(req, res, next) {
db.updateOrCreate(req.user, function(err, user){
if(err) {return next(err);}
// we store the updated information in req.user again
req.user = {
id: user.id
};
next();
});
}
from my experience passportjs with oauth always requires sessions to operate, despite the session: false option.
i believe the underlying oauth library dependencies look for sessions no matter what. its quite frustrating.
edit: to add more detail to this, the example you are linking to uses the default strategy, which is not oauth based. in this instance you could opt out of using sessions. you are using the github strategy which uses oauth thus requires sessions
Aren't you missing the {session:false} option in your callback?
app.get('/auth/github/callback',passport.authenticate('github',{failureRedirect:'/', session: false}),
function(req,res){
res.redirect('/')
})
Im guessing right here because I've never worked with Strategies that requires a callback. But i would imagine that passport tries to serialize the user in the callback as thats the point where you receive the profile from Github.
I'm learning passportjs. I'm looking at the passport-google example here
https://github.com/jaredhanson/passport-google/blob/master/examples/signon/app.js
It contains the following lines of code
app.get('/auth/google',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
And subsequently, these lines:
app.get('/auth/google/return',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
Can someone help me understand why the duplicate call to passport.authenticate is needed?
The two calls actually serve distinct functions depending on what type of request is received and at what stage of authentication the flow is at.
The first call passport.authenticate is to initiate the OpenID authentication (which is what passport-google uses under the hood) and the second call (for the return URL) is used by the OpenID Provider to respond to the prior authentication request. The Passport Strategy reads the relevant assertion from the second request and processes it accordingly -- eventually leading to either a redirection to /login if the assertion failed or a redirection to / if the assertion succeeded.
The source code at https://github.com/jaredhanson/passport-openid/blob/master/lib/passport-openid/strategy.js#L164 contains some well-written comments explaining what's happening.
As a final aside, other Passport strategies may behave differently, so not every strategy with a callback necessarily requires the same seemingly "repeated" calls to passport.authenticate(...).
I'm developing a node.js app where I'm using passport to build OAuth authentication system. I can access the user through request object in each resource load after configurating it. But my question is: How can I do to check before every URL load - resources defined with app.get('/', function(..) {...}) - if user is loged and redirect the client if it's not loged. I could do it just adding a test in every method, but this is not what I want.
Thanks!
You want a middleware that checks whether the user is logged in.
isAuthenticated = function (req, res, next) {
if (req.user)
return next(); // All good, let the route handler process the request.
else
res.redirect('/login'); // Not logged in.
}
And to use it on every route that needs to be logged in:
app.get('/something', isAuthenticated, function (req, res) {
// Only in here if the user is authenticated.
});
You can also use the middleware on every route, by doing app.use(isAuthenticated), but you will need to have extra logic in the method to not create infinite redirect loops to /login, etc.