Most OAuth breaches do not break the protocol: they steal a token someone else was holding, abuse a consent nobody reviewed, or use a grant that should have been switched off years ago. OAuth 2.0 now sits behind almost every SaaS integration, mobile app, single-page app and machine-to-machine API call, so a single long-lived refresh token can carry more reach than an administrator password. This page ranks the ten OAuth security risks we see most often in real incidents and in the IETF's own guidance, with what goes wrong, how attackers use it, how to detect it and the fix. It is for identity architects, application security engineers, SaaS administrators and the security leaders who own third-party integration risk. Ranking is editorial: it weighs how often a risk appears in published incidents against how much damage it does when it does.
The Top 10 at a glance
- Long-lived tokens held by third-party integrations
- Illicit consent grants and consent phishing
- Over-broad scopes and application permissions
- Forgotten, unowned apps and test tenants
- Bearer tokens with no sender constraint
- Loose redirect URI validation and open redirectors
- Authorization code flows without PKCE or CSRF protection
- Legacy grants: implicit and resource owner password credentials
- Weak client authentication with shared secrets
- Resource servers that skip audience and issuer checks
| # | Risk | How attackers use it | First fix |
|---|---|---|---|
| 1 | Long-lived tokens held by integrators | Breach the vendor, replay its customers' refresh tokens | Inventory grants, rotate and expire refresh tokens, restrict where tokens work |
| 2 | Illicit consent grants | Trick a user into approving a malicious app | Restrict user consent, admin approval workflow, alert on new grants |
| 3 | Over-broad scopes | One token reads every mailbox or every CRM object | Least-privilege scopes, review application permissions |
| 4 | Forgotten apps and test tenants | Take over a stale app that still holds privilege | Owners, expiry and recertification for every app |
| 5 | Unconstrained bearer tokens | Replay a stolen token from any network | DPoP or mTLS sender-constrained tokens |
| 6 | Loose redirect URI checks | Redirect the code or token to an attacker's URL | Exact string matching, no open redirectors |
| 7 | No PKCE or CSRF protection | Inject or intercept authorization codes | PKCE with S256 for every client |
| 8 | Implicit and ROPC grants | Tokens in URLs, passwords handed to clients | Disable both; use authorization code with PKCE |
| 9 | Shared client secrets | Steal the secret, mint tokens as the app | private_key_jwt or mTLS client authentication |
| 10 | Missing audience and issuer checks | Replay a token at a different API, mix-up attacks | Validate aud, iss and scope at every resource server |
1. Long-lived tokens held by third-party integrations
The risk: when you connect a SaaS integration, the vendor stores a refresh token (and often an access token) that can act on your tenant for months. You cannot see how that vendor protects it, and you rarely notice when the vendor is breached.
Why it matters: this is the pattern behind the largest OAuth incidents. In the Salesloft Drift breach, an attacker who had reached Salesloft's GitHub account and then Drift's AWS environment used stored customer tokens between 8 and 18 August 2025 to export Salesforce records, then searched them for AWS keys, passwords and Snowflake tokens; Google said over 700 organisations were potentially affected. In the GitHub OAuth token breach of April 2022, user tokens issued to the Heroku Dashboard and Travis CI were stolen from those integrators and used to list and clone private repositories, including npm's. In neither case was the user phished or the identity provider exploited. ATT&CK tracks the reuse as T1550.001 (Use Alternate Authentication Material: Application Access Token).
The fix: keep an inventory of every connected app with its owner, scopes and last use; remove anything unused for 90 days. Enforce refresh token rotation and an absolute refresh token lifetime (OWASP ASVS 5.0 V10.4.8), and use IP or network restrictions on integration users where the platform supports them. When a vendor discloses a breach, treat every token it held as compromised: revoke, then rotate any secrets the token could read. See the OAuth Refresh Token Rotation and Expiry Guide and the SaaS integration token breach response.
2. Illicit consent grants and consent phishing
The risk: any user can approve a third-party app that asks for access to their mail, files or calendar. An attacker registers an app with a convincing name, sends a link to the real sign-in page, and the user grants access. No password is stolen and MFA is satisfied, because the user really did sign in.
Why it matters: the resulting refresh token survives a password reset, because revoking a password does not revoke consent. ATT&CK covers the theft as T1528 (Steal Application Access Token), delivered through T1566.002 (Spearphishing Link). OWASP ASVS 5.0 V10.7.2 requires the consent screen to give the user clear information about what they are approving, and V10.7.3 requires that users can review and revoke what they granted.
The fix: restrict user consent to low-risk permissions from verified publishers, route everything else through an admin consent request workflow, and alert on every new grant with high-impact scopes such as mail read, file read-write or offline access. Teach users that the consent screen is the attack, not the sign-in page. See the Consent Phishing and Illicit OAuth Grants Guide and the Entra ID Applications and Consent Guide.
3. Over-broad scopes and application permissions
The risk: integrations ask for the widest scope available because it is easier to build, and administrators approve it because the vendor says it is needed. Application permissions (app-only access with no user in the loop) are worse: they apply to every user in the tenant.
Why it matters: in the Microsoft Midnight Blizzard breach, the attacker granted its OAuth apps the Exchange Online full_access_as_app application permission, which read corporate mailboxes, including senior leadership's, without signing in as each user. RFC 9700 section 2.3 says access token privileges should be restricted to the minimum required and tokens should be audience-restricted to the specific resource server.
The fix: the client should request only the scopes it needs (ASVS V10.2.3) and the authorization server should assign only those scopes to that client (ASVS V10.4.11). Flag tenant-wide application permissions for mail, files, directory write and role management as tier 0 and require a named approver. Where the API supports it, use resource-scoped permissions (for example, a single mailbox or site) instead of tenant-wide ones. See the OAuth Scope Design Guide.
4. Forgotten, unowned apps and test tenants
The risk: app registrations, service principals and connected apps outlive the project and the person who created them. Test tenants keep production trust. Nobody reviews them because nobody owns them.
Why it matters: Midnight Blizzard got in by password spraying (T1110.003) a legacy test tenant account without MFA, then took over a legacy test OAuth application that still had elevated access to Microsoft's corporate environment, and created new apps for persistence. ATT&CK v20 tracks adding malicious integrations for persistence as T1671 (Cloud Application Integration), and granting extra roles to an app as T1098.003 (Account Manipulation: Additional Cloud Roles).
The fix: every app needs an owner, a business purpose, an expiry or review date and a record of its permissions. Recertify high-privilege apps quarterly as you would privileged users. Delete or disable apps with no sign-ins in 90 days, and apply the same MFA, conditional access and monitoring to test and development tenants that hold any trust into production. See the SaaS and OAuth App Governance Guide and the APT29 (Midnight Blizzard) Threat Actor Profile.
5. Bearer tokens with no sender constraint
The risk: a plain bearer token works for whoever presents it. If it leaks from a log, a browser, a vendor database or a developer laptop, the attacker can use it from anywhere until it expires.
Why it matters: RFC 9700 section 2.2.1 says authorization and resource servers should use sender-constrained access tokens, naming mutual TLS (RFC 8705) and DPoP (RFC 9449). Section 2.2.2 says refresh tokens for public clients must be either sender-constrained or rotated. Without either, refresh token theft gives an attacker long-term access that looks like the legitimate client.
The fix: use DPoP for browser and mobile clients and certificate-bound tokens (mTLS) for server-to-server traffic where your authorization server supports them. ASVS V10.3.5 asks resource servers to require sender-constrained tokens, and V10.4.5 asks authorization servers to mitigate refresh token replay for public clients, preferably with DPoP. Where you cannot yet bind tokens, keep access tokens short-lived (minutes, not hours) and rotate refresh tokens with reuse detection. See the DPoP Guide and the mTLS Guide.
6. Loose redirect URI validation and open redirectors
The risk: the authorization server accepts redirect URIs by prefix, wildcard or pattern, or the client site has an open redirect. An attacker crafts an authorization request that sends the code or token to a URL they control.
Why it matters: RFC 9700 section 2.1 requires exact string matching of redirect URIs, with one exception for the port number of localhost redirect URIs used by native apps, and says clients and authorization servers must not expose open redirectors. Pattern matching has repeatedly been bypassed with subdomain, path and encoding tricks. Codes and tokens can also leak through the Referer header when the page after authorization loads third-party content (RFC 9700 section 4.2.4).
The fix: register full redirect URIs per client and compare them exactly (ASVS V10.4.1). Remove wildcards from existing registrations, scan client applications for open redirects, and keep third-party scripts and links off the redirect landing page. See the Open Redirect Guide.
7. Authorization code flows without PKCE or CSRF protection
The risk: without Proof Key for Code Exchange, an intercepted or injected authorization code can be redeemed by someone other than the client that started the flow. Without CSRF protection, an attacker can log a victim into the attacker's account or bind the attacker's resources to the victim's session.
Why it matters: RFC 9700 section 2.1.1 says public clients must use PKCE, confidential clients should use it, and authorization servers must support it; S256 is the transformation to use. Section 4.8.2 describes a PKCE downgrade, where the server must reject a token request carrying a code_verifier if the authorization request had no code_challenge.
The fix: require PKCE with S256 for every client, public and confidential (ASVS V10.4.6), and make authorization codes single use and short-lived: ASVS V10.4.2 and V10.4.3 allow a maximum of 10 minutes at levels 1 and 2 and 1 minute at level 3. Keep a one-time state value as well if any client cannot rely on PKCE or the OpenID Connect nonce (ASVS V10.2.1). See the PKCE Implementation guide.
8. Legacy grants: implicit and resource owner password credentials
The risk: the implicit grant returns access tokens in the URL fragment, where they end up in browser history and logs. The resource owner password credentials (ROPC) grant makes the user type their password into the client, which defeats MFA, federation and phishing resistance.
Why it matters: RFC 9700 says clients should not use the implicit grant (section 2.1.2) and that ROPC must not be used (section 2.4). Section 4.3.2 adds that clients must not pass access tokens in URI query parameters. Both grants survive in older single-page apps, scripts and mobile apps long after the guidance changed.
The fix: per client, allow only the grants that client needs (ASVS V10.4.4). Move single-page apps to authorization code with PKCE, ideally behind a backend-for-frontend so tokens never reach JavaScript (ASVS V10.1.1). Replace ROPC in scripts and automation with the client credentials grant or workload identity federation. See the OAuth for Browser-Based Applications and the BFF Pattern Guide and the OAuth for Native and Mobile Apps Guide.
9. Weak client authentication with shared secrets
The risk: confidential clients authenticate with a static client secret that is copied into configuration files, CI variables and vendor portals. Anyone who finds it can request tokens as the application, often with application permissions and no user involved.
Why it matters: client secrets are just passwords for software, with the same leak paths as any other secret. RFC 9700 section 2.5 says authorization servers should enforce client authentication where feasible and recommends asymmetric methods such as mTLS or private_key_jwt, which keep the private key with the client and never send a reusable secret.
The fix: authenticate confidential clients on every back-channel request (ASVS V10.4.10), prefer private_key_jwt or mTLS (ASVS V10.4.16 at level 3), store keys in a secrets manager or HSM, and set expiry on every remaining client secret. For workloads on cloud platforms, workload identity federation removes the stored secret entirely. See the Machine-to-Machine OAuth (Client Credentials) Guide.
10. Resource servers that skip audience and issuer checks
The risk: an API accepts any validly signed token from a trusted issuer without checking that the token was meant for it, or a client that talks to several authorization servers does not check which one answered.
Why it matters: a token issued for a low-value API can then be replayed against a high-value one. In a mix-up attack, a client that uses more than one authorization server can be tricked into sending a code or token to the wrong one; RFC 9700 section 4.4.2 requires clients to store the issuer per request and abort on mismatch, using the iss response parameter defined in RFC 9207.
The fix: at every resource server, validate signature, issuer, audience, expiry and scope before any authorization decision (ASVS V10.3.1), and base access on the token's delegated claims, not just on the presence of a token (ASVS V10.3.2). Clients that use multiple authorization servers must implement mix-up defence (ASVS V10.2.2). See the OAuth Token Introspection and Revocation Guide.
Detecting OAuth abuse
Most of these risks are invisible in authentication logs because the attacker never signs in interactively. Watch the token and app layer instead.
| Signal | Where to find it | Risks it catches |
|---|---|---|
| New consent grant with high-impact scopes | Identity provider audit log (consent and app role assignment events) | 2, 3 |
| New credential (secret or certificate) added to an existing app | Identity provider audit log, app registration changes | 4, 9 |
| Refresh token or app token used from a new IP range, ASN or country | Sign-in logs for service principals, SaaS event logs | 1, 5 |
| Bulk export or unusual query volume by an integration user | SaaS API and event monitoring logs (for example CRM bulk API jobs) | 1, 3 |
| Refresh token reuse after rotation | Authorization server logs | 1, 5 |
| Token use after revocation, or by a disabled app | Resource server logs | 1, 4 |
| Authorization requests with unregistered redirect URIs or missing code_challenge | Authorization server error logs | 6, 7 |
Five measures show whether the programme is working: the percentage of connected apps with a named owner (target 100%), apps unused for 90 days still holding grants (target zero), tenant-wide application permissions on mail, files or directory (trend down), clients still allowed implicit or ROPC grants (target zero), and median time from vendor breach notice to revocation of that vendor's tokens (hours, not days). See How to detect use of a stolen OAuth refresh token.
Lessons from incidents
- The vendor's breach is your breach: in both the Salesloft Drift and the 2022 GitHub incidents, customers did nothing wrong at sign-in. Their exposure was set by which tokens they had granted and what those tokens could read.
- Secrets in data multiply the damage: the Drift attacker searched exported CRM records for cloud keys, and the GitHub attacker used an AWS key found in a cloned npm repository. Scan support cases, CRM notes and repositories for credentials.
- Apps are identities: Midnight Blizzard turned a forgotten test app into mailbox access. Apps need the ownership, review and monitoring you give privileged users. See the OAuth and SaaS integration breaches guide for more cases.
Mapping to OWASP
| Risk | OWASP ASVS 5.0 (V10) | MITRE ATT&CK v20 | NIST SP 800-53 Rev. 5 |
|---|---|---|---|
| 1. Long-lived integrator tokens | V10.4.8, V10.4.9 | T1550.001 | IA-5, AC-2 |
| 2. Illicit consent grants | V10.7.2, V10.7.3 | T1528, T1566.002 | AC-2, AC-6 |
| 3. Over-broad scopes | V10.2.3, V10.4.11 | T1098.003 | AC-6 |
| 4. Forgotten apps and test tenants | Not mapped | T1671, T1110.003 | AC-2, CM-7 |
| 5. Unconstrained bearer tokens | V10.3.5, V10.4.5 | T1550.001 | SC-23 |
| 6. Loose redirect URIs | V10.4.1 | T1528 | SC-23 |
| 7. No PKCE or CSRF protection | V10.2.1, V10.4.2, V10.4.3, V10.4.6 | T1528 | SC-23 |
| 8. Implicit and ROPC grants | V10.1.1, V10.4.4 | T1528 | CM-7 |
| 9. Shared client secrets | V10.4.10, V10.4.16 | T1550.001 | IA-5 |
| 10. Missing audience and issuer checks | V10.2.2, V10.3.1, V10.3.2 | T1550.001 | SC-23 |
In NIST CSF 2.0 terms, risks 1 to 4 and 9 sit under PR.AA-01 (identities and credentials for users and services are managed) and PR.AA-05 (access permissions follow least privilege and are reviewed); the detection table supports DE.CM-03. The ASVS level matters: several requirements above (V10.4.14 sender-constrained tokens for all clients, V10.4.16 strong client authentication) are level 3, so decide which applications need that level rather than applying it everywhere at once.
Where to start
If you can do only three things this quarter: build the inventory of connected apps with owners and scopes, and revoke what is unused (risks 1 and 4); restrict user consent and add an approval workflow plus alerts on new high-impact grants (risk 2); and turn off implicit and ROPC grants while requiring PKCE for every client (risks 7 and 8). Then move to sender-constrained tokens for your most sensitive APIs and asymmetric client authentication for confidential clients.
Small organisations mostly consume OAuth rather than run an authorization server, so risks 1 to 4 are the whole job: the SaaS admin consoles already expose consent settings, app lists and audit logs. Larger organisations that run their own authorization server own risks 5 to 10 as well and should test them in every release, using ASVS V10 as the test plan. If a token is stolen, follow the OAuth Token Theft Incident Playbook.
Practitioner checklist
- Export every connected app and grant from your identity provider and main SaaS platforms, with owner, scopes and last use.
- Revoke grants unused for 90 days and disable apps with no owner after a short notice period.
- Restrict user consent and route high-impact permissions through admin approval.
- Alert on new consent grants, new app credentials and new application permissions.
- Set refresh token rotation and an absolute lifetime; keep access tokens short-lived.
- Require PKCE (S256) and exact redirect URI matching for every client; remove wildcards.
- Disable implicit and ROPC grants on the authorization server.
- Move confidential clients to private_key_jwt or mTLS and expire remaining client secrets.
- Validate aud, iss, exp and scope at every resource server, and pilot DPoP or mTLS on the most sensitive APIs.
- Write a vendor-breach runbook: which tokens that vendor holds, who revokes them and which secrets to rotate.
Standards and references
- IETF: RFC 9700 Best Current Practice for OAuth 2.0 Security
- OWASP: Application Security Verification Standard 5.0
- MITRE ATT&CK: Steal Application Access Token
- MITRE ATT&CK: Use Alternate Authentication Material: Application Access Token
- MITRE ATT&CK: Cloud Application Integration
- NIST: SP 800-53 Rev. 5
- NIST: Cybersecurity Framework 2.0
Related NHI Mgmt Group resources: OAuth 2.0 Security Best Current Practice (RFC 9700) Guide · OAuth 2.0 and OpenID Connect Guide · Token and Session Security Guide · Top 10 API Security Risks