RC: W3 D2 — Demystifying session-based authentication
February 27, 2024Today, I decided it was high time I redid the small authentication app that p.b. showed us 10 days ago. Redoing it helped me clarify my thoughts as to session-based authentication. So here is how it works.
Say we have a simple authentication mechanism in which we store the encrypted password for each user in a database. Whenever a user wants to access a page:
- either they are already logged in — in which case they should be allowed access the requested page
- or they are not logged in — in which case they should be redirected to the login page.
The problem is that, if they refresh the page, or open it in a different tab, they would have to log in again (because the information is not stored anywhere).
We can overcome this with session-based authentication. To implement it, we need to create and store the information about the session so that we can access it on different pages. The simplest way to do this is by adding cookies: when the user logs in, if the password is correct, we add a cookie that says that the user is authenticated. And when the user tries to access the page, we read the cookie and grant access if the session indicates that the user is authenticated.
In practice, it looks like that:
const app = express()
// LOGIN PAGE
app.post("/login", async (_, res) => {
// ...
if (passwordIsCorrect) {
// Store information about the session in the database
const sessionId = nanoid() // Generate a UUID for the session
const session: Session = {userId: userId, authenticated: true}
DATABASE.setSession(sessionId, session)
// Add a cookie indicating sessionId
res.cookie('session', sessionId)
// Redirect to the home page
res.redirect("/home")
}
})
// HOME PAGE
app.get("/home", (req, res) => {
// Check if the user is authenticated
// - If yes, render the page
// - If no, redirect to the login page
if (isAuthenticated(req)) {
res.render("home")
} else {
res.redirect("/login")
}
})
// Check authentication by reading cookies
function isAuthenticated(req: Request) {
// Read cookies to get sessionId
const cookies = req.get("Cookie")
const sessionId = extractSessionId(cookies)
// Retrieve session information in the database
const session = DATABASE.getSession(sessionId)
return session?.authenticated
}
If you’re interested, the full implementation is in this repo.