Senior · Security-Focused Technique

Session & Authentication Testing

The login button works. But does the session expire correctly? Can a user see someone else's data by changing a URL? Is the JWT actually verified?

Senior ISTQB CTAL-TA 4.3 (Security Testing) — K4 Analyse ~12 min read + exercise

1 The Hook — Why This Matters

In 2021, an NZ fintech startup ran a penetration test before their Series A. The testers found five critical authentication flaws in a single afternoon. The worst: changing a single digit in the account summary URL displayed another customer's transaction history. No additional password or token was required.

That flaw is called an Insecure Direct Object Reference (IDOR). It is not an advanced hack. It is changing a 3 to a 4 in the address bar. The startup's QA team had tested login hundreds of times — valid credentials, invalid credentials, locked accounts — but never thought to test what happens after login.

They fixed it, delayed their launch by six weeks, and changed their hiring criteria. Session and auth testing is not just about whether the door opens. It is about whether the locks work after you are inside.

2 The Rule — The One-Sentence Version

Authentication proves who you are; authorisation proves what you can do; session management proves the system remembers correctly.

Most testers stop at authentication. They test username and password combinations and call the feature secure. A senior tester knows that the real vulnerabilities live in authorisation (can this user access that resource?) and session management (does the token expire, invalidate on logout, and resist tampering?).

3 The Analogy — Think Of It Like...

Analogy

A hotel key card system.

Authentication is showing your ID at reception to prove you booked the room. Authorisation is the key card only opening your door, not the penthouse. Session management is the card deactivating at checkout, or after 24 hours if you never check in. If the card still works after checkout, or opens every door in the building, the system is broken. Testing only the reception desk misses the entire risk.

4 Watch Me Do It — Step by Step

Here is the systematic approach for testing authentication, session management, and authorisation. I will use an NZ banking app as the running example.

  1. Test valid and invalid credential combinations Valid username + valid password should succeed. Valid username + invalid password should fail with a generic error (never reveal which field is wrong). Invalid username + any password should fail identically. Test account lockout after N failed attempts and verify unlock behaviour.
  2. Test multi-factor authentication flows For SMS, email, and authenticator app MFA: test valid code, expired code, reused code, code with transposed digits, and brute-force rate limiting. Verify that disabling MFA requires re-authentication. Check that backup codes work and are invalidated on use.
  3. Test session timeout and warning behaviour The specification says 15-minute idle timeout with a warning at 12 minutes. Set a timer. Leave the app idle for 11 minutes: no warning. At 12 minutes: warning appears. At 15 minutes: session terminates and the next action redirects to login. Test that refreshing the page does not reset the idle timer unfairly.
  4. Test logout and session invalidation Log out, then press the browser back button. A cached page must not reveal sensitive data. Copy the session cookie to another browser or incognito window; it must be rejected. Verify cookie flags: HttpOnly, Secure, and SameSite must be set correctly.
  5. Test token lifecycle and tampering (JWT) Decode the JWT at jwt.io. Verify the claims (sub, exp, iat, iss). Wait for expiry and confirm the API rejects the token. Modify the payload (e.g., change the user ID) and send it: signature verification must fail. Test with a missing signature algorithm header.
  6. Test authorisation and IDOR vulnerabilities Log in as a low-privilege user. Attempt to access high-privilege URLs directly (e.g., /admin/users, /api/account/1234 where 1234 is not your account). Change object IDs in URLs and API parameters. The system must return 403 Forbidden or 404, never another user's data.
  7. Test cross-tab and concurrent session behaviour Log in on Tab A. Log out on Tab B. Return to Tab A and perform an action: it must redirect to login, not silently fail. Test concurrent logins from different devices: does the system allow it, warn the user, or terminate the older session? Verify the behaviour matches the security policy.
  8. Test OAuth and SSO edge cases Cancel the OAuth flow at the provider. The application must return to the login screen with a clear error, not crash with a blank page or 500 error. Test login with an expired or revoked OAuth token. Verify that unlinking an SSO account requires password setup first.
Session & auth test matrix
Test case Input / Action Expected result
Valid loginCorrect credentialsSession created, redirect to dashboard
Invalid passwordWrong passwordGeneric error, no user enumeration
Session expiryIdle 15 minutesSession terminated, redirect to login
Logout + back buttonLogout, press BackCached data not displayed
JWT tamperingModified payloadSignature rejected, 401 response
IDOR attemptChange account ID in URL403 Forbidden, not other user's data
OAuth cancelCancel at providerReturn to login with clear error
Pro tip: Always test the API separately from the UI. A beautifully secure login page means nothing if the underlying /api/v1/account/{id} endpoint lacks authorisation checks. Use Postman, OWASP ZAP, or Burp Suite to send requests directly.

Second Example: Auckland Fintech Investment App

An Auckland-based fintech app lets users link multiple bank accounts, view balances, and set spending limits. The app uses JWT stored in localStorage. Testing reveals an IDOR and session weakness:

Test caseActionExpected resultActual resultRisk
IDOR: Change linked account IDLogin as User A. URL shows /account/5678/balance. Change 5678 to 5679 (User B's account).403 Forbidden or 404Displays User B's balance, holdings, and transaction historyCRITICAL — user data exposure, regulatory breach
Logout + token reuseCopy JWT before logout. After logout, send API request: GET /api/v1/account/5678/balance with old JWT in Authorization header.401 UnauthorizedAPI returns User A's balance; token still validCRITICAL — logout is broken; token persists server-side
Cross-tab session syncLogin on Tab A. Open Tab B to same site. Log out on Tab A. Return to Tab B and request a transaction.Session ends on both tabs; request redirects to loginTab B continues as if logged in; request succeedsHIGH — concurrent session state not synchronized

Remediation: (1) Add server-side authorisation check: verify that the authenticated user owns the requested account before returning data. (2) Implement token revocation: blacklist tokens on logout. (3) Use WebSocket or polling to sync logout events across tabs. (4) Consider storing JWT in HttpOnly cookie instead of localStorage to reduce XSS surface.

5 When to Use It / When NOT to Use It

✅ Use this when...

  • The application has user accounts, roles, or permissions
  • You are testing financial, health, or government systems
  • JWT, OAuth, or SSO is part of the architecture
  • Session timeout and concurrent login policies exist
  • A penetration test or security audit is scheduled

❌ Don't rely on this alone when...

  • The app is fully public with no user accounts or sessions
  • You have not tested basic functionality yet (login before lockout)
  • You lack permission to test security features (get written consent)
  • You are testing in production without a safe test environment
  • The token implementation is custom-built without cryptographic review

📋 Decision Checklist: Should You Test Session & Auth?

  • Does your app have user accounts or roles? If yes, session and auth testing is mandatory. Without it, you risk IDOR, privilege escalation, and data exposure.
  • Is written permission and a safe test environment available? Security testing must be intentional, not ad hoc. Never exploit production systems, and get approval from the business and security team first.
  • Do you have the right tools? You need Burp Suite, OWASP ZAP, or Postman to test APIs independently. Browser testing alone misses half the vulnerability surface.

6 Common Mistakes — Don't Do This

🚫 Only testing the happy path

I used to think: If valid credentials work and invalid ones fail, authentication is secure.
Actually: The dangerous flaws are in the edge cases. What happens with a token that expired 1 second ago? What happens if you replay an MFA code? What happens if you strip the signature from a JWT? Happy-path testing gives you false confidence.

🚫 Not testing token expiry mid-flow

I used to think: Token expiry is a backend concern; the frontend handles it gracefully.
Actually: Users routinely start a form, get distracted, and submit after their session expires. If the frontend does not detect the 401 and redirect cleanly, the user loses data and sees a cryptic error. Test mid-flow expiry on every multi-step process.

🚫 Assuming server-side validation exists

I used to think: The frontend blocks unauthorised actions, so the backend must too.
Actually: Frontend validation is for UX, not security. A malicious user can bypass your React form and hit the API directly with curl. Every authorisation rule must be enforced server-side. Test the API independently to verify this.

⚠ When It Fails

Session and auth testing fails when you test only the UI and miss the API. You log in to the web app, perform actions, and confirm everything works. But you never hit the backend endpoints directly with curl or Postman. A malicious attacker will. Your tests passed, but the API has no authorisation checks and anyone can access any user's data by changing a URL parameter. It also fails when you test only the happy path and miss edge cases. Valid login and logout work perfectly. But you never test token expiry during a multi-step form, MFA code reuse, or logout with an already-revoked token. The edge cases are where the vulnerabilities hide.

7 Now You Try — Spot the Flaw

🎯 Interactive Exercise

Scenario: You are testing an NZ insurance portal. After logging in, the URL is /policy/88421/summary. You notice the JWT is stored in localStorage. The logout button clears localStorage and redirects to the login page.

Question: List three security tests you would run immediately. Write them down before revealing the answer.

Three critical security tests:

  1. IDOR / authorisation test. Change 88421 to 88422 in the URL. You must not see another customer's policy. Verify both in the UI and by hitting the API directly.
  2. Session persistence after logout. Copy the JWT from localStorage before logging out. After logout, send an authenticated API request using that token. It must be rejected. If it succeeds, logout is broken.
  3. JWT storage vulnerability. localStorage is accessible to any JavaScript running on the domain, including malicious scripts from XSS. Verify the team has XSS protection. If possible, test whether the token works from a fresh incognito window with the copied value.

Tip: Storing JWTs in localStorage is a red flag for security-conscious testers. HttpOnly cookies are harder to steal via XSS.

8 Self-Check — Can You Actually Do This?

Click each question to reveal the answer. If you got all three, you're ready to practice.

Q1. What is an IDOR vulnerability?

Insecure Direct Object Reference (IDOR) occurs when a user can access another user's data by modifying a URL parameter, API path, or request body field — such as changing /account/123 to /account/124. The application fails to verify that the authenticated user owns the requested resource. It is one of the most common and serious authorisation flaws.

Q2. What three cookie flags should a secure session cookie have?

HttpOnly (prevents JavaScript access, mitigating XSS), Secure (sent only over HTTPS), and SameSite (prevents cross-site request forgery). Missing any of these increases attack surface. A senior tester verifies them in the browser's DevTools Network tab or with a proxy tool.

Q3. Why is testing the API separately from the UI important for auth?

Because the frontend is not a security boundary. A malicious actor or simple API client can bypass React validations, hidden fields, and disabled buttons. If the API does not independently enforce authentication and authorisation on every endpoint, the system is insecure regardless of how pretty the login form is.

9 Interview Prep — Q&A

Q. What is an IDOR vulnerability and how would you test for it?

IDOR (Insecure Direct Object Reference) lets users access resources they should not by manipulating identifiers. I test for it by logging in as User A, recording every URL and API call that contains an ID, then systematically changing those IDs to values belonging to User B. I verify that the server returns 403 or 404, never the other user's data. I automate this with Burp Suite's Intruder or OWASP ZAP's fuzzer for large ID ranges.

Q. How do you test session timeout behaviour?

I do not just wait. I use proxy tools or browser DevTools to inspect session cookies and JWT expiry claims. I test three scenarios: idle timeout (no activity), absolute timeout (hard limit regardless of activity), and mid-flow expiry (token dies while the user is filling a form). For each, I verify the warning timing, the redirect destination, and whether partial data is preserved. I also confirm that refreshing the page does not unfairly extend the session.

Q. What is the difference between authentication and authorisation?

Authentication answers "Who are you?" It validates identity via passwords, tokens, biometrics, or MFA. Authorisation answers "What are you allowed to do?" It enforces permissions after identity is proven. A user can be authenticated (logged in) but not authorised (blocked from admin functions). Testing both is essential; authentication without authorisation testing is incomplete.

Q. How would you test an OAuth 2.0 login integration?

I test the full flow: successful login, denied permissions at the provider, cancel mid-flow, expired provider token, revoked application access, and account linking/unlinking. I verify error messages are clear and do not leak implementation details. I confirm that the application never stores the provider password. I check that unlinking an SSO account requires setting a local password first, preventing account lockout.