Passport req.isAuthenticated()始终返回false且req.user()未定义问题求助
req.isAuthenticated() Returning False with Passport-Facebook & Express-Session Got it, let's break down the possible issues here since you mentioned passport.deserializeUser is running but req.isAuthenticated() still returns false. These are the most common culprits to check one by one:
Incorrect Middleware Order
Express middleware executes in the order you define it, and this is critical for Passport to work with sessions. You must ensure:express-sessionis initialized before Passport's middlewarepassport.initialize()comes beforepassport.session()
Example of correct order:
// First: Initialize session storage (MongoDB in your case) app.use(session({ secret: 'your-strong-secret-key', resave: false, saveUninitialized: false, store: new MongoStore({ mongooseConnection: mongoose.connection }) })); // Then: Initialize Passport and attach it to the session app.use(passport.initialize()); app.use(passport.session()); // This depends on the session middleware aboveIf you reverse any of these steps, Passport won't be able to access the session data, leading to
req.isAuthenticated()returning false.DeserializeUser Returns a Null/Undefined User
Even ifdeserializeUserruns, if it fails to fetch a valid user from your database (e.g., the stored ID doesn't exist, or a query error occurs),req.userwill be undefined. Double-check:passport.deserializeUser(async (userId, done) => { try { const user = await User.findById(userId); console.log('Fetched user during deserialization:', user); // Add this log done(null, user); // If user is null here, req.user stays undefined } catch (err) { done(err); } });If the log shows
null, you'll need to fix your user lookup logic or ensure the ID stored in the session maps to an existing user.Mismatched Cookie Configuration for Cross-Domain or HTTPS
If your frontend and backend are on different origins (e.g.,localhost:3000vslocalhost:5000) or you're using HTTPS, incorrect cookie settings can block the browser from sending the session cookie to the backend. Adjust your session config:app.use(session({ // ... other settings cookie: { maxAge: 24 * 60 * 60 * 1000, // 1 day (adjust as needed) sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax', // For cross-domain secure: process.env.NODE_ENV === 'production', // Required for sameSite: 'none' domain: process.env.NODE_ENV === 'production' ? '.yourdomain.com' : 'localhost' // Match your domain } }));Note: For local development with HTTP, set
secure: false(browsers won't send secure cookies over HTTP).Missing Credentials in Cross-Domain Requests
If you're making AJAX requests from a frontend app (React/Vue/etc.), you need two things:- Frontend: Enable
withCredentialsin your requests (e.g., Axios:axios.get('/api/user', { withCredentials: true })) - Backend: Configure CORS to allow credentials:
const cors = require('cors'); app.use(cors({ origin: 'http://localhost:3000', // Your frontend URL credentials: true }));
Without these, the browser won't send the session cookie, so the backend can't authenticate the user.
- Frontend: Enable
Session Data Doesn't Include Passport User
Even if sessions are stored in MongoDB, check if the session document actually contains apassport.userfield. You can log the session in your callback route to verify:app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), (req, res) => { console.log('Session after Facebook auth:', req.session); // Look for req.session.passport.user here res.redirect('/'); } );If
req.session.passportis missing, yourpassport.serializeUsermight not be correctly storing the user ID, or the Facebook authentication failed to trigger serialization. Double-check your Facebook strategy's verify callback:passport.use(new FacebookStrategy({ clientID: FACEBOOK_APP_ID, clientSecret: FACEBOOK_APP_SECRET, callbackURL: '/auth/facebook/callback' }, async (accessToken, refreshToken, profile, done) => { // Ensure you're correctly finding/creating a user and calling done(null, user) const existingUser = await User.findOne({ facebookId: profile.id }); if (existingUser) { return done(null, existingUser); // Must pass the user object here } const newUser = await User.create({ facebookId: profile.id, name: profile.displayName }); done(null, newUser); }));Mismatched Facebook Callback URL
Verify that the callback URL in your Facebook Developer Dashboard exactly matches the one in your code—including HTTP/HTTPS, port number, and path. A mismatch will cause Facebook to fail the auth flow, so Passport never gets the user data to serialize into the session.
内容的提问来源于stack exchange,提问作者Ayan

