Coverage area · 2 checks
Authentication: tokens, sessions and JWTs
Authentication bugs are rarely in the login form itself; they are in how tokens are verified and sessions are kept afterwards. OpenRouting reviews that code path end to end.
Illustrative example of how a finding in this area is reviewed.
Why this area matters
Identification and authentication failures are OWASP Top 10 A07. In token-based systems the classic mistakes are decoding a JWT without verifying its signature, accepting the none algorithm, ignoring expiry, and storing session tokens in cookies scripts can read (CWE-287, CWE-347, CWE-613).
Scanners flag every jwt.decode call, but many are fine: decoding a token you just verified, or reading an ID token's header to pick a key. The authentication agent checks whether verification actually happens before the claims are trusted.
What goes wrong in real applications
Unverified or forgeable tokens
Trusting a JWT's claims without verifying its signature, or accepting alg=none, lets anyone mint a token for any user.
Tokens that never expire
Missing or ignored expiry means a token leaked once — in a log, a screenshot, a browser history — works indefinitely.
Weak session cookies
Session cookies without HttpOnly, Secure and SameSite can be read by injected scripts, sent over cleartext, or ridden by cross-site requests.
Session fixation and missing rotation
Keeping the same session ID across login lets someone who set it beforehand inherit the authenticated session.
Sample: the risky pattern and the fix
import jwt
def current_user(request):
token = request.cookies.get("session")
claims = jwt.decode(token, options={"verify_signature": False})
return User.get(claims["sub"])
def login_response(resp, token):
resp.set_cookie("session", token, httponly=False, secure=False)import jwt
def current_user(request):
token = request.cookies.get("session")
claims = jwt.decode(
token, SIGNING_KEY, algorithms=["HS256"],
audience="openrouting-api", options={"require": ["exp", "sub"]},
)
return User.get(claims["sub"])
def login_response(resp, token):
resp.set_cookie("session", token, httponly=True, secure=True, samesite="Lax")The original reads claims from the token without checking the signature, so anyone can write their own token with any user ID. The fix verifies the signature against a pinned algorithm, requires expiry and subject, checks the audience, and stores the token in a cookie scripts can't read.
Illustrative code, simplified for clarity — not taken from a customer repository.
What OpenRouting checks in your repository
- JWT decode and verify calls: signature verification, algorithm pinning, exp/aud/iss checks
- Session cookie flags: HttpOnly, Secure, SameSite
- Session ID rotation on login and invalidation on logout
- OAuth callback handling: state parameter, redirect URI validation
- Whether a decode is preceded by verification elsewhere (the main false-positive signal)
Scope and limits
- It reviews authentication code in your repository; it doesn't attempt logins, test credential stuffing or check an external identity provider's settings.
- Settings held only in an identity provider's console (MFA policy, token lifetimes) aren't visible.
Coverage areas reflect OpenRouting's check library. Code, secret and infrastructure scanning run today; other areas are rolling out. Scanners surface candidates and a review agent decides whether each one is real — it doesn't promise to find every issue.
Review agents for this area
- Authentication & JWT — Checks that identity, tokens and sessions are actually verified and hardened.
- Access control & authorization — Checks that each sensitive action is authorized for the specific object, not just a logged-in user.
- Cryptography — Checks that cryptographic primitives fit their purpose and keys, IVs and randomness are handled correctly.
Common questions
Will it flag every jwt.decode?
Semgrep may flag them. The authentication agent marks decodes as likely false positives when the token was already verified, or when only the unverified header is read to choose a key.
Does it check password hashing?
Yes. Weak password hashing (MD5, SHA-1, unsalted hashes) is routed to the cryptography agent, which suggests Argon2 or bcrypt.