BACK TO JOURNAL
May 20, 20268 min read

Securing the Stack: Role-Based Authentication and Custom JWT Verification

Best practices for implementing secure user authentication in Node/Express applications using JWTs, HTTP-only cookies, and client side route guards.

SecurityJWTNode.jsExpress

Authentication is one of the most critical aspects of web development. In my blood donation platform, LifeDrop, failing to secure backend endpoints could mean exposing private donor records.

Here is how I architected a role-based authentication flow in Express and React.

1. Where to Store JWTs?

Storing JWTs in localStorage or sessionStorage is a major security risk. It makes your tokens vulnerable to Cross-Site Scripting (XSS) attacks. If an attacker injects a malicious script, they can easily read the token.

The solution: HTTP-only Cookies.

These cookies cannot be accessed via JavaScript (document.cookie returns empty), protecting them from XSS.

res.cookie('token', token, {
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: 'strict',
  maxAge: 3600000 // 1 hour
});

2. Role-Based Backend Middleware

Instead of verifying roles inside every controller, write a generic authorization middleware. This keeps your route definitions readable and safe:

const verifyRole = (allowedRoles) => {
  return (req, res, next) => {
    if (!req.user || !allowedRoles.includes(req.user.role)) {
      return res.status(403).json({ message: 'Forbidden: Insufficient privileges' });
    }
    next();
  };
};

// Usage
router.get('/admin/dashboard', verifyToken, verifyRole(['Admin']), getAdminData);

3. Frontend Route Guards

On the React frontend, we must protect pages from unauthorized navigation. Using React Router or Next.js middleware, check user roles stored in global state. If a normal donor tries to access the /admin route, redirect them to a fallback dashboard.

Structuring authentication this way keeps your application dry, modular, and highly secure.

S

Showaib Hossain

Mathematics Honors & MERN Developer

Get in touch →