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:ekT7kQM-iXdaK5fUM8b5ISPRGNUi_Jvx.SS5yn71YjFU1NZCFXVtlk4gw900PiUkqbH+LBEFPRlE',
'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:ekT7kQM-iXdaK5fUM8b5ISPRGNUi_Jvx.SS5yn71YjFU1NZCFXVtlk4gw900PiUkqbH+LBEFPRlE',
'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.
CodePudding user response:
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)
});
