Top OAuth & OIDC Misconfigurations — and How to Avoid Them

Share this

OAuth 2.0 and OpenID Connect (OIDC) are powerful, flexible, and… surprisingly easy to misconfigure.
Note: This article belongs to Part 5.2: App Security Best Practices in our Application Security series.

From overly permissive tokens to incorrect redirect URIs and unchecked ID tokens — even mature teams fall into subtle traps. In this final post of our Application Security series, we’ll look at the most common OAuth/OIDC mistakes developers and architects make, what goes wrong under the hood, and how to do it right — especially when working with Spring Security.

Let’s secure your setup before your pen test does.

Application Security Series
Application Security Series

🧨 1. Misconfigured Redirect URIs

❌ What Goes Wrong

  • Wildcard redirect URIs (e.g., https://yourapp.com/*)
  • Open redirect vulnerabilities via query manipulation
  • Redirects pointing to non-production domains or external sites

⚠️ Risk

  • Attackers can hijack the auth code and steal tokens via malicious redirect endpoints.

✅ What to Do

  • Always whitelist exact redirect URIs on your Identity Provider (IdP).
  • Avoid dynamic manipulation of redirect_uri via query params.
  • In Spring Security:oauth2Login() .redirectionEndpoint() .baseUri("/oauth2/callback/*"); // be specific

🔓 2. Not Verifying ID Token or Access Token

❌ What Goes Wrong

  • Trusting tokens without validating their signatureissuer, or audience
  • Skipping nonce validation in OIDC flows

⚠️ Risk

  • Accepting forged or tampered tokens from untrusted sources.

✅ What to Do

  • Always validate:
    • iss (issuer)
    • aud (audience)
    • exp (expiry)
    • Token signature via JWKS
  • In Spring Security, most of this is done if you configure the JWT decoder correctly: .oauth2ResourceServer() .jwt() .jwkSetUri("https://example.com/.well-known/jwks.json")

🔐 3. Storing Tokens in Local Storage

❌ What Goes Wrong

  • Storing tokens (especially refresh tokens) in localStorage or sessionStorage

⚠️ Risk

  • Vulnerable to Cross-Site Scripting (XSS) — attackers can steal tokens from browser storage.

✅ What to Do

  • Prefer using HttpOnly, Secure cookies for token storage.
  • Or better yet, use a Backend-for-Frontend (BFF) pattern to manage tokens safely on the server side.

🔄 4. Not Using PKCE in Public Clients

❌ What Goes Wrong

  • SPAs and mobile apps using Authorization Code flow without PKCE

⚠️ Risk

  • Code interception attack: an attacker can steal the auth code and exchange it for a token.

✅ What to Do

  • Always use PKCE (code_challenge + code_verifier) in public clients.
  • Spring Security handles this out-of-the-box with oauth2Login() since Spring Security 5.2+.

📡 5. Too Broad or Undefined Scopes

❌ What Goes Wrong

  • Apps request openid profile email when only email is needed
  • APIs issue access tokens with "scope": "read write delete *" by default

⚠️ Risk

  • Excessive privileges violate least privilege principle; if a token is compromised, more damage is possible.

✅ What to Do

  • Explicitly define and request minimal scopes needed.
  • Scope policies should be reviewed regularly.
  • In Spring Security, configure scope validation for resource server endpoints: .authorizeHttpRequests() .requestMatchers("/admin/**").hasAuthority("SCOPE_admin")

🧪 6. Mixing Up Access Tokens and ID Tokens

❌ What Goes Wrong

  • Using an ID token (meant for login identity) to authorize API access
  • Sending ID tokens to APIs

⚠️ Risk

  • ID tokens are not meant to be validated by resource servers. APIs might trust unverified data.

✅ What to Do

  • Access tokens go to APIs; ID tokens stay in the frontend or app logic.
  • Never send ID tokens to backend services.

🧯 7. Skipping Token Expiry & Refresh Handling

❌ What Goes Wrong

  • Not handling 401 Unauthorized responses
  • Not using refresh tokens at all

⚠️ Risk

  • Users get logged out unexpectedly, or your app keeps trying to use expired tokens.

✅ What to Do

  • Implement a token refresh strategy with retry logic.
  • For SPAs or mobile apps, use a BFF or silent refresh via iframe/token endpoint.
  • In Spring, handle token expiry in filters or custom handlers.

🧰 Bonus: Spring Security Tips

  • Set your token audience check manually if needed: .jwtAuthenticationConverter(customJwtAuthenticationConverter());
  • Customize token introspection if you’re using opaque tokens: .oauth2ResourceServer() .opaqueToken() .introspectionUri(...)

Conclusion

OAuth and OIDC are battle-tested protocols — but they’re only as secure as their configuration.

Whether you’re securing a SPA, a mobile app, or a backend-for-frontend architecture, the difference between “it works” and “it’s secure” lies in the details. By avoiding these common misconfigurations, you’re not just patching holes — you’re designing trust.

What’s Next?

🎉 That’s a wrap on our Application Security Series!

If you’ve followed us from the basics of identity to token handling and security best practices — give yourself a high-five. Missed a post? You can catch up on the full series here.

Have a Question?

Hit a wall trying to debug a token issue? Confused by a provider-specific config? Drop a comment — always happy to help.

Share this

Leave a comment

Your email address will not be published. Required fields are marked *