Upon successful authentication using the passport
module, a template was rendered with the req.user
object as shown below,
app.get('/', (req, res) => {
console.log(`Router get user: ${req.user}`);
console.log("Router get user of type: " + (typeof req.user));
res.render('index', {
layout: false,
user: req.user,
});
});
I verified the contents of req.user
through console.log
, and the user
object appeared as expected,
Router get user: {
_id: new ObjectId("629e3821bfb2869c42ac3c4b"),
username: 'me',
password: '123'
}
The second console.log
indicated that the type of req.user
is indeed an object
,
Router get user of type: object
After converting the req.user
to a string
,
app.get('/', (req, res) => {
console.log(JSON.stringify(req.user));
console.log("Router get user of type: " + (typeof req.user));
res.render('index', {
layout: false,
user: req.user,
});
});
the output transformed into,
{"_id":"629e3821bfb2869c42ac3c4b","username":"me","password":"123"}
Router get user of type: object
When I attempted to log req.user.username
like this,
app.get('/', (req, res) => {
console.log(req.user.username);
console.log("Router get user of type: " + (typeof req.user));
res.render('index', {
layout: false,
user: req.user,
});
});
I encountered the following error,
TypeError: Cannot read properties of undefined (reading 'username')
at /Users/Wei/github/play-js/express/authentication/src/app.js:87:24
However, when I used user.username
in the template file, it did not display the username.
<body>
{{#if user}}
<h1>WELCOME BACK {{user.username}}</h1>
{{/if}}
</body>
But when I replaced {{user.username}}
with {{user}}
, the user
object displayed correctly,
<body>
{{#if user}}
<h1>WELCOME BACK {{user}}</h1>
{{/if}}
</body>
WELCOME BACK { "_id": "629e3821bfb2869c42ac3c4b", "username": "me", "password": "123" }
As per the Handlebars Documentation, dot-separated paths are allowed in Handlebars expressions.
Hence, what could be causing this issue?
Below is the complete code illustrating how I set up the express
server and implemented passport
authentication,
// connect to MongoDB
const mongoDB = process.env.DB_URI;
mongoose.connect(mongoDB);
const db = mongoose.connection;
db.on('error', console.error.bind(console), 'MongoDB connection error');
// Schema & Model
const userSchema = new Schema({
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
}
});
const User = mongoose.model('User', userSchema);
// Express server
const app = express();
app.set('views', path.join(__dirname, 'views'));
const eh = handlebars.create(); // ExpressHandlebars instance
app.engine('handlebars', eh.engine); // register the engine() function
app.set('view engine', 'handlebars');
// Middleware
app.use(morgan('dev')); // logger
app.use(session({
secret: 'cats',
resave: false,
saveUninitialized: true,
}));
app.use(passport.initialize());
app.use(passport.session()); // this middleware will set cookie in client computer for each session.
app.use(express.urlencoded({
extended: false,
}));
// Verify username & password in our database
// Register the LocalStrategy to the passport.
passport.use(
new LocalStrategy(function verify(username, password, done) {
User.findOne({username: username}, (err, user) => {
if (err) return done(err);
if (!user) return done(null, false, {message: 'Incorrect username'});
if (user.password !== password) return done(null, false, {message: 'Incorrect password'});
return done(null, user);
});
})
);
// Only store user._id in the cookie.
passport.serializeUser(function(user, done) {
console.log(`serialize: ${user._id}`);
done(null, user._id);
});
// Get the user object from database by searching user._id.
passport.deserializeUser(function(_id, done) {
console.log(`deserialize search for: ${_id}`);
User.findById(_id, function(err, user) {
console.log(`deserialization find user: ${user}`);
done(err, user);
});
});
// router
app.get('/', (req, res) => {
console.log(JSON.stringify(req.user));
console.log("Router get user of type: " + (typeof req.user));
res.render('index', {
layout: false,
user: req.user,
});
});
app.post('/log-in', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/',
}));