Skip to content

Express: Result Page

Design a protected /result route that only logged-in students can access.

  • Use session middleware to verify if the student is logged in before allowing access to the route.

  • If the session is valid, the route should display the message: "Hi [name], your results are available!".

  • If the user is not logged in, it should return an access denied message: "Access denied: Please login to view results."

  • Add a /logout route that properly destroys the session and clears the login cookie.

app.js

js
import express from 'express';
import session from 'express-session';
import cookieParser from 'cookie-parser';

// --- App Initialization ---
const app = express();
const PORT = 3001;

// --- In-Memory Data (for demonstration purposes) ---
const users = [
    { id: 1, username: 'student1', name: 'Alice', password: 'password1' },
    { id: 2, username: 'student2', name: 'Bob', password: 'password2' }
];

// --- Middleware ---
app.use(express.json());

app.use(cookieParser());

// Configure session management
app.use(session({
    secret: 'a-very-secret-key-for-students',
    resave: false,
    saveUninitialized: false,
    cookie: { secure: false}
}));


// --- API Routes ---
app.post('/login', (req, res) => {
    const { username, password } = req.body;
    const user = users.find(u => u.username === username && u.password === password);

    if (!user) {
        return res.status(401).json({ error: 'Invalid username or password.' });
    }
    // Store the user's ID in the session
    req.session.userId = user.id;

	res.cookie( 'studentPortalAccess', 
		user.id, 
		{ maxAge: 3 * 60 * 1000 });
    
    res.json({ message: `Welcome, ${user.name}!` });
});


// Authentication Middleware
const authenticate = (req, res, next) => {
    if (!req.session.userId) {
        return res.status(401).json({ error: 'Access denied. Please log in.' });
    }
    
    next();
};


app.get('/result', authenticate, (req, res) => {
    // `authenticate` middleware has already verified the session.
    const user = users.find(u => u.id === req.session.userId);
    
    res.send(`Hi ${user.name}, your results are available!`);
});


app.post('/logout', (req, res) => {
    req.session.destroy(err => {
        if (err) {
            return res.status(500).json({ error: 'Logout failed. Please try again.' });
        }
        // The default session cookie is named 'connect.sid'
        res.clearCookie('studentPortalAccess');
        res.json({ message: 'Successfully logged out.' });
    });
});

// --- Start Server ---
app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});

All routes with ejs

Updated Express.js application with the protected /result route and a functional /logout route.

The key changes are the new authMiddleware function to protect routes and the addition of the /result and /logout endpoints.

app.js

js
import express from 'express';
import session from 'express-session';
import cookieParser from 'cookie-parser';
import path from 'path';
import { fileURLToPath } from 'url';

const app = express();
const PORT = 3000;

// Needed for __dirname in ES Modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// --- Middleware Setup ---
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(session({
    secret: 'a_secret_key_to_sign_the_cookie',
    resave: false,
    saveUninitialized: true,
    cookie: { secure: false }
}));

// Set EJS as the view engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// In-memory student database
const students = [];

// Custom middleware to check for authenticated session
const authMiddleware = (req, res, next) => {
    if (req.session && req.session.student) {
        return next(); // Session is valid, proceed to the route
    }
    // No valid session, deny access
    res.status(403).send('Access denied: Please login to view results.');
};

// --- Routes ---

// Render registration page
app.get('/register', (req, res) => {
    res.render('register');
});

// Handle registration logic
app.post('/register', (req, res) => {
    const { rollNo, name, password } = req.body;
    students.push({ rollNo, name, password });
    console.log('Students:', students);
    res.redirect('/login');
});

// Render login page
app.get('/login', (req, res) => {
    res.render('login');
});

// Handle login logic
app.post('/login', (req, res) => {
    const { rollNo, password } = req.body;
    const student = students.find(s => s.rollNo === rollNo && s.password === password);

    if (student) {
        req.session.student = { rollNo: student.rollNo, name: student.name };
        res.cookie('studentPortalAccess', student.rollNo, { maxAge: 3 * 60 * 1000 });
        res.redirect('/dashboard');
    } else {
        res.send('Invalid roll number or password.');
    }
});

// Render dashboard (protected)
app.get('/dashboard', authMiddleware, (req, res) => {
    res.render('dashboard', { student: req.session.student });
});

// NEW: Protected result route
app.get('/result', authMiddleware, (req, res) => {
    const studentName = req.session.student.name;
    res.status(200).send(`Hi ${studentName}, your results are available!`);
});

// NEW: Logout route
app.get('/logout', (req, res) => {
    req.session.destroy(err => {
        if (err) {
            // Handle error case, e.g., redirect to dashboard
            return res.redirect('/dashboard');
        }
        // Clear the cookie and redirect to login
        res.clearCookie('studentPortalAccess');
        res.redirect('/login');
    });
});


// Start the server
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}/register`);
});

EJS Files

The register.ejs and login.ejs files remain the same. The dashboard.ejs is updated to include a link to the new /result route.

views/dashboard.ejs (Updated)

html
<!DOCTYPE html>
<html lang="en">
<head><title>Dashboard</title></head>
<body>
    <h1>Welcome to the Student Portal, <%= student.name %>!</h1>
    <p>Your Roll Number is: <%= student.rollNo %></p>
    
    <p><a href="/result">View Your Results</a></p>
    
    <a href="/logout">Logout</a>
</body>
</html>

Run and Test

bash
npm init -y
npm install express express-session cookie-parser ejs

Then, ensure your package.json includes "type": "module".

node app.js
  1. Test without Logging In: Open a new private/incognito browser window and navigate directly to http://localhost:3000/result. You will see the "Access denied" message.

  2. Log In: Navigate to http://localhost:3000/login and log in with a registered student's credentials. You will be redirected to the dashboard.

  3. Access Results: From the dashboard, click the "View Your Results" link. You will be taken to the /result page and see the personalized welcome message.

  4. Log Out: From the dashboard, click the "Logout" link. You will be redirected back to the login page.

  5. Verify Logout: Try to navigate back to http://localhost:3000/dashboard or http://localhost:3000/result. You will be blocked and see the "Access denied" message again, confirming the session was successfully destroyed.

Made with ❤️ for students, by a fellow learner.