1

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();
  });
}
Jayaram
  • 6,276
  • 12
  • 42
  • 78

2 Answers2

3

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

mikesizz
  • 51
  • 3
  • I assumed that both local and social would follow the same api :/. that sucks – Jayaram Jun 20 '16 at 13:30
  • you really only "require" sessions for the initial oauth handshake. once that is completed you can resume operations as normal using your token and a deserialization middleware/handler. if i recall, when making calls without your session cookie you may get an error due to a lack of a session. i believe my workaround was to catch the request and create a dummy session object with { passport:{} } inside it, just to satisfy the existence of a session. – mikesizz Jun 20 '16 at 13:33
  • There is a stack overflow question about using JWT with Oauth2 - http://stackoverflow.com/questions/11458364/oauth-2-0-no-session-stateless – Gibryon Bhojraj Jun 20 '16 at 13:55
  • using jwt with oauth itself isnt difficult/problematic, but i believe the root of OPs problem is implementing that strategy via passportjs and its dependencies. – mikesizz Jun 20 '16 at 14:00
  • Yeah, it seems passport is calling serializeUser even though session is disabled, which means that it's not an option for github strategy. – Gibryon Bhojraj Jun 20 '16 at 14:04
  • @user3524561 - are there any alternatives to passport.js which would make it easier? – Jayaram Jun 20 '16 at 15:17
  • imo just doing oauth handling on your own is easier, faster, and cleaner. i know its not the answer you are looking for but imo it would save you a lot of headache if you just do it yourself or find an oauth library that lets you deal with sessions however you please. if you must use passport you can review my comment above which describes how to deal with the session/token issue while keeping passportjs – mikesizz Jun 20 '16 at 15:28
  • i probably could store the jwt in the cookie .. serialize it using serializeUser .. and retrieve the jwt from the cookie and store it in a socket object from which i can continue communicating with the server. would this work? – Jayaram Jun 20 '16 at 18:29
  • asi said in my previous comment, the usage of sessions with passport is purely an oauth handshake limitation. once you finish the handshake you can simply pass the authenticated user's jwt back to the client for authenticated calls. you can store it in localstorage or any other means you see fit. – mikesizz Jun 20 '16 at 19:03
1

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.

Johannes Merz
  • 3,252
  • 17
  • 33