hoangvvo / next-connect

The TypeScript-ready, minimal router and middleware layer for Next.js, Micro, Vercel, or Node.js http/http2
https://www.npmjs.com/package/next-connect
MIT License
1.63k stars 65 forks source link

Redirects not working? #125

Closed olifog closed 3 years ago

olifog commented 3 years ago

Hi! I'm still very new to next.js and next-connect, so I'm probably doing something wrong here- but I've been trying to figure this out for the past few hours and I've made no headway.

I'm using next-connect with an openid passport setup. Everything works well except for my /api/return endpoint- after the user logs in on the 3rd-party site and is redirected back to the /api/return endpoint, I want that endpoint to in turn redirect the user to the root of the application (after authenticating using my auth middleware). When I try to redirect to the root of the application though, it appears to hang for a couple minutes before redirecting, without the authentication having gone through and no user/cookie/session being set.

Here's my code in the /api/return endpoint:

handler.use(auth).get(passport.authenticate('steam', { failureRedirect: '/login' }), async (req, res) => {
  res.redirect('/')
})

Replacing res.redirect('/') with res.json({user: req.user}) works perfectly, in terms of authenticating the user and saving it in the session- just doesn't redirect the user back to the root of the application like I want it to.

Again I'm probably doing something dumb, any help would be very much appreciated!

hoangvvo commented 3 years ago

Hey @olifog, did you include passport.session and/or express-session in your code?

olifog commented 3 years ago

Yes, passport.session is being used I'm pretty sure, not express-session though- sorry for not mentioning it. My repo's here if that's helpful! It's using pretty much the same structure as the official next.js example using passport/next-connect.

Here's my auth middleware:

import nextConnect from 'next-connect'
import passport from '../lib/passport'
import session from '../lib/session'

const auth = nextConnect()
  .use(
    session({
      name: 'sess',
      secret: process.env.COOKIES_SECRET,
      cookie: {
        maxAge: 60 * 60 * 8, // 8 hours,
        httpOnly: true,
        secure: process.env.VERCEL_ENV === 'production',
        path: '/',
        sameSite: 'lax',
      },
    })
  )
  .use(passport.initialize())
  .use(passport.session())

export default auth

lib/passport: (data is just my options for the strategy)

passport.serializeUser(function (user, done) {
  done(null, user)
})

passport.deserializeUser(function (obj, done) {
  done(null, obj)
})

passport.use(
  new SteamStrategy(data, (identifier, profile, done) => {
    // update database here in future
    return done(null, profile);
  })
);

export default passport;

and lib/session is here

hoangvvo commented 3 years ago

@olifog Thanks for the detail. I took a look and nothing seems wrong.

Can you try doing the below instead of res.redirect:

res.statusCode = 302;
res.setHeader("Location", "/");
res.end()
olifog commented 3 years ago

Yes that works perfectly, thanks so much!