02 config: Authentication- Login, Logout, Forgot

ยท

4 min read

๐Ÿ“0.1 ./app.js

// Load environment variables from .env file
require('dotenv').config({ path: './.env' });

// Import route handlers
var indexRouter = require('./routes/index.routes');
var userRouter = require('./routes/user.routes');

// Create an Express application
var app = express();

// Set up view engine
app.set('views', path.join(__dirname, 'views')); // Set views directory
app.set('view engine', 'ejs'); // Set view engine to EJS

// Database connection
const db = require('./models/db');
db.connectDB(); // Connect to the database

// Import user schema/model
const UserCollection = require('./models/user.schema');

// ------------- passport & session config -------------
const session = require('express-session');
const passport = require('passport');

// Configure session middleware
app.use(
  session({
    secret: process.env.SESSION_SECRET, // Session secret from environment variables
    resave: false, // Do not save session if unmodified
    saveUninitialized: true // Save uninitialized sessions
  })
);

// Initialize passport and session
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(UserCollection.serializeUser()); // Serialize user instance
passport.deserializeUser(UserCollection.deserializeUser()); // Deserialize user instance
// ------------- passport & session config -------------

// Export the app module
module.exports = app;

0.2 ๐Ÿ“./middleware/auth.js

// Middleware function to check if the user is authenticated
// const isLoggedIn = (req, res, next) => {
exports.isLoggedIn = (req, res, next) => {
    if (req.isAuthenticated()) {
        // If the user is authenticated, proceed to the next middleware or route handler
        return next();
    } else {
        // If the user is not authenticated, redirect to the login page
        res.redirect("/login");
    }
};

// Export the isLoggedIn function
// module.exports = isLoggedIn; // To fetch this function in another file without needing destructuring

0.3 ๐Ÿ“./routes/user.routes.js

// Import required modules
var express = require('express');
var router = express.Router();

// Import middleware for authentication check
const { isLoggedIn } = require('../middleware/auth');

// ------------ passport routes ------------ 
const passport = require('passport');
const LocalStrategy = require('passport-local');
const UserCollection = require('../models/user.schema');

// Configure passport to use the local strategy for authentication
passport.use(new LocalStrategy(UserCollection.authenticate()));
// ------------ passport routes ------------ 

/* GET users listing. */

// Route to handle user registration
router.post('/register', async (req, res, next) => {
  try {
    const { username, email, password } = req.body; // Extract user details from the request body
    const encryptedDetail = password; // Encrypt the password

    // Register the new user in the UserCollection
    await UserCollection.register({ username, email }, encryptedDetail);
    res.redirect("/login"); // Redirect to login page after successful registration
  } catch (err) {
    console.error("Error: ", err); // Log the error
    res.send("Error: ", err.message); // Send the error message as a response
  }
});

// Route to handle user login
router.post('/login',
  passport.authenticate("local", {
    successRedirect: "/user/profile", // Redirect to profile page on successful login
    failureRedirect: "/login", // Redirect to login page on failed login
  }),
  (req, res, next) => { }
);

// Route to display user profile, accessible only if logged in
router.get('/profile', isLoggedIn, (req, res, next) => {
  res.render("profile", { title: "Profile | Socialmedia", user: req.user }); // Render profile page with user details
});

// Route to handle user logout, accessible only if logged in
router.get('/logout', isLoggedIn, (req, res, next) => {
  req.logOut(() => {
    res.redirect('/login'); // Redirect to login page after logout
  });
});

// Export the router
module.exports = router;

0.4 ๐Ÿ“./views/partials/navbar.ejs

<nav class="flex justify-between h-[5rem] text-lg text-center font-semibold py-5 border-b-2 border-gray-300 " >    
    <div class="flex gap-8 ">
        <a href="/"        class="hover:border-b-2 border-black duration-100 px-6 py-1 text-[--nav-txt] hover:text-[--nav-txt-h] " >Home</a>
        <a href="/about"   class="hover:border-b-2 border-black duration-100 px-6 py-1 text-[--nav-txt] hover:text-[--nav-txt-h] " >About</a>
        <a href="/contact" class="hover:border-b-2 border-black duration-100 px-6 py-1 text-[--nav-txt] hover:text-[--nav-txt-h] " >Contact</a>        
    </div>
    <div class="flex gap-8" >

        <% if(user){ %>
            <a href="/user/logout" class=" bg-red-300 hover:bg-red-400 rounded-full  px-6 py-1 " >Logout</a>
        <% }else{ %>
            <a href="/login" class="    hover:border-b-2 border-black duration-100 text-[--nav-txt] hover:text-[--nav-txt-h] uppercase px-6 py-1 " >Login</a>
            <a href="/register" class=" bg-slate-300 hover:bg-slate-400 rounded-full uppercase px-6 py-1 " >Register</a>
        <% } %>
    </div>
</nav>

1. Register New User

๐Ÿ“./views/register.ejs

<form action="/user/register" method="post" class="flex flex-col justify-start gap-6 px-[5rem]">
    <input class="px-6 py-2 rounded-full  " type="email" name="email" id="" placeholder="Email">
    <input class="px-6 py-2 rounded-full  " type="text" name="username" id=""
      placeholder="Username">
    <div class="flex flex-col gap-3 ">
      <input class="px-6 py-2 rounded-full  " type="password" name="password" id=""
        placeholder="Password">
        <a href="/login" class="text-right underline font-semibold text-slate-600">Already have an account ?</a>
    </div>
    <button class="px-8 py-2 bg-[--secondary] rounded-full  text-white text-xl font-semibold"
      type="submit">Register</button>
</form>

2. Forgot Password

wait it will be updated soon ...

ย