Safeguard
Application Security•

ASVS 5.0 V7.2.1: Verify Session Tokens on a Trusted Backend

ASVS V7.2.1 says session token checks must run on a trusted backend service, never in client code. See how to centralize verification and prove it.

Safeguard Security Team
3 min read

ASVS 5.0 V7.2.1 (Level 1) requires that all session token verification is performed by a trusted backend service. The browser, a mobile app or any other client the user controls can hold a token, but it must never be the thing that decides whether the token is valid.

Why it matters

Anything running on the client can be edited. If a single page app decides "this JWT looks fine, show the admin screen" and the API behind it trusts the same decision, an attacker only needs to change a few lines in developer tools. Verification belongs where the attacker cannot rewrite the code.

The same applies to internal hops. A microservice that accepts a user id from a header set by another service is trusting that service as the verifier, so that service must actually verify, and the path between them must be closed to outsiders.

How to implement it

Verify on every request at one choke point, such as middleware or a gateway, and make everything downstream depend on the result.

For a reference session token, look it up in a server side store:

async function requireSession(req, res, next) {
  const raw = req.cookies.sid;
  if (!raw) return res.sendStatus(401);
  const hash = crypto.createHash("sha256").update(raw).digest("hex");
  const session = await db.sessions.findOne({ hash, revoked: false });
  if (!session || session.expiresAt < Date.now()) return res.sendStatus(401);
  req.user = { id: session.userId };
  next();
}

For a signed token, verify the signature, issuer, audience and expiry with a maintained library, pinning the allowed algorithm:

const claims = jwt.verify(token, publicKey, {
  algorithms: ["RS256"],
  issuer: "https://auth.example.com",
  audience: "orders-api",
});

Do not decode without verifying. Do not read the algorithm from the token header and accept whatever it says.

How to test it

  • Send a request with no token, an expired token and a token with a tampered payload. Each must get a 401.
  • Take a valid signed token, change the role claim, keep the old signature, and confirm rejection.
  • Change the header algorithm to "none" and confirm rejection.
  • Search the front end bundle for logic that gates data on token contents. UI hiding is fine, but the API must enforce the same rule.

Common mistakes

  • Decoding a JWT in the client and treating the result as truth.
  • Verifying at the gateway but leaving internal services reachable directly.
  • Skipping audience checks, so a token for one service works on another.

Quick check

Is it fine for the client to read token claims?

Yes, for display purposes. It must never be the control that grants access.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.