Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using AuthenticationCallback/req.logIn() breaks deserialization in 0.7.0 #1020

Open
Mark-Elliott5 opened this issue Mar 10, 2024 · 0 comments

Comments

@Mark-Elliott5
Copy link

I am creating a chat app with websockets and want to use req.user within websocket event listener handlers. Using a simple passport.authenticate('local') works fine and populates req.user in later requests as expected. However, I want to provide an AuthenticationCallback to send a variable JSON message back to my React frontend on login success/failure rather than just a 401 status. User information is retrieved successfully but later requests do not deserialize. Downgrading to 0.5.3 fixes the issue.

Expected behavior

req.user is populated through deserialization on requests after authorization

Actual behavior

req.user is undefined on requests after authorization

Steps to reproduce

Route:

app.post('/login', (req: IReq, res: IRes, next: INext) =>
  passport.authenticate('local', function (err, user) {
    if (err) {
      console.log('err');
      return res.json({
        authenticated: false,
        message: 'Server error. Try again.',
      });
    }
    if (!user) {
      return res.json({
        authenticated: false,
        message: 'User not found.',
      });
    }
    req.logIn(user, { session: true }, (err) => {
      console.log(err);
    });
    res.json({ authenticated: true });
  } as AuthenticateCallback)(req, res, next)
);

My passport configuration:

import { Application } from 'express';
import passport from 'passport';
import { Strategy as LocalStrategy } from 'passport-local';
import 'dotenv/config';
import session from 'express-session';
import bcrypt from 'bcrypt';
import { User } from '../types/mongoose/User';

const configureAuthentication = (app: Application) => {
  const secret =
    process.env.SECRET ??
    (() => {
      throw new Error('.env secret key not found! Sessions need a secret key.');
    })();

  app.use(
    session({
      secret,
      resave: false,
      saveUninitialized: true,
    })
  );

  passport.use(
    new LocalStrategy(async (username, password, done) => {
      try {
        const user = await User.findOne({ username });
        if (!user) {
          return done(null, false);
        }
        const match = await bcrypt.compare(password, user.password);
        if (!match) {
          return done(null, false);
        }
        return done(null, user);
      } catch (err) {
        return done(err);
      }
    })
  );

  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser(async (_id, done) => {
    try {
      const user = await User.findById(_id);
      done(null, user);
    } catch (err) {
      done(err);
    }
  });

  app.use(passport.initialize());
  app.use(passport.session());
};

export default configureAuthentication;

My websocket (logs undefined on 0.7.0, logs correctly on 0.5.3):

import WebSocket from 'ws';
import { IReq } from '../types/express';

function websocketHandler(ws: WebSocket, req: IReq) {
  ws.on('message', function (msg: WebSocket.RawData) {
    console.log(req.user); // undefined
    ws.send(msg);
  });
}

Environment

  • Operating System: macOS 14.1.1
  • Node version: 20.10
  • passport version: 0.7.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant