Broken access control happens when users can reach pages, APIs, or data they’re not allowed to. In React apps, the UI can hide buttons or routes—but real protection must also live on the server. Below is a concise, copy-pasteable playbook.
1) Route Guards (React Router v6)
Protect routes by role. Hide first in the UI, but enforce in code:
import { Navigate } from "react-router-dom";
import { useAuth } from "./auth"; // returns { user: { roles: [...] } }
const RequireRole = ({ role, children }) => {
const { user } = useAuth();
if (!user) return <Navigate to="/login" replace />;
if (!user.roles?.includes(role)) return <Navigate to="/403" replace />;
return children;
};
// usage
// <Route path="/admin" element={<RequireRole role="admin"><Admin/></RequireRole>} />
Tip: Prefer specific permissions (e.g., invoice:read
) over broad roles.
2) Don’t Trust the UI (Feature/Permission Checks)
Hiding a button ≠ security. Still, it improves UX and reduces casual misuse:
const can = (perm, user) => user?.perms?.includes(perm);
{can("invoice:read", user) && <a href="/invoices">View Invoices</a>}
{can("invoice:delete", user) ? <DeleteButton/> : <span>No delete rights</span>}
✅ Pair UI checks with server-side authorization (next sections).
Screenshot: Free Website Vulnerability Scanner tool Homepage
Scan your site for common misconfigurations and exposures with our free tool: free.pentesttesting.com.
3) Server-Side Authorization (Node/Express)
Always validate identity and permissions on the API:
import jwt from "jsonwebtoken";
const auth = (req, res, next) => {
const token = req.cookies?.token || req.headers.authorization?.replace("Bearer ","");
try { req.user = jwt.verify(token, process.env.JWT_SECRET); next(); }
catch { return res.status(401).json({ error: "Unauthenticated" }); }
};
const requirePerm = (perm) => (req, res, next) => {
if (!req.user?.perms?.includes(perm)) return res.status(403).json({ error: "Forbidden" });
next();
};
// routes
app.get("/api/invoices", auth, requirePerm("invoice:read"), listInvoices);
Object-Level Access (IDOR defense)
app.get("/api/projects/:id", auth, async (req, res) => {
const p = await Project.findById(req.params.id);
if (!p || p.ownerId !== req.user.id) return res.status(403).json({ error: "Forbidden" });
res.json(p);
});
4) Quick Checklist
- Enforce authN + authZ on every API route.
- Use least privilege permissions (fine-grained scopes).
- Validate resource ownership (no IDORs).
- Prefer HTTP-only cookies or short-lived JWTs; rotate secrets.
- Log denied attempts; add tests for “should NOT access”.
Sample Vulnerability Report to check Website Vulnerability
Example: a quick report snapshot you can generate from free.pentesttesting.com.
Further Reading & Tools
Managed Services & Offers
Managed IT Services
Stabilize, patch, and monitor your stack 24/7.
Learn more: https://www.pentesttesting.com/managed-it-services/
AI Application Cybersecurity
Threat-model and test LLM/AI features before launch.
Learn more: https://www.pentesttesting.com/ai-application-cybersecurity/
Offer Cybersecurity to Your Clients
Agencies/MSPs: white-label assessments and remediation.
Learn more: https://www.pentesttesting.com/offer-cybersecurity-service-to-your-client/
Stay Updated
Subscribe on LinkedIn: https://www.linkedin.com/build-relation/newsletter-follow?entityUrn=7327563980778995713
Pro tip: Publish this checklist in your repo’s /SECURITY.md
and enforce it in CI by testing “forbidden” paths, not just happy paths.
Top comments (0)