can't access res.user.username in passport express-session

Issue

I’m learning to create sessions using passport and express.
I’m trying to access username from user stored in session using res.user.username but can’t.
Here’s the code:

if (process.env.NODE_ENV !== 'production') {
  require("dotenv").config();
}
const express = require("express");
const mongoose = require("mongoose");
const passport = require('passport');
const bcrypt = require('bcrypt');
const flash = require('express-flash');
const session = require('express-session');
const cookieParser = require('cookie-parser')
const userAuth = require('./models/userAuth');
const initPassport = require('./passport-config');
const app = express();
const port = 3033;

initPassport(passport, userAuth);

//database
mongoose.connect(process.env.DB_URL);
const db = mongoose.connection;
db.on("error", err => console.error(err));
db.on("open", () => console.log("connected to database"));

//middleware
app.set('view-engine', 'ejs');
app.use(express.urlencoded({
  extended: false
}));
app.use(cookieParser());
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());


//  routes
app.get('/login', (req, res) => {
  res.render("login.ejs");
})
app.get('/register', (req, res) => {
  res.render("register.ejs");
})
app.get('/', (req, res) => {
  console.log(res)
  res.render("user.ejs", {
    username: res.user.username //hhheeeerrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeee
  });
});
app.post('/auth/register', isUnique, async(req, res) => {
  let newuser;
  try {
    const encryptedPwd = await hashit(req.body.password);
    const user = new userAuth({
      username: req.body.username,
      password: encryptedPwd
    })
    newuser = await user.save();
    respond(res, 201, newuser);
  } catch (err) {
    respond(res, 400, {
      message: err.message
    })
  }
});
app.post('/auth/login', passport.authenticate('local', {
  successRedirect: '/',
  failureRedirect: '/login',
  failureFlash: true
}));
app.get('/', async(req, res) => {
  const users = await userAuth.find();
  res.json(users)
});

async function isUnique(req, res, next) {
  try {
    const users = await fetchUsers();
    const user = req.body.username;
    if (users.find(data => data.username === user)) {
      return respond(res, 400, {
        message: "User already exists"
      })
    }
  } catch (err) {
    return respond(res, 500, {
      message: err.message
    })
  }
  next();
}

function hashit(password) {
  return bcrypt.hash(password, 10);
}

function fetchUsers() {
  return userAuth.find();
}

function respond(res, code, message) {
  res.status(code).json(message);
}

//start listening
app.listen(port, () => {
  console.log(`listening on http://localhost:${port}`)
});

initPassport module :

const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');

function initPassport(passport, userDB) {
    const authUser = async (username, password, done) => {
        const user  = await userDB.findOne({username: username});
        if (user == null) {
            return done(null, false, {message: "no user found"});
        }
        try {
            if(await bcrypt.compare(password, user.password)){
                return done(null, user);
            }else{
                return done(null, false, {message: "incorrect password"});
            }
        }catch(err){
            return done(err);
        }
    }
    // new LocalStrategy({usernameField: 'username', passwordField: 'password'}, authUser)
    passport.use(new LocalStrategy(authUser))
    passport.serializeUser((user, done)=>{
        done(null, user.id)
    });
    passport.deserializeUser((id, done)=>{
        return done(null, async()=>await userDB.findById(id));
    });
}
module.exports = initPassport;

userAuth model :

const mongoose = require('mongoose');

const schema = new mongoose.Schema({
    username: {
        type: String,
        required: true,
    },
    password: {
        type: String,
        required: true,
    }
})

module.exports = mongoose.model('userAuth', schema);

installed dependencies:

"dependencies": {
    "bcrypt": "^5.0.1",
    "cookie-parser": "^1.4.6",
    "ejs": "^3.1.8",
    "express": "^4.18.1",
    "express-flash": "^0.0.2",
    "express-session": "^1.17.3",
    "mongoose": "^6.5.2",
    "passport": "^0.6.0",
    "passport-local": "^1.0.0"
  },
  "devDependencies": {
    "dotenv": "^16.0.1",
    "nodemon": "^2.0.19"
  }

server response log

<ref *2> ServerResponse {
  _events: [Object: null prototype] { finish: [Function: bound resOnFinish] },
  _eventsCount: 1,
  _maxListeners: undefined,
  outputData: [],
  outputSize: 0,
  writable: true,
  destroyed: false,
  _last: false,
  chunkedEncoding: false,
  shouldKeepAlive: true,
  maxRequestsOnConnectionReached: false,
  _defaultKeepAlive: true,
  useChunkedEncodingByDefault: true,
  sendDate: true,
  _removedConnection: false,
  _removedContLen: false,
  _removedTE: false,
  _contentLength: null,
  _hasBody: true,
  _trailer: '',
  finished: false,
  _headerSent: false,
  _closed: false,
  socket: <ref *1> Socket {
    connecting: false,
    _hadError: false,
    _parent: null,
    _host: null,
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: false,
      endEmitted: false,
      reading: true,
      constructed: true,
      sync: false,
      needReadable: true,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: false,
      dataEmitted: false,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] {
      end: [Array],
      timeout: [Function: socketOnTimeout],
      data: [Function: bound socketOnData],
      error: [Function: socketOnError],
      close: [Array],
      drain: [Function: bound socketOnDrain],
      resume: [Function: onSocketResume],
      pause: [Function: onSocketPause]
    },
    _eventsCount: 8,
    _maxListeners: undefined,
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: false,
      needDrain: false,
      ending: false,
      ended: false,
      finished: false,
      destroyed: false,
      decodeStrings: false,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: false,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 0,
      constructed: true,
      prefinished: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      errored: null,
      closed: false,
      closeEmitted: false,
      [Symbol(kOnFinished)]: []
    },
    allowHalfOpen: true,
    _sockname: null,
    _pendingData: null,
    _pendingEncoding: '',
    server: Server {
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _connections: 2,
      _handle: [TCP],
      _usingWorkers: false,
      _workers: [],
      _unref: false,
      allowHalfOpen: true,
      pauseOnConnect: false,
      noDelay: false,
      keepAlive: false,
      keepAliveInitialDelay: 0,
      httpAllowHalfOpen: false,
      timeout: 0,
      keepAliveTimeout: 5000,
      maxHeadersCount: null,
      maxRequestsPerSocket: 0,
      headersTimeout: 60000,
      requestTimeout: 0,
      _connectionKey: '6::::3033',
      [Symbol(IncomingMessage)]: [Function: IncomingMessage],
      [Symbol(ServerResponse)]: [Function: ServerResponse],
      [Symbol(kCapture)]: false,
      [Symbol(async_id_symbol)]: 18
    },
    _server: Server {
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _connections: 2,
      _handle: [TCP],
      _usingWorkers: false,
      _workers: [],
      _unref: false,
      allowHalfOpen: true,
      pauseOnConnect: false,
      noDelay: false,
      keepAlive: false,
      keepAliveInitialDelay: 0,
      httpAllowHalfOpen: false,
      timeout: 0,
      keepAliveTimeout: 5000,
      maxHeadersCount: null,
      maxRequestsPerSocket: 0,
      headersTimeout: 60000,
      requestTimeout: 0,
      _connectionKey: '6::::3033',
      [Symbol(IncomingMessage)]: [Function: IncomingMessage],
      [Symbol(ServerResponse)]: [Function: ServerResponse],
      [Symbol(kCapture)]: false,
      [Symbol(async_id_symbol)]: 18
    },
    parser: HTTPParser {
      '0': [Function: bound setRequestTimeout],
      '1': [Function: parserOnHeaders],
      '2': [Function: parserOnHeadersComplete],
      '3': [Function: parserOnBody],
      '4': [Function: parserOnMessageComplete],
      '5': [Function: bound onParserExecute],
      '6': [Function: bound onParserTimeout],
      _headers: [],
      _url: '',
      socket: [Circular *1],
      incoming: [IncomingMessage],
      outgoing: null,
      maxHeaderPairs: 2000,
      _consumed: true,
      onIncoming: [Function: bound parserOnIncoming],
      [Symbol(resource_symbol)]: [HTTPServerAsyncResource]
    },
    on: [Function: socketListenerWrap],
    addListener: [Function: socketListenerWrap],
    prependListener: [Function: socketListenerWrap],
    setEncoding: [Function: socketSetEncoding],
    _paused: false,
    _httpMessage: [Circular *2],
    timeout: 0,
    [Symbol(async_id_symbol)]: 64,
    [Symbol(kHandle)]: TCP {
      reading: true,
      onconnection: null,
      _consumed: true,
      [Symbol(owner_symbol)]: [Circular *1]
    },
    [Symbol(lastWriteQueueSize)]: 0,
    [Symbol(timeout)]: Timeout {
      _idleTimeout: -1,
      _idlePrev: null,
      _idleNext: null,
      _idleStart: 10625,
      _onTimeout: null,
      _timerArgs: undefined,
      _repeat: null,
      _destroyed: true,
      [Symbol(refed)]: false,
      [Symbol(kHasPrimitive)]: false,
      [Symbol(asyncId)]: 112,
      [Symbol(triggerId)]: 110
    },
    [Symbol(kBuffer)]: null,
    [Symbol(kBufferCb)]: null,
    [Symbol(kBufferGen)]: null,
    [Symbol(kCapture)]: false,
    [Symbol(kSetNoDelay)]: false,
    [Symbol(kSetKeepAlive)]: false,
    [Symbol(kSetKeepAliveInitialDelay)]: 0,
    [Symbol(kBytesRead)]: 0,
    [Symbol(kBytesWritten)]: 0,
    [Symbol(RequestTimeout)]: undefined
  },
  _header: null,
  _keepAliveTimeout: 5000,
  _onPendingData: [Function: bound updateOutgoingData],
  req: IncomingMessage {
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: null,
      ended: true,
      endEmitted: false,
      reading: false,
      constructed: true,
      sync: true,
      needReadable: false,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: true,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: true,
      dataEmitted: false,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: null
    },
    _events: [Object: null prototype] { end: [Function: clearRequestTimeout] },
    _eventsCount: 1,
    _maxListeners: undefined,
    socket: <ref *1> Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: [Server],
      _server: [Server],
      parser: [HTTPParser],
      on: [Function: socketListenerWrap],
      addListener: [Function: socketListenerWrap],
      prependListener: [Function: socketListenerWrap],
      setEncoding: [Function: socketSetEncoding],
      _paused: false,
      _httpMessage: [Circular *2],
      timeout: 0,
      [Symbol(async_id_symbol)]: 64,
      [Symbol(kHandle)]: [TCP],
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: Timeout {
        _idleTimeout: -1,
        _idlePrev: null,
        _idleNext: null,
        _idleStart: 10625,
        _onTimeout: null,
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: true,
        [Symbol(refed)]: false,
        [Symbol(kHasPrimitive)]: false,
        [Symbol(asyncId)]: 112,
        [Symbol(triggerId)]: 110
      },
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kSetNoDelay)]: false,
      [Symbol(kSetKeepAlive)]: false,
      [Symbol(kSetKeepAliveInitialDelay)]: 0,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(RequestTimeout)]: undefined
    },
    httpVersionMajor: 1,
    httpVersionMinor: 1,
    httpVersion: '1.1',
    complete: true,
    rawHeaders: [
      'Host',
      'localhost:3033',
      'Connection',
      'keep-alive',
      'Cache-Control',
      'max-age=0',
      'Upgrade-Insecure-Requests',
      '1',
      'User-Agent',
      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 Edg/104.0.1293.63',
      'Accept',
      'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
      'Sec-Fetch-Site',
      'same-origin',
      'Sec-Fetch-Mode',
      'navigate',
      'Sec-Fetch-User',
      '?1',
      'Sec-Fetch-Dest',
      'document',
      'sec-ch-ua',
      '"Chromium";v="104", " Not A;Brand";v="99", "Microsoft Edge";v="104"',
      'sec-ch-ua-mobile',
      '?0',
      'sec-ch-ua-platform',
      '"Windows"',
      'Referer',
      'http://localhost:3033/login',
      'Accept-Encoding',
      'gzip, deflate, br',
      'Accept-Language',
      'en-US,en;q=0.9,hi;q=0.8',
      'Cookie',
      'connect.sid=s%3AekT7kQM-iXdaK5fUM8b5ISPRGNUi_Jvx.SS5yn71YjFU1NZCFXVtlk4gw900PiUkqbH%2BLBEFPRlE',
      'If-None-Match',
      'W/"6-eGOtFq5DFbs3SMD6aWlJRytWFYg"'
    ],
    rawTrailers: [],
    aborted: false,
    upgrade: false,
    url: '/',
    method: 'GET',
    statusCode: null,
    statusMessage: null,
    client: <ref *1> Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: [Server],
      _server: [Server],
      parser: [HTTPParser],
      on: [Function: socketListenerWrap],
      addListener: [Function: socketListenerWrap],
      prependListener: [Function: socketListenerWrap],
      setEncoding: [Function: socketSetEncoding],
      _paused: false,
      _httpMessage: [Circular *2],
      timeout: 0,
      [Symbol(async_id_symbol)]: 64,
      [Symbol(kHandle)]: [TCP],
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: Timeout {
        _idleTimeout: -1,
        _idlePrev: null,
        _idleNext: null,
        _idleStart: 10625,
        _onTimeout: null,
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: true,
        [Symbol(refed)]: false,
        [Symbol(kHasPrimitive)]: false,
        [Symbol(asyncId)]: 112,
        [Symbol(triggerId)]: 110
      },
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kSetNoDelay)]: false,
      [Symbol(kSetKeepAlive)]: false,
      [Symbol(kSetKeepAliveInitialDelay)]: 0,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(RequestTimeout)]: undefined
    },
    _consuming: false,
    _dumped: false,
    next: [Function: next],
    baseUrl: '',
    originalUrl: '/',
    _parsedUrl: Url {
      protocol: null,
      slashes: null,
      auth: null,
      host: null,
      port: null,
      hostname: null,
      hash: null,
      search: null,
      query: null,
      pathname: '/',
      path: '/',
      href: '/',
      _raw: '/'
    },
    params: {},
    query: {},
    res: [Circular *2],
    body: {},
    secret: undefined,
    cookies: {
      'connect.sid': 's:ekT7kQM-iXdaK5fUM8b5ISPRGNUi_Jvx.SS5yn71YjFU1NZCFXVtlk4gw900PiUkqbH+LBEFPRlE'
    },
    signedCookies: [Object: null prototype] {},
    _parsedOriginalUrl: Url {
      protocol: null,
      slashes: null,
      auth: null,
      host: null,
      port: null,
      hostname: null,
      hash: null,
      search: null,
      query: null,
      pathname: '/',
      path: '/',
      href: '/',
      _raw: '/'
    },
    sessionStore: MemoryStore {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      sessions: [Object: null prototype],
      generate: [Function (anonymous)],
      [Symbol(kCapture)]: false
    },
    sessionID: 'ekT7kQM-iXdaK5fUM8b5ISPRGNUi_Jvx',
    session: Session { cookie: [Object], passport: [Object] },
    logIn: [Function (anonymous)],
    login: [Function (anonymous)],
    logOut: [Function (anonymous)],
    logout: [Function (anonymous)],
    isAuthenticated: [Function (anonymous)],
    isUnauthenticated: [Function (anonymous)],
    _sessionManager: SessionManager {
      _key: 'passport',
      _serializeUser: [Function: bound ]
    },
    _passport: { instance: [Authenticator] },
    user: [AsyncFunction (anonymous)],
    flash: [Function: _flash],
    route: Route { path: '/', stack: [Array], methods: [Object] },
    [Symbol(kCapture)]: false,
    [Symbol(kHeaders)]: {
      host: 'localhost:3033',
      connection: 'keep-alive',
      'cache-control': 'max-age=0',
      'upgrade-insecure-requests': '1',
      'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 Edg/104.0.1293.63',
      accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
      'sec-fetch-site': 'same-origin',
      'sec-fetch-mode': 'navigate',
      'sec-fetch-user': '?1',
      'sec-fetch-dest': 'document',
      'sec-ch-ua': '"Chromium";v="104", " Not A;Brand";v="99", "Microsoft Edge";v="104"',
      'sec-ch-ua-mobile': '?0',
      'sec-ch-ua-platform': '"Windows"',
      referer: 'http://localhost:3033/login',
      'accept-encoding': 'gzip, deflate, br',
      'accept-language': 'en-US,en;q=0.9,hi;q=0.8',
      cookie: 'connect.sid=s%3AekT7kQM-iXdaK5fUM8b5ISPRGNUi_Jvx.SS5yn71YjFU1NZCFXVtlk4gw900PiUkqbH%2BLBEFPRlE',
      'if-none-match': 'W/"6-eGOtFq5DFbs3SMD6aWlJRytWFYg"'
    },
    [Symbol(kHeadersCount)]: 36,
    [Symbol(kTrailers)]: null,
    [Symbol(kTrailersCount)]: 0,
    [Symbol(RequestTimeout)]: undefined
  },
  _sent100: false,
  _expect_continue: false,
  locals: [Object: null prototype] {},
  writeHead: [Function: writeHead],
  end: [Function: end],
  render: [Function (anonymous)],
  [Symbol(kCapture)]: false,
  [Symbol(kNeedDrain)]: false,
  [Symbol(corked)]: 0,
  [Symbol(kOutHeaders)]: [Object: null prototype] {
    'x-powered-by': [ 'X-Powered-By', 'Express' ]
  }
}

This is first time im learning backend so if you would, please explain its inner working too.

Solution

User is stored not in res but in req. So correct line is req.user.username.

And replace the deserializeUser function, which returns as second argument in your case function, not the user.

passport.deserializeUser(async (id, done) => {
        const user = await userDb.findById(id)
        if (user) {
               return done(null, user);
        }
        return done(null, false)
    });

Answered By – Fide

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published