diff --git a/content/guides.json b/content/guides.json index eec0d8b8d..b7a179d5e 100644 --- a/content/guides.json +++ b/content/guides.json @@ -1,4 +1,14 @@ [ + { + "id": "session-based-authentication", + "title": "Session Based Authentication", + "description": "Learn what is Session Based Authentication and how to implement it in Node.js", + "isNew": true, + "type": "textual", + "authorUsername": "kamranahmedse", + "updatedAt": "2022-11-01T19:59:14.191Z", + "createdAt": "2022-11-01T19:59:14.191Z" + }, { "id": "http-basic-authentication", "title": "HTTP Basic Authentication", @@ -13,7 +23,7 @@ "id": "basics-of-authentication", "title": "Basics of Authentication", "description": "Learn the basics of Authentication and Authorization", - "isNew": true, + "isNew": false, "type": "textual", "authorUsername": "kamranahmedse", "updatedAt": "2022-09-21T19:59:14.191Z", diff --git a/content/guides/session-based-authentication.md b/content/guides/session-based-authentication.md new file mode 100644 index 000000000..9b1878e7d --- /dev/null +++ b/content/guides/session-based-authentication.md @@ -0,0 +1,199 @@ +HTTP is the internet protocol that standardizes how clients and servers interact with each other. When you open a website, among other things, HTTP is the protocol that helps load the website in the browser. + +## HTTP is Stateless +HTTP is a stateless protocol which means that each request made from the client to the server is treated as a standalone request; neither the client nor the server keeps track of the subsequent requests. Sessions allow you to change that; with sessions, the server has a way to associate some information with the client so that when the same client requests the server, it can retrieve that information. + +In this guide, we will learn what is Session-Based Authentication and how to implement it in Node.js. We also have a separate [visual guide on Session-Based Authentication](/guides/session-authentication) as well that explains the topic visually. + +## What is Session-Based Authentication? +Session-based authentication is a stateful authentication technique where we use sessions to keep track of the authenticated user. Here is how Session Based Authentication works: + +* User submits the login request for authentication. +* Server validates the credentials. If the credentials are valid, the server initiates a session and stores some information about the client. This information can be stored in memory, file system, or database. The server also generates a unique identifier that it can later use to retrieve this session information from the storage. Server sends this unique session identifier to the client. +* Client saves the session id in a cookie and this cookie is sent to the server in each request made after the authentication. +* Server, upon receiving a request, checks if the session id is present in the request and uses this session id to get information about the client. + +And that is how session-based authentication works. + +## Session-Based Authentication in Node.js +Now that we know what session-based authentication is, let's see how we can implement session-based authentication in Node.js. + +Please note that, for the sake of simplicity, I have intentionally kept the project strictly relevant to the Session Based Authentication and have left out a lot of details that a production-ready application may require. Also, if you don't want to follow along, project [codebase can be found on GitHub](https://github.com/kamranahmedse/node-session-auth-example). + +First things first, create an empty directory that will be holding our application. + +```shell +mkdir session-auth-example +``` +Now run the following command to setup a sample `package.json` file: +```shell +npm init -y +``` +Next, we need to install the dependencies: +```shell +npm install express express-session +``` +`Express` is the application framework, and `express-session` is the package that helps work with sessions easily. + +### Setting up the server +Now create an `index.js` file at the root of the project with the following content: + +```javascript +const express = require('express'); +const sessions = require('express-session'); + +const app = express(); + +app.use(sessions({ + secret: "some secret", + cookie: { + maxAge: 1000 * 60 * 60 * 24 // 24 hours + }, + resave: true, + saveUninitialized: false, +})); + +app.use(express.json()); +app.use(express.urlencoded({extended: true})); + +// @todo register routes + +app.listen(3000, () => { + console.log(`Server Running at port 3000`); +}); +``` +The important piece to note here is the `express-session` middleware registration which automatically handles the session initialization, cooking parsing and session data retrieval, and so on. In our example here, we are passing the following configuration options: +* `secret`: This is used to sign the session ID cookie. Using a secret that cannot be guessed will reduce the ability to hijack a session. +* `cookie`: Object containing the configuration for session id cookie. +* `resave`: Forces the session to be saved back to the session store, even if the session data was never modified during the request. +* `saveUninitialized`: Forces an "uninitialized" session to be saved to the store, i.e., saves a session to the store even if the session was not initiated. + +Another important option is `store` which we can configure to change how/where the session data is stored on the server. By default, this data is stored in the memory, i.e., `MemoryStore`. + +Look at the [express-session documentation](https://github.com/expressjs/session) to learn more about the available options. + +### Creating Handlers +Create a directory called the `handlers` at the project's root. This is the directory where we will be placing all the route-handling functions. + +Now let's create the homepage route, which will show the welcome message and a link to log out for the logged-in users and redirect to the login screen for the logged-out users. Create a file at `handlers/home.js` with the following content. + +```javascript +module.exports = function HomeHandler(req, res) { + if (!req.session.userid) { + return res.redirect('/login'); + } + + res.setHeader('Content-Type', 'text/HTML) + res.write(` +