JWT, Sessions and Account Recovery
Key confusion, JWK and kid injection, session lifecycle, password reset, MFA bypass, account recovery and where a passkey still falls back to a weaker channel.
A token can be cryptographically sound and still be the weakest part of the login, because the lifecycle around it, and the way back in when it is lost, are separate designs.
JWT Key Confusion
A public key can remain public and still become dangerous when the backend confuses asymmetric verification with HMAC. RS256 uses a private key to sign and a public key to verify. HS256 uses the same secret for both operations. A vulnerable implementation may accept alg=HS256 and reuse the RSA public key as an HMAC secret. I confirm the expected algorithm, library behavior, key loading and rejection of alternate algorithms before attempting forgery. Publishing a public key through JWKS is normal. The bug is algorithm and key selection, not public-key availability.
1
{"alg":"HS256","typ":"JWT"}
JWT JWK and JWKS Injection
A token should not be able to convince the verifier to trust a key selected by that same token without a prior trust relationship. Headers jwk and jku can embed or point to key material. That can be legitimate in specific protocols when the source is controlled. Unsafe verifiers accept an embedded JWK or fetch JWKS from an arbitrary URL supplied by the token. I inspect accepted headers, JWKS allowlists, TLS, issuer and kid-to-key-set association before testing an attacker-controlled key. SSRF may also appear if the verifier fetches arbitrary jku URLs server-side. Auth bypass and SSRF remain different findings even when one header triggers both.
1
{"alg":"RS256","jku":"https://keys.attacker.test/jwks.json","kid":"lab"}
JWT kid Injection
kid should select a known key. In a bad implementation it selects a file, database row or lookup the attacker can manipulate. Key ID helps the verifier locate the correct key inside a set. The value comes from a user-controlled header. Path traversal, SQL injection and cache poisoning appear when kid is directly concatenated into the lookup mechanism. I determine how keys are stored and look for error or timing differences while changing kid with harmless values. Even with a vulnerable lookup, the attacker still needs a signature accepted with the resulting key material. The complete chain should be demonstrated.
1
{"alg":"HS256","kid":"../../../../dev/null"}
Session Management
A session ID with 256 bits of entropy is still dangerous if it never rotates after login and remains valid after logout. Session security includes generation, storage, transport, rotation, timeout and invalidation. Entropy solves only one part. Session fixation appears when a pre-login identifier remains valid after authentication. Concurrent sessions and device revocation also matter. I compare cookies before and after login, privilege change, password reset and logout. I also test idle and absolute timeouts. Stateless JWT sessions do not eliminate session management. Revocation, refresh tokens and logout remain lifecycle decisions.
1
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax
Password Reset Flows
When password reset is easier to abuse than login, the attacker chooses the cheaper path. A secure reset flow needs account identification without excessive leakage, unpredictable tokens, limited lifetime and correct invalidation. Host header poisoning, token leakage, weak OTPs, user enumeration and session handling can turn recovery into account takeover. I test request, delivery, consumption and token invalidation separately using lab accounts. Changing a password should invalidate old reset tokens and, depending on product requirements, existing sessions. That effect needs to be explicit in the threat model.
1
2
3
4
5
POST /forgot-password HTTP/1.1
Host: app.example.test
Content-Type: application/x-www-form-urlencoded
email=lab-user%40example.test
MFA Bypass
MFA only improves security when every path creating a strong session actually requires the second factor. Bypass appears in alternate endpoints, remember-device tokens, recovery codes, mobile APIs, legacy authentication and state transitions between password and MFA steps. An application may mark the session authenticated too early or allow direct access after only the first factor. I map session states and test direct navigation, cookie reuse, user switching and endpoint access before second-factor validation. MFA fatigue and social engineering belong to another testing class. This article focuses on application logic and technical enforcement.
Compare the session cookie before the password step, after it and after MFA, and call the protected endpoint at each of the three states.
Account Recovery
Recovery exists to bypass a lost credential. That makes it one of the most sensitive flows around an account. Recovery flows may use email, SMS, support processes, backup codes, security questions or federated identity. Each alternative removes one control and introduces another. Email changes, MFA recovery and fallback to weaker channels are common downgrade points. I document every recovery route and try to chain the weakest one with partial sessions, predictable objects or data leaked by another API. Account takeover may require two medium findings. A changeable email plus reset delivery to the current email can create a stronger chain than either bug alone.
1
enrolled -> lost factor -> recovery -> new credential -> session
Magic Links and Passwordless
Magic links remove passwords from the experience. The token delivered by email now carries the full power of login. Passwordless links depend on unpredictable tokens, short lifetime, one-time use and correct binding to the account and browser when the design requires it. Email scanners, redirects, Referer leakage and preview bots may consume or expose tokens when the flow was not designed for intermediaries. I test replay, expiration, account swapping, open redirects and whether the GET authenticates before a safe confirmation step. A one-time token needs atomic invalidation. Two parallel requests may expose a race condition and allow double consumption.
1
2
GET /magic-login?token=4d1b2d7f... HTTP/1.1
Host: app.example.test
WebAuthn and Passkeys
A passkey can remove password phishing and still be implemented incorrectly when challenge, origin or RP ID are not bound to the right login. WebAuthn uses asymmetric credentials created by an authenticator. The server stores the public key and sends challenges to prove credential possession. RP ID, origin, challenge, user verification and credential ID need to belong to the same registration or authentication ceremony. I test challenge replay, account binding, origin, RP ID changes and fallback flows to passwords or recovery. A strong passkey loses value when account recovery still accepts a weak channel or the backend binds the credential to the wrong account.
Capture the registration and authentication JSON in a proxy, then compare challenge, origin, rpId and credentialId across two lab accounts.