May 14, 2026
JWT, OAuth, and Every Auth Method You’ll Meet in Web App Testing—Explained Simply
A no-fluff guide to JWT, OAuth 2.0, sessions, MFA, and every auth method you’ll attack as a tester.
Yamini Yadav_369
9 min read
If you're testing web apps — for security, for bugs, or just to understand how they work — authentication is where everything starts.
It's also where most things break.
Almost every serious vulnerability you'll find in a real-world app touches auth in some way: stolen tokens, broken sessions, weak password resets, OAuth misconfigurations, and JWTs that anyone can forge. If you understand auth deeply, you understand half of web security.
This post is your foundation. We'll go slow, and cover:
- What "authentication" and "authorization" really mean (they are not the same)
- Every common auth method — from old-school to modern
- JWT in deep detail — what it is, how it works, how it breaks
- OAuth 1.0 and OAuth 2.0 — what they are and why they exist
- How testers actually attack and verify these systems
Grab coffee. Let's go. ☕
1. Authentication vs Authorization — Know the Difference
People mix these up constantly. They're related but very different.
Authentication (AuthN) answers: Who are you? → Logging in with email + password. Authorization (AuthZ) answers: What are you allowed to do? → "Admins can delete users; regular users cannot."
Think of a hotel:
Authentication = the front desk checking your ID and giving you a keycard. Authorization = your keycard only opens your room and the gym, not the rooftop or other guests' rooms.
When you test an app, you test both, and bugs in either one are equally dangerous.
2. The Big Picture — How Web Apps Identify Users
Web apps need a way to remember who is making each request. HTTP itself is stateless — every request is independent, and the server doesn't remember anything from before.
So the app must include some kind of "I am user X" proof in every single request. That proof is what we call a credential or token.
The main strategies are:
- Session-based auth server keeps a session, client carries a session ID
- Token-based auth (JWT, etc.) client carries a self-contained signed token
- API keys — long secret string identifying an app or user
- Basic auth — username + password sent on every request
- OAuth / OAuth 2.0 — delegated auth ("Login with Google")
- OpenID Connect — identity layer built on top of OAuth 2.0
- SAML — enterprise XML-based single sign-on
- Multi-factor auth (MFA / 2FA) an extra layer on top of any of the above
- Biometric / WebAuthn / Passkeys modern passwordless
Let's walk through each.
3. Auth Method #1 — Basic Authentication
The oldest and simplest. The browser sends:
Authorization: Basic eW91cjp1c2VybmFtZTpwYXNz
That long string is just username: password encoded in Base64. Not encrypted — just encoded. Anyone who sees the request sees your password.
Tester's view:
Always check it's used over HTTPS only. Try echo "ZW1haWw6cGFzcw==" | base64 -d — it decodes to plain creds, proving why HTTP-only Basic auth is dangerous. Look for it on internal admin panels — a common place to find it left exposed.
4. Auth Method #2 — Session-Based Authentication (Cookies)
This is the classic web app auth.
How it works:
- You log in with email + password.
- Server checks the password is correct.
- Server creates a session (a record in its database/memory, e.g., session_id_abc123 → user_id_42).
- Server sends back a cookie: Set-Cookie: session_id=abc123.
- Your browser automatically attaches that cookie to every future request.
- Server looks up the session, knows it's you.
The key idea: the session ID is just a random string. The meaning lives on the server.
What testers look for:
Cookie flags: Are HttpOnly, Secure, and SameSite set? HttpOnly → JavaScript can't read it (blocks XSS theft) Secure → only sent over HTTPS SameSite → blocks CSRF attacks Session fixation: Does the session ID change after login? It must. Logout behaviour: Does the server actually invalidate the session, or just delete the cookie? Session timeout: Does it expire after inactivity? Predictable session IDs: Are they random enough?
5. Auth Method #3 — API Keys
A long secret string like:
sk_live_4f8a9b2c7d1e3f5a6b8c9d0e1f2a3b4c
Used mostly for: Server-to-server calls Developer/programmatic access Identifying applications, not end users
Sent in a header: Authorization: Bearer sk_live_… or sometimes x-api-key Tester's view: API keys leaked in JavaScript bundles, GitHub, and mobile apps are a very common bug Check for rate limiting per key Check that key permissions actually scope correctly (a read-only key shouldn't allow writes)
6. Auth Method #4 — Token-Based Authentication & JWT
Now we get to the meaty part. This is where JWT lives.
What is a token-based system?
Instead of the server maintaining session state, the client carries a signed token that proves their identity. The server just verifies the signature.
Benefits:
Stateless — server doesn't store sessions, scales horizontally easily Great for APIs and microservices Works well for mobile apps
Enter JWT (JSON Web Token)
A JWT looks like this — three Base64 chunks separated by dots:
**``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJZYW1pIiwicm9sZSI6ImFkbWluIn0.k3pY8Q2h7N1F3xS9wZf_M4hL5tRq6vC7
Three parts:
Three parts:
HEADER. PAYLOAD. SIGNATURE
_Part 1 — The Header_
Base64-decoded, it's just JSON:
``**`json
{
"alg": "HS256",
"typ": "JWT"
}**
_Part 1 — The Header_
Base64-decoded, it's just JSON:
``**`json
{
"alg": "HS256",
"typ": "JWT"
}**It says, "I am a JWT, signed with HMAC-SHA256."
Part 2 — The Payload (the "claims")
{
"sub": "12345",
"name": "Yami",
"role": "admin",
"iat": 1715000000,
"exp": 1715003600
} {
"sub": "12345",
"name": "Yami",
"role": "admin",
"iat": 1715000000,
"exp": 1715003600
}Standard claims: sub → subject (user ID) iat → issued-at time exp → expiration time iss → issuer aud → audience
Important: the payload is NOT encrypted. It's just Base64. Anyone can read it. Never put passwords or secrets in it.
Part 3 — The Signature
The server takes:
**HMAC-SHA256( base64(header) + "." + base64(payload), SECRET_KEY )
```**
And that's the signature.
When a request comes in, the server re-runs the same calculation. If the signature matches, the token is genuine. If anyone changes one
character of the payload, the signature breaks and the token is rejected.
How JWT auth flows in practice
1. User logs in with email + password.
2. Server verifies the password.
3. Server generates a JWT and sends it back.
4. Client stores it (localStorage, sessionStorage, or — better — an HttpOnly cookie).
5. Every API request includes: **HMAC-SHA256( base64(header) + "." + base64(payload), SECRET_KEY )
```**
And that's the signature.
When a request comes in, the server re-runs the same calculation. If the signature matches, the token is genuine. If anyone changes one
character of the payload, the signature breaks and the token is rejected.
How JWT auth flows in practice
1. User logs in with email + password.
2. Server verifies the password.
3. Server generates a JWT and sends it back.
4. Client stores it (localStorage, sessionStorage, or — better — an HttpOnly cookie).
5. Every API request includes:Authorization: Bearer eyJhbGciOi…
6. Server verifies the signature, reads the payload, and knows who the user is.
**JWT Vulnerabilities Every Tester Must Know**
This is gold for testing. JWTs are powerful but have classic attack patterns:
**1. The algorithm: none attack**
Old or misconfigured libraries accept tokens with "alg": "none" and no signature. An attacker just rewrites the payload (role: admin) and
removes the signature. If the server accepts it, game over.
**2. Algorithm confusion (RS256 → HS256)**
The server expects RS256 (asymmetric, uses public/private key pair). Attacker changes the header to HS256 (symmetric) and signs the token
using the server's public key as the HMAC secret. Vulnerable libraries accept it.
**3. Weak HMAC secret**
If the secret is something like "secret" or "password123", tools like hashcat or jwt_tool can brute-force it offline in seconds. Then the An
attacker can forge any token.
**4. No expiration check**
Tokens with no exp or with exp not actually validated → tokens live forever. Steal one once, use it forever.
**5. No revocation**
JWTs are stateless, so logging out doesn't truly invalidate them. If a token is stolen and there's no blocklist, the attacker keeps access
until expiry.
**6. Sensitive data in payload**
Putting emails, internal IDs, roles, or PII in the payload — readable by anyone who has the token.
**7. kid (key ID) injection**
Some implementations use kid to look up the signing key. If a kid is fed into a SQL query or file path, you can get path traversal or SQL injection
injection.
Tools to test JWTs:
jwt.io ([https://jwt.io](https://jwt.io)) — decode and inspect tokens
jwt_tool — automated JWT attacks
Burp Suite extension: JWT Editor
**7. Auth Method #5 — OAuth 1.0 (Briefly)**
OAuth was created to solve a real problem:
│ "I want to let App A read my data from App B — without giving App A my Service B password."
Example: a photo-printing site wanting to access your Flickr photos. Before OAuth, you'd have to give them your Flickr password. Terrible.
OAuth 1.0 (and 1.0a) introduced the idea of:
The user authorizes App A inside App B's website.
App B issues App A a token that represents the user's permission.
App A uses that token — never the password.
OAuth 1.0 also required request signing with HMAC, which made it secure even over plain HTTP. Cool, but complicated to implement correctly.
It's mostly historical now — Twitter used it for years. You should understand the concept but you'll rarely test 1.0 in the wild.
**8. Auth Method #6 — OAuth 2.0 (The Big One)**
OAuth 2.0 is the dominant delegated authorization framework today. Every "Sign in with Google / GitHub / Facebook / Microsoft" is OAuth 2.0.
Important: OAuth 2.0 is about authorization, not authentication
This is the most common misconception. OAuth 2.0 was designed to let one app access resources from another app on a user's behalf. People
bolted authentication onto it later (OpenID Connect, in section 9).
The four roles in OAuth 2.0
Resource Owner → You, the user
Client → The app that wants access (e.g., a photo-printing site)
Authorization Server → The server that issues tokens (e.g., Google's auth server)
Resource Server → The API holding the data (e.g., Google Photos API)
The most common flow — Authorization Code Flow
This is the one you'll see 90% of the time.
1. You click "Login with Google" on App A.
2. App A redirects you to Google's auth page with parameters:6. Server verifies the signature, reads the payload, and knows who the user is.
**JWT Vulnerabilities Every Tester Must Know**
This is gold for testing. JWTs are powerful but have classic attack patterns:
**1. The algorithm: none attack**
Old or misconfigured libraries accept tokens with "alg": "none" and no signature. An attacker just rewrites the payload (role: admin) and
removes the signature. If the server accepts it, game over.
**2. Algorithm confusion (RS256 → HS256)**
The server expects RS256 (asymmetric, uses public/private key pair). Attacker changes the header to HS256 (symmetric) and signs the token
using the server's public key as the HMAC secret. Vulnerable libraries accept it.
**3. Weak HMAC secret**
If the secret is something like "secret" or "password123", tools like hashcat or jwt_tool can brute-force it offline in seconds. Then the An
attacker can forge any token.
**4. No expiration check**
Tokens with no exp or with exp not actually validated → tokens live forever. Steal one once, use it forever.
**5. No revocation**
JWTs are stateless, so logging out doesn't truly invalidate them. If a token is stolen and there's no blocklist, the attacker keeps access
until expiry.
**6. Sensitive data in payload**
Putting emails, internal IDs, roles, or PII in the payload — readable by anyone who has the token.
**7. kid (key ID) injection**
Some implementations use kid to look up the signing key. If a kid is fed into a SQL query or file path, you can get path traversal or SQL injection
injection.
Tools to test JWTs:
jwt.io ([https://jwt.io](https://jwt.io)) — decode and inspect tokens
jwt_tool — automated JWT attacks
Burp Suite extension: JWT Editor
**7. Auth Method #5 — OAuth 1.0 (Briefly)**
OAuth was created to solve a real problem:
│ "I want to let App A read my data from App B — without giving App A my Service B password."
Example: a photo-printing site wanting to access your Flickr photos. Before OAuth, you'd have to give them your Flickr password. Terrible.
OAuth 1.0 (and 1.0a) introduced the idea of:
The user authorizes App A inside App B's website.
App B issues App A a token that represents the user's permission.
App A uses that token — never the password.
OAuth 1.0 also required request signing with HMAC, which made it secure even over plain HTTP. Cool, but complicated to implement correctly.
It's mostly historical now — Twitter used it for years. You should understand the concept but you'll rarely test 1.0 in the wild.
**8. Auth Method #6 — OAuth 2.0 (The Big One)**
OAuth 2.0 is the dominant delegated authorization framework today. Every "Sign in with Google / GitHub / Facebook / Microsoft" is OAuth 2.0.
Important: OAuth 2.0 is about authorization, not authentication
This is the most common misconception. OAuth 2.0 was designed to let one app access resources from another app on a user's behalf. People
bolted authentication onto it later (OpenID Connect, in section 9).
The four roles in OAuth 2.0
Resource Owner → You, the user
Client → The app that wants access (e.g., a photo-printing site)
Authorization Server → The server that issues tokens (e.g., Google's auth server)
Resource Server → The API holding the data (e.g., Google Photos API)
The most common flow — Authorization Code Flow
This is the one you'll see 90% of the time.
1. You click "Login with Google" on App A.
2. App A redirects you to Google's auth page with parameters:https://accounts.google.com/o/oauth2/v2/auth? client_id=APP_A_CLIENT_ID &redirect_uri=https://appA.com/callback &response_type=code &scope=email profile &state=xyz123
3. Google asks you: "App A wants access to your email and profile. Allow?"
4. You click Allow.
5. Google redirects you back to App A:3. Google asks you: "App A wants access to your email and profile. Allow?"
4. You click Allow.
5. Google redirects you back to App A:https://appA.com/callback?code=AUTH_CODE&state=xyz123
6. App A's server (not browser) takes that code and calls Google directly:
6. App A's server (not browser) takes that code and calls Google directly:
POST https://oauth2.googleapis.com/token { code: AUTH_CODE, client_id: …, client_secret: …, redirect_uri: … }
7. Google returns an access token (and usually a refresh token).
8. App A uses the access token to call Google's APIs on your behalf.
_Why the two-step (code → token) dance?_
So the access token never appears in the browser URL — only the short-lived auth code does. The token exchange happens server-to-server,
much safer.
Other OAuth 2.0 flows
**Implicit flow:** token returned directly in URL. Old, insecure, deprecated.
**Client credentials**: server-to-server, no user involved.
**Resource owner password credentials (ROPC):** the user gives the password to the client. Almost always wrong, deprecated.
**Device flow**: for TVs, IoT devices ("go to xxx.com/device and enter code ABC-123").
**PKCE (Proof Key for Code Exchange):** extension for mobile/SPA apps. Mandatory for public clients now.
**OAuth 2.0 Vulnerabilities Every Tester Must Know**
**1. Open redirect / redirect_uri manipulation**
If the auth server doesn't strictly validate redirect_uri, an attacker tricks the server into sending the auth code to their site. They
steal the code → exchange it → get access.
**2. Missing or unchecked state parameter**
The state parameter is your CSRF defence. If the client app doesn't verify it on return, an attacker can perform an OAuth login, CSRF and link
their account to the victim's session.
**3. Authorization code reuse**
Codes must be one-time use. If they can be reused, an attacker who intercepts one can replay it.
**4. Leaking tokens via Referer header**
If the app loads third-party scripts on the page that gets the token, those scripts can leak it via Referer or fetch.
**5. Misconfigured scopes**
Apps requesting waaay more scope than needed. Or scopes silently expanding.
**6. PKCE missing on public clients**
Mobile/SPA apps without PKCE → auth codes interceptable.
**7. JWT-as-access-token weaknesses**
Many OAuth implementations use JWTs as access tokens → all the JWT attacks above apply too.
Tools: Burp Suite, oauth.tools ([https://oauth.tools/](https://oauth.tools/)), browser dev tools.
**8. Auth Method #9 — MFA / 2FA**
Multi-factor auth = "something you know + something you have (+ something you are)."
Common forms:
TOTP (Google Authenticator, Authy):6-digit codes from a shared secret
SMS codes: convenient but vulnerable to SIM-swapping
Push notifications (Duo, Microsoft Authenticator)
Hardware tokens (YubiKey, FIDO2)
Email codes: common but only as secure as the email account
Tester's view:
Can MFA be bypassed by going directly to the post-login URL?
Is the MFA token tied to that specific session, or reusable?
Are there brute-force protections on the 6-digit code? (Only 1,000,000 combinations — must rate-limit!)
Can the "remember me" flag be abused?
Is MFA enforced for password reset, or can it be skipped that way?
**9. Auth Method #10 — WebAuthn / Passkeys (The Future)**
Passwordless. Uses public-key cryptography stored on your device (Touch ID, Face ID, YubiKey, Windows Hello).
The server stores only your public key. The private key never leaves your device. Phishing-resistant by design.
This is where the industry is heading. As a tester, focus on:
Fallback flows (if passkey fails → does it drop to a weaker method?)
Account recovery flows (often the weakest link)
Cross-device authentication
**_10. The Tester's Universal Auth Checklist_**
For any auth system you test, run through this:
**Account creation**
Email verification required?
Password strength enforced?
Username enumeration possible? (different errors for "user not found" vs "wrong password")
**Login**
- Rate-limited? Lockout after N attempts?
- Same response time for valid vs invalid users? (timing attacks)
- HTTPS only?
- Credentials never in URL?
**Session/token handling**
Cookie flags correct? (HttpOnly, Secure, SameSite)
Token expires? Renewable? Revocable?
Session ID rotates after login?
Logout actually invalidate the server-side?
**Authorization**
Can user A access user B's data by changing an ID? (IDOR)
Are admin endpoints actually protected, or just hidden?
Role checks happen server-side, not just client-side?
**Password reset**
Token random, single-use, short-lived?
Reset link sent only to verified email?
Old sessions invalidated after reset?
**MFA**
Required where claimed?
Skippable via password reset or alternate flow?
Rate-limited?
**OAuth / OIDC / SAML (if present)**
state and nonce validated?
Is redirect_uri strictly whitelisted?
PKCE used on public clients?
Are token signatures actually verified?
Auth is huge. You won't master it in one read — and that's fine. The trick is to understand the shape of each method: what it's for, what it
carries, where it can break.
Once you have that mental map, you can walk into any web app, look at the auth flow, and immediately know what to probe.
Happy hacking.7. Google returns an access token (and usually a refresh token).
8. App A uses the access token to call Google's APIs on your behalf.
_Why the two-step (code → token) dance?_
So the access token never appears in the browser URL — only the short-lived auth code does. The token exchange happens server-to-server,
much safer.
Other OAuth 2.0 flows
**Implicit flow:** token returned directly in URL. Old, insecure, deprecated.
**Client credentials**: server-to-server, no user involved.
**Resource owner password credentials (ROPC):** the user gives the password to the client. Almost always wrong, deprecated.
**Device flow**: for TVs, IoT devices ("go to xxx.com/device and enter code ABC-123").
**PKCE (Proof Key for Code Exchange):** extension for mobile/SPA apps. Mandatory for public clients now.
**OAuth 2.0 Vulnerabilities Every Tester Must Know**
**1. Open redirect / redirect_uri manipulation**
If the auth server doesn't strictly validate redirect_uri, an attacker tricks the server into sending the auth code to their site. They
steal the code → exchange it → get access.
**2. Missing or unchecked state parameter**
The state parameter is your CSRF defence. If the client app doesn't verify it on return, an attacker can perform an OAuth login, CSRF and link
their account to the victim's session.
**3. Authorization code reuse**
Codes must be one-time use. If they can be reused, an attacker who intercepts one can replay it.
**4. Leaking tokens via Referer header**
If the app loads third-party scripts on the page that gets the token, those scripts can leak it via Referer or fetch.
**5. Misconfigured scopes**
Apps requesting waaay more scope than needed. Or scopes silently expanding.
**6. PKCE missing on public clients**
Mobile/SPA apps without PKCE → auth codes interceptable.
**7. JWT-as-access-token weaknesses**
Many OAuth implementations use JWTs as access tokens → all the JWT attacks above apply too.
Tools: Burp Suite, oauth.tools ([https://oauth.tools/](https://oauth.tools/)), browser dev tools.
**8. Auth Method #9 — MFA / 2FA**
Multi-factor auth = "something you know + something you have (+ something you are)."
Common forms:
TOTP (Google Authenticator, Authy):6-digit codes from a shared secret
SMS codes: convenient but vulnerable to SIM-swapping
Push notifications (Duo, Microsoft Authenticator)
Hardware tokens (YubiKey, FIDO2)
Email codes: common but only as secure as the email account
Tester's view:
Can MFA be bypassed by going directly to the post-login URL?
Is the MFA token tied to that specific session, or reusable?
Are there brute-force protections on the 6-digit code? (Only 1,000,000 combinations — must rate-limit!)
Can the "remember me" flag be abused?
Is MFA enforced for password reset, or can it be skipped that way?
**9. Auth Method #10 — WebAuthn / Passkeys (The Future)**
Passwordless. Uses public-key cryptography stored on your device (Touch ID, Face ID, YubiKey, Windows Hello).
The server stores only your public key. The private key never leaves your device. Phishing-resistant by design.
This is where the industry is heading. As a tester, focus on:
Fallback flows (if passkey fails → does it drop to a weaker method?)
Account recovery flows (often the weakest link)
Cross-device authentication
**_10. The Tester's Universal Auth Checklist_**
For any auth system you test, run through this:
**Account creation**
Email verification required?
Password strength enforced?
Username enumeration possible? (different errors for "user not found" vs "wrong password")
**Login**
- Rate-limited? Lockout after N attempts?
- Same response time for valid vs invalid users? (timing attacks)
- HTTPS only?
- Credentials never in URL?
**Session/token handling**
Cookie flags correct? (HttpOnly, Secure, SameSite)
Token expires? Renewable? Revocable?
Session ID rotates after login?
Logout actually invalidate the server-side?
**Authorization**
Can user A access user B's data by changing an ID? (IDOR)
Are admin endpoints actually protected, or just hidden?
Role checks happen server-side, not just client-side?
**Password reset**
Token random, single-use, short-lived?
Reset link sent only to verified email?
Old sessions invalidated after reset?
**MFA**
Required where claimed?
Skippable via password reset or alternate flow?
Rate-limited?
**OAuth / OIDC / SAML (if present)**
state and nonce validated?
Is redirect_uri strictly whitelisted?
PKCE used on public clients?
Are token signatures actually verified?
Auth is huge. You won't master it in one read — and that's fine. The trick is to understand the shape of each method: what it's for, what it
carries, where it can break.
Once you have that mental map, you can walk into any web app, look at the auth flow, and immediately know what to probe.
Happy hacking.