25 Capstone: Adding user authentication to Confetti Cuisine
This capstone walks through securing the Confetti Cuisine app by adding user authentication and better UX feedback. The author upgrades the app from simple user creation to a full login/logout flow grounded in sessions, cookies, and Passport.js, while introducing flash messaging for user-facing status and validation middleware to protect data integrity. By the end, the team can confidently sign users up (running locally for now), authenticate them, and communicate success or error states across redirects.
The setup begins by installing and wiring express-session, cookie-parser, connect-flash, express-validator, passport, and passport-local-mongoose. A simple login form (email and password) and corresponding routes/actions are added. Passport is initialized in Express with sessions, and the User model is enhanced with passport-local-mongoose to handle hashing/salting and to treat email as the username field—eliminating the need to store plain-text passwords. Registration uses User.register to create users, and flash messages are introduced via middleware and layout updates so users see immediate feedback after redirects.
Input validation is added with express-validator to sanitize emails, enforce ZIP code format, and require a password before reaching the create action; errors are aggregated into flash messages and short-circuit user creation when present. Authentication is completed with passport.authenticate using the local strategy, defining success/failure redirects and flashes. Finally, the UI gains session awareness through res.locals variables (loggedIn, currentUser), showing the active user’s name and a logout option, and a logout action clears the session with a confirmation flash. The result is a safer, clearer, and more reliable registration and login experience, ready for local testing and demonstration.
FAQ
Which packages do I need to add for secure login and validation?
- express-session: server-side session storage
- cookie-parser: signed cookies on the client
- connect-flash: flash messages across redirects
- express-validator: input sanitizing/validation
- passport: authentication middleware
- passport-local-mongoose: Passport helpers for Mongoose User model
Install: npm i express-session cookie-parser connect-flash express-validator passport passport-local-mongoose -S
How do sessions, cookies, and Passport work together in Express?
- cookie-parser signs and parses cookies sent by the browser.
- express-session creates/manages server-side sessions tied to those cookies.
- passport.initialize() sets up Passport; passport.session() stores/retrieves the authenticated user from the session.
- Use a strong secret for both cookie parsing and session signing.
How do I create the login form and routes?
- Create a login view with two fields: email and password; submit via POST.
- Routes:
- GET /users/login → render the login view.
- POST /users/login → usersController.authenticate (Passport).
- GET /users/logout → usersController.logout then redirect.
How do I enable Passport in my Express app?
- Require: passport, cookie-parser, express-session, and the User model.
- Use middleware in this order:
1) cookieParser(secret)
2) expressSession({ secret, resave: false, saveUninitialized: false, cookie: { maxAge } })
3) passport.initialize()
4) passport.session()
- Configure Passport with:
- passport.use(User.createStrategy())
- passport.serializeUser(User.serializeUser())
- passport.deserializeUser(User.deserializeUser())
How do I integrate passport-local-mongoose into the User model?
- Require passport-local-mongoose in the User model.
- userSchema.plugin(passportLocalMongoose, { usernameField: 'email' })
- This adds salt and hash fields and treats email as the username.
- Remove any plain-text password field from the schema and views.
How do I register new users and show flash messages?
- Ensure connect-flash is installed and router.use(connectFlash()) is set.
- Add middleware to expose flashes: res.locals.flashMessages = req.flash()
- In usersController.create:
- Build a new User from request data.
- Call User.register(newUser, password, callback)
- On success: flash a success message, set redirect, next()
- On error: flash an error message, set redirect to the signup form, next()
How do I display flash messages globally in my views?
- After setting res.locals.flashMessages = req.flash() in middleware, in your layout:
- Check if flashMessages exists.
- If flashMessages.success, render it.
- Else if flashMessages.error, render it.
- Place this markup above the body content so messages appear on all pages.
How do I validate signup data with express-validator before creating a user?
- Require express-validator and router.use(expressValidator()).
- Add usersController.validate before usersController.create in the POST /users/create route.
- In validate:
- Sanitize/normalize email, trim names.
- Check email format.
- Check zipCode is 5 digits and numeric.
- Ensure password is not empty.
- If errors: set req.skip = true, flash a combined error message, redirect to /users/new.
- Otherwise call next() to continue to create.
How do I authenticate on login and handle success/failure?
- usersController.authenticate should use passport.authenticate('local', { ...options })
- Options typically include:
- failureRedirect (e.g., /users/login)
- failureFlash (e.g., “Failed to login.”)
- successRedirect (e.g., /)
- successFlash (e.g., “Logged in!”)
How do I show the logged-in user in the UI and implement logout?
- In a middleware that runs on every request:
- res.locals.loggedIn = req.isAuthenticated()
- res.locals.currentUser = req.user
- In the layout:
- If loggedIn, display currentUser.fullName with a link and a “Log out” link.
- Else show a “Log in” link.
- In usersController.logout:
- Call req.logout(), flash a success message, set redirect to '/', next()
pro $24.99 per month
access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!