The OAuth Vulnerability That Shook the Cybersecurity World
December 2020. Security teams at Microsoft, FireEye, and multiple US government agencies discovered they'd been breached. Not through a zero-day exploit or sophisticated malware.
Through stolen OAuth tokens.
The SolarWinds supply chain attack—one of the most sophisticated cyber operations in history—used a simple but devastating technique: OAuth token theft. Attackers compromised the SolarWinds Orion update mechanism, gained access to customer environments, and then stole OAuth access tokens.
What Made This So Devastating?
With stolen OAuth tokens, the attackers could:
- ✅ Access corporate email accounts (Microsoft 365)
- ✅ Read confidential documents (SharePoint)
- ✅ Impersonate legitimate users (no password needed)
- ✅ Bypass multi-factor authentication (MFA didn't matter—they had valid tokens)
- ✅ Maintain access for months (tokens refreshed automatically)
The impact:
- 18,000+ organizations potentially compromised
- Multiple US federal agencies breached (Treasury, Commerce, DHS, State Department)
- FireEye's red team tools stolen
- Estimated cost: $18+ million in incident response and remediation
Source: Microsoft Security Response Center, December 2020
The Core Problem: OAuth Token Lifecycle Misunderstanding
The attackers didn't need to crack passwords or bypass MFA. They just needed to understand something many developers and security engineers don't fully grasp:
OAuth tokens are bearer tokens - anyone who possesses a valid token can use it.
If you can't answer these questions in 60 seconds, you're vulnerable to the same class of attacks:
- How long should access tokens live?
- Why must refresh tokens rotate?
- What's the difference between public and confidential clients?
- How does PKCE prevent token theft?
Let's find out if you understand OAuth better than the organizations that got breached.
What Every Security Engineer Must Know About OAuth 2.0
After the SolarWinds breach, I spent 3 weeks diving deep into OAuth 2.0 security with OAuth 2 in Action by Justin Richer and Antonio Sanso (Manning Publications, 2017). The book is cited in Microsoft's post-breach security guidance.
📚 Prerequisite: Get the Book First
Before attempting this quiz, it is strongly recommended that you have a copy of OAuth 2 in Action (Manning Publications). This quiz is designed to test your understanding of concepts covered in:
- Chapter 2: The OAuth dance (pages 21-39)
- Chapter 3: Building a simple OAuth client (pages 43-58)
- Chapter 6: OAuth 2.0 in the real world (pages 93-118)
- Chapter 7: Common client vulnerabilities (pages 121-138)
The answer key references specific pages and chapters. Without the book, you'll miss the context and deeper explanations that make these concepts stick.
Get it here: OAuth 2 in Action on Manning.com
Why OAuth 2.0 Knowledge is Non-Negotiable
Here's the brutal truth:
- 95% of modern APIs use OAuth 2.0 (Google, GitHub, Stripe, Twitter, Microsoft 365)
- Every SaaS platform you integrate with uses OAuth (Salesforce, Slack, Zoom)
- OAuth token theft is now a standard advanced persistent threat (APT) technique
- You cannot fake OAuth knowledge in Security Engineering roles
The SolarWinds breach proved that understanding OAuth isn't just academic—it's about preventing nation-state level attacks.
The OAuth 2.0 Conceptual Quiz That Tests SolarWinds-Level Understanding
I created this quiz based on the OAuth vulnerabilities exposed by SolarWinds and real Security Engineering interview questions from companies like Trail of Bits, GitLab, Anthropic, and Stripe.
These aren't trick questions. These are the fundamentals that organizations failed to implement correctly—and paid the price.
Time yourself: 30 minutes. No Google. No ChatGPT.
Question 1: Mobile App Authentication
Scenario
You're building a mobile app (iOS and Android) that needs to access your backend API. The app will call these endpoints:
GET /api/user/profile - Returns user's profile (email, phone, DOB)
GET /api/posts - Returns user's posts (public and private)
POST /api/posts - Create new posts
PUT /api/user/profile - Update profile
DELETE /api/posts/{id} - Delete posts
Questions (Answer All 4)
1. Which authentication method should you use? (API Keys vs OAuth 2.0 vs mTLS)
2. If OAuth, which grant type? (Authorization Code, Client Credentials, Implicit, Resource Owner Password)
3. Why is this the appropriate choice for mobile apps?
4. Why would API Keys NOT work for this use case?
Write your answer in 5-8 sentences.
Question 2: PKCE Mechanics
The Question
"Walk me through how PKCE works and what attack it prevents. Explain the mechanics of code_verifier and code_challenge."
Your answer should cover:
- What PKCE stands for
- The attack scenario PKCE prevents (be specific)
- How
code_verifierworks (what, where generated, where stored) - How
code_challengeworks (what, how computed, where sent) - The verification step (how does auth server verify?)
- Why this prevents the attack
Write your answer in 6-10 sentences.
Question 3: State Parameter
The Question
"What's the state parameter in OAuth and why is it important? Explain the attack it prevents and how it works."
Your answer should cover:
- What the state parameter is (type of value, who generates it)
- When it's used (which steps in OAuth flow)
- What attack does it prevent?
- How does the attack work WITHOUT state parameter?
- How does state parameter prevent it?
- Bonus: Why constant-time comparison matters
Write your answer in 6-10 sentences.
Question 4: Token Refresh Flow
The Question
"How should an app handle expired access tokens? Walk me through the token refresh process."
Your answer should cover:
-
What happens when access token expires?(Skip - too implementation-specific) - What is a refresh token? (What, when issued, how long it lives)
- How does token refresh flow work? (Step-by-step)
- What does the authorization server return?
- Why should refresh tokens rotate?
- What happens to old refresh token after rotation?
Write your answer in 6-10 sentences.
⏸️ Stop Here - Try Answering Before Scrolling
Seriously. Get a piece of paper. Write your answers. You won't learn by just reading mine.
The difference between Security Engineers who pass interviews and those who don't is whether they can explain these concepts cold.
Answer Key
Question 1: Mobile App Authentication
Answer:
OAuth2 is best in this case. API Keys require the client handle an API key that has to constantly be sent to endpoints. This is risky since the API key can be stolen in a Man-in-the-Middle Attack. Even though TLS can mitigate this, API Keys have more issues. API Key Revocation is less sophisticated than OAuth2—where OAuth2 offers the use of a refresh token to replace an expired one.
mTLS is a great way to authenticate a client but does not give the resource owner the decision to authorize access to specific protected resources.
Authorization Code Grant Type is best practice. Keep in mind the user is using a mobile phone and therefore can authenticate themself using a web browser. User's login credentials are not seen by the client. They are instead passed to the authorization server (protected under TLS). The developers of the authorization server are free to decide how authentication should take place. This technique allows the client application to benefit from future improvements to user authentication.
Why not other grant types?
- Implicit grant is worse: No way for client to keep a secret. No way to use refresh tokens.
- Client Credentials grant: The resource owner has no opportunity to authenticate themselves. Only the client can decide when to access the sensitive info—not the resource owner!
- Resource Owner Credentials Grant Type is a bad idea since the resource owner gives away user credentials to client—and the client sends the user's credentials to the authorization server.
- Assertion Credentials Grant Type does not work since the client is acting on behalf of the resource owner.
PKCE is needed when using the Authorization Code Grant Type. PKCE will stop the attacker from intercepting stolen authorization codes.
Source: OAuth 2 in Action, Chapter 6 (pages 93-108)
Question 2: PKCE Mechanics
Answer:
PKCE stands for: Proof Key for Code Exchange
Attack prevented: Authorization Code Interception Attack - An attacker can steal an authorization code and send it to the authorization server.
How code_verifier works: A code_verifier is a randomly generated string of data. It is generated and stored on the client.
How code_challenge works: The code_challenge is a cryptographic message digest (e.g., SHA256) of the code_verifier. This prevents the authorization server, or anyone that compromises the authorization server, or anyone that steals the code_challenge, from deducing what the code_verifier is.
The preimage resistance property of cryptographic message digests prevents attackers from reversing the code_challenge back to the code_verifier.
The client sends the code_challenge to the authorization server.
Verification step: Later after the client has received the authorization code, the client makes a token request and attaches the code_verifier in its request. The authorization server calculates the cryptographic message digest of the code_verifier and checks if this digest matches the code_challenge. If so, request is approved and token is granted.
Why this prevents the attack: An attacker cannot use the stolen authorization code without knowledge of the code_verifier—which is supposed to be a long string generated by a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) that is hard to guess.
Source: OAuth 2 in Action, Chapter 7, Section 7.7 (pages 136-137); RFC 7636
Question 3: State Parameter
Answer:
What state is: The state parameter is a random string generated by a CSPRNG. It defends OAuth2 against CSRF attacks. Such an attack can waste client and server resources and cause the client to fetch a token that was never requested.
When it's used: It is passed in the first call to the authorization server. The authorization server replies with the state parameter as one of the parameters of the redirect URI. When the redirect URI is called, the client must check the validity of the state parameter before continuing the OAuth2 flow.
Attack prevented: CSRF (Cross-Site Request Forgery).
How the attack works WITHOUT state: If the state parameter is absent, the attacker can inject their own authorization code into the client—bypassing OAuth2 checks.
How state prevents it: The client compares the received state parameter against the stored state. If they don't match, the flow is terminated as a potential CSRF attack.
Constant-time comparison: Without constant-time comparison (in Python you can use hmac.compare_digest() for example), the attacker can deduce the state parameter while the client is comparing before performing redirection of URI. Timing attacks can leak information about which characters match.
Source: OAuth 2 in Action, Chapter 3 (pages 46-51), Chapter 7 (pages 122-125)
Question 4: Token Refresh Flow
Answer:
What is a refresh token: A refresh token can be used by OAuth2 to receive a new access token and refresh token.
How the flow works:
- Client requests access to protected resource using access token but receives an error.
- Client next sends refresh token to authorization server and receives new access token and new refresh token. Previously sent refresh token is now null-and-void.
- Client now requests access to protected resource using new access token and is approved for access.
What auth server returns: The new access token to access protected resource and new refresh token are both returned. The previously sent refresh token is now null-and-void.
Why rotate refresh tokens: Rotation of refresh tokens avoids the issue of an attacker stealing the refresh token to receive an access token. If that happens, an attacker can abuse the access token to gain access to protected resources. Rotation of refresh tokens renders the old refresh token null-and-void and replaces it with a different, new refresh token. To ensure this works, refresh tokens should be valid significantly longer than access tokens. Otherwise the refresh token expires too soon and the entire OAuth2 flow must start all over again from scratch.
What happens to old refresh token: It is null-and-void. Even if an attacker steals the old refresh token, the attacker will be unable to receive a new access token from the authorization server.
Source: OAuth 2 in Action, Chapter 3, Section 3.4 (pages 54-58); Chapter 5, Section 5.4 (pages 86-88)
How Did You Do?
Scoring Guide
- All 4 questions correct: You understand OAuth at the level needed to prevent SolarWinds-class attacks ✅
- 3/4 correct: Review OAuth 2 in Action chapters cited above - you have gaps that attackers exploit
- 2/4 or less: Your systems are vulnerable to token theft attacks - study OAuth fundamentals urgently
If you struggled with these questions, you're not alone. Many organizations that got breached in SolarWinds also didn't have engineers who could answer these correctly.
The good news: This knowledge is learnable. It took me 3 weeks of focused study to master these concepts.
Want More Security Engineering Practice?
I'm building AppSec-Exercises - a GitHub repository with LeetCode-style security challenges to help engineers like us master AppSec fundamentals:
🔗 github.com/fosres/AppSec-Exercises
What You'll Find:
✅ OAuth 2.0 Challenges - PKCE implementation, state validation, token refresh
✅ SQL Injection - Parameterized queries, ORM security, blind SQLi detection
✅ XSS Prevention - Context-aware encoding, CSP implementation
✅ CSRF Protection - Token validation, SameSite cookies
✅ API Security - Rate limiting, input validation, authentication
Why This Repo is Different:
- ❌ NOT "here's vulnerable code, find the bug"
- ✅ IS "implement this security feature correctly"
- Each exercise has ~30 automated test cases
- Inspired by Python Workout - learn by building
- Real interview questions from Trail of Bits, GitLab, Stripe
How to Use:
git clone https://github.com/fosres/AppSec-Exercises
cd AppSec-Exercises
python3 oauth_pkce_challenge.py # Start with OAuth
Each challenge includes:
- Clear problem statement
- Test cases (visible)
- No reference implementation (you build it)
- Links to authoritative sources (RFCs, OWASP)
⭐ Star the Repo if This Helped You
If this quiz helped you understand OAuth better, please star the repository. It helps other engineers find these resources.
👉 Star AppSec-Exercises on GitHub
Resources for Further Study
Books
- OAuth 2 in Action by Justin Richer & Antonio Sanso (Manning, 2017) - The definitive guide
- API Security in Action by Neil Madden (Manning, 2020)
- Full Stack Python Security by Dennis Byrne (Manning, 2021)
Online
- PortSwigger Web Security Academy - Free OAuth labs
- RFC 6749 - OAuth 2.0 Authorization Framework
- RFC 7636 - PKCE specification
My Learning Path
I document my Security Engineering journey on Dev.to/@fosres and GitHub. Follow along if you're also transitioning into AppSec!
One Last Thing: Prevention vs Reaction
The SolarWinds breach cost organizations millions in incident response. Microsoft had to build new token revocation infrastructure. Federal agencies had to assume their most sensitive communications were compromised.
All because OAuth token lifecycle management wasn't properly understood.
The difference between secure systems and breached systems isn't just intelligence or budget. It's understanding OAuth fundamentals deeply enough to implement them correctly.
These 4 questions represent the knowledge that could have prevented SolarWinds-level breaches if more security engineers deeply understood OAuth token security.
Don't wait for a breach to learn this. Master OAuth fundamentals now.
Good luck! 🚀
Did you find this helpful? Drop a comment with your quiz score and which question was hardest. Let's learn together.
Building your Security Engineering skills? *Star AppSec-Exercises** and let's grow this resource together.*
Top comments (0)