Stateless web Architecture using REST API and JWT-cookie

Aniket Rai
3 min readSep 14, 2021

Stateless architecture provides scalability and lower server load and we can implement them using secure cookies (httpOnly).

API’s are essential parts for any development now days, weather you work on Website, Android or iOS. API’s are very helpful as they provide single contact point for all.

for example, you may have a single api route “/api/login” which takes the following JSON body.

{username : value. Password: value} 

for all the API knows it is only concerned with the request body, no matter where it comes from. So this single route can be called by your mobile app/ website, which in turns processes the authentication on the backend and provides an appropriate response. (Authentication True/False).

The same is true for all the other endpoints, This provides the advantage of creating a single monolithic backend for all the applications and only worry about the frontend.

API Setup

a. Using NodeJS and ExpressJS backend — it is a very quick way to spin up your API with few lines of code

const express =require('express');
const app =express();
const port = port_no;
app.use(express.json())app.listen(port,() => {
console.log(`App running on port ${port}.`)
})
app.post('/login',(req,res)=>{
// Process the incoming request here
})

From here we can use the request body to validate the user against the database and then mark the user as authenticated.(we can do it via sessions or cookie based token method)

Introducing JWT

In case of a stateless application we can create a json web token(JWT), which would look something like this in js.

const jwt = require("jsonwebtoken");
const dotenv = require("dotenv").config();
async function generateAccessToken(id) {
return jwt.sign(
{
uid: id, role: "user" },process.env.JWT_TOKEN_SECRET,
{ expiresIn: process.env.JWT_VALIDITY }
);
}

here we are using a secret key from the configuration file to sign the token with user specific values. Then we can pass this token as httpOnly Cookie to the user so that every request we receive from here on will have this cookie and we can parse it and validate in express using a middleware which on successful authentication will be forwarded to the api routs business logic.

if (true) { // auth success from DB
response
.status(200)
.cookie(
process.env.TOKEN_NAME,
await jwt.generateAccessToken(id),
{
secure: true,
httpOnly: true,
maxAge: process.env.JWT_VALIDITY,
sameSite: "strict",
path: "/",
}
)

One point to mention here is that keep the secure flag of in case of localhost testing.

Login process

from now on the user will pass on this token every time and on the server we will have a middleware that will validate this token every time.

Other API Calls

HttpOnly Cookie

const authorization = (req, res, next) => {
const token = req.cookies.access_token;
if (!token) {
return res.sendStatus(403);
}
try {
const data = jwt.verify(token, process.env.JWT_TOKEN_SECRET);
req.id= data.id;
req.userRole = data.role;
return next();
} catch {
return res.sendStatus(403);
}
};

here we created express middleware for token validation which we can add to every api.

app.post("/api/logout", jwt.authorization, auth.logout);// User Endpoints
app.get("/api/userDetails", jwt.authorization, db.userDetails);

Since httpOnly cookies are managed only from server side here is how the logout process would look like.

const logout = async (request, response) => {
response
.status(202)
.clearCookie(process.env.TOKEN_NAME)
.send(
JSON.stringify({
login: 0,
message: "Logout Success",
})
);
logger.info(`Logout Success`);
};

with that all our API’s are now secured and we are using all the benifits of stateless application.

Thank you for reading this article, would love to hear your suggestions.

--

--