TL;DR: JWT verification in a Next.js App Router app is easy to get almost right and still ship silent auth failures if you skip issuer, audience, algorithm, or runtime checks, according to WorkOS. The real control gap is not cryptography alone but where verification happens, because middleware, server components, and route handlers each fail differently if trust is misplaced.
NHIMG editorial — based on content published by WorkOS: How to verify JWTs in a Next.js App Router app
Questions worth separating out
Q: How should security teams verify JWTs in Next.js App Router apps?
A: Verify JWTs on the server with a library that works in both Edge and Node, then enforce signature, issuer, audience, and expiration checks on every token.
Q: Why do JWTs fail even when the signature is valid?
A: A valid signature only proves the token was not tampered with.
Q: What breaks when JWT verification is done only in middleware?
A: Middleware can be bypassed by configuration mistakes and it often only decides whether a request should continue.
Practitioner guidance
- Standardize on a single server-safe JWT library Use one library that runs in both Edge and Node so middleware, server components, and route handlers share the same verification logic.
- Verify issuer, audience, and algorithms explicitly Treat those checks as mandatory in every verification call.
- Re-verify claims at the enforcement point Use middleware for coarse routing decisions, then verify again in the server component or route handler that actually reads claims or authorizes access.
What's in the full article
WorkOS's full article covers the operational detail this post intentionally leaves for the source:
- Library-specific code examples for jose and jsonwebtoken across Edge and Node runtimes
- Complete middleware, server component, and route handler snippets for real Next.js App Router implementations
- JWKS caching behaviour and key rotation handling details for third-party token verification
- Practical token storage guidance covering cookies, localStorage, and refresh token handling
👉 Read WorkOS's guide to verifying JWTs in Next.js App Router →
JWT verification in Next.js App Router: where do controls break?
Explore further
JWT verification is an identity control, not a code utility. The article is really about trust boundaries: a token is only useful if the application verifies who issued it, who it was meant for, and whether it is still valid. That aligns with OWASP-NHI and Zero Trust thinking, because the application must continuously prove identity claims instead of assuming them from a decoded string. The practitioner takeaway is that JWT handling belongs in the same governance conversation as session trust and privilege assertion.
A few things that frame the scale:
- Only 1.5 out of 10 organisations are highly confident in their ability to secure NHIs, compared to nearly 1 in 4 for securing human identities, according to The State of Non-Human Identity Security.
- 85% of organisations lack full visibility into third-party vendors connected via OAuth apps, which shows how quickly federated trust becomes opaque once identity spans multiple systems.
A question worth separating out:
Q: How do you choose between HS256 and RS256 for JWTs?
A: Use HS256 only when signing and verification stay inside one tight trust boundary with a shared secret you can protect well. Use RS256 when tokens cross trust boundaries, multiple services verify them, or you need public-key distribution and JWKS-based rotation.
👉 Read our full editorial: JWT verification in Next.js App Router needs server-side controls