Broken Authentication in React.js: Fix It Fast

Why Broken Authentication Happens in React.js

React apps often leak auth via insecure token storage, trusting client flags, weak session handling, or missing rate-limits/MFA. Attackers turn these into account takeovers. For more security reads, explore the Pentest Testing Blog.

Broken Authentication in React.js: Fix It Fast

Mistake #1: Storing JWT in localStorage

Anti-pattern

// DON'T: token persists, XSS = full account takeover
const login = async (u, p) => {
  const r = await fetch('/api/login',{method:'POST',body:JSON.stringify({u,p})});
  const {token} = await r.json();
  localStorage.setItem('token', token);
};

Secure pattern: httpOnly cookie + CSRF

// DO: rely on httpOnly cookie; send CSRF from meta tag or /csrf endpoint
const login = async (u, p, csrf) => {
  await fetch('/api/login', {
    method:'POST',
    headers:{'Content-Type':'application/json','X-CSRF-Token':csrf},
    credentials:'include',
    body:JSON.stringify({u,p})
  });
};

Screenshot of the free Website Vulnerability Scanner tool homepage

Screenshot of the free tools webpage where you can access security assessment tools.
Screenshot of the free tools webpage where you can access security assessment tools.

Mistake #2: Trusting Client-Side “isLoggedIn”

Never gate routes with only a boolean or presence of a token. Always verify with the server.

// Route guard that checks the server
import {useEffect, useState} from 'react';
const useSession = () => {
  const [user,setUser]=useState(null);
  useEffect(()=>{
    fetch('/api/me',{credentials:'include'})
      .then(r=>r.ok?r.json():null).then(setUser).catch(()=>setUser(null));
  },[]);
  return user;
};

Mistake #3: Weak Login Protections (No Rate-Limit/Lockout)

Backends must slow brute force and protect sessions.

// Express.js: basic rate limit + safe compare
import rateLimit from "express-rate-limit";
import bcrypt from "bcrypt";
const limiter = rateLimit({ windowMs: 15*60*1000, max: 100 });
app.use('/api/login', limiter);

app.post('/api/login', async (req,res)=>{
  const {u,p}=req.body;
  const user = await db.users.findOne({u});
  if(!user || !(await bcrypt.compare(p,user.hash))) return res.status(401).end();
  // set signed, httpOnly, SameSite=strict cookie
  res.cookie('sid', createSession(user.id), {httpOnly:true, sameSite:'strict', secure:true});
  res.json({ok:true});
});

Sample assessment report from the free tool to check Website Vulnerability

Sample vulnerability assessment report generated with our free tool, providing insights into possible vulnerabilities.
Sample vulnerability assessment report generated with our free tool, providing insights into possible vulnerabilities.

Quick React Checklist

  • Use httpOnly cookies + SameSite=strict.

  • Fetch with credentials:'include' and a CSRF token.

  • Verify session via /api/me; avoid trusting stored tokens.

  • Add rate-limits, lockouts, and MFA.

  • Rotate/reset sessions on login, password change, and privilege change.

Run your site through our Website Vulnerability Scanner to spot auth flaws fast: free.pentesttesting.com.


Services to Help You Go Further

Managed IT Services

Harden identity, SSO, MDM, backups, and monitoring with our end-to-end ops team.
๐Ÿ‘‰ https://www.pentesttesting.com/managed-it-services/

AI Application Cybersecurity

Threat-model LLM features, secure prompts, and APIs powering your app.
๐Ÿ‘‰ https://www.pentesttesting.com/ai-application-cybersecurity/

Offer Cybersecurity to Your Clients

Agencies/MSPs: white-label our testing & compliance to grow revenue.
๐Ÿ‘‰ https://www.pentesttesting.com/offer-cybersecurity-service-to-your-client/

Subscribe on LinkedIn https://www.linkedin.com/build-relation/newsletter-follow?entityUrn=7327563980778995713

Comments

Popular posts from this blog

Fix Sensitive Data Exposure in Symfony Apps

Fix Security Misconfiguration Issues in Symfony

Open Redirect Vulnerability in Symfony