For startups, OAuth 2.0 is the go-to for simple logins and API access. But in the rush to launch, critical security steps are often missed, creating backdoors for attackers. Here are the common mistakes that can jeopardize user trust.
1. Neglecting Redirect URI Validation
One of the most common
and dangerous errors is a poorly configured redirect URI. This URI is where the authorization server sends a user back after they approve access. If your application doesn't strictly validate this address, attackers can manipulate it. They can craft a link that sends the user's authorization code—a temporary key to their data—to a malicious server instead of your app. The fix is simple in principle: maintain a strict allow-list of exact, full redirect URIs. Do not allow partial matches or open redirects, as even major companies have been caught by this vulnerability.
2. Ignoring the 'state' Parameter
Think of the 'state' parameter as a secret handshake. Your app generates a unique, unguessable string, saves it, and sends it with the authorization request. The authorization server sends it right back. If the returned 'state' doesn't match what you originally sent, the request is fraudulent. Skipping this check opens the door to Cross-Site Request Forgery (CSRF) attacks. An attacker could trick a logged-in user into clicking a malicious link, which then uses the user's session to authorize the attacker’s account, potentially linking the victim's app account to the attacker's identity provider.
3. Using the Wrong Grant Type
OAuth offers several 'grant types' or flows for different scenarios, and choosing the wrong one is like using a house key for a car. A frequent mistake is using the Implicit grant for new applications. This flow, now deprecated, exposes the access token directly in the browser, making it vulnerable to interception. For web and mobile apps, the Authorization Code grant with PKCE (Proof Key for Code Exchange) is the modern standard. PKCE adds a dynamic, one-time secret that proves the app initiating the request is the same one that completes it, preventing authorization code interception.
4. Storing Tokens Insecurely
Once your application receives an access token, where you store it is critical. Placing tokens in a browser's localStorage or sessionStorage is a major risk. Any malicious script injected via a Cross-Site Scripting (XSS) attack can read and steal these tokens. For web applications, a more secure approach is using HttpOnly cookies to handle tokens, which prevents JavaScript from accessing them. For other platforms, use secure, encrypted storage native to the operating system, such as Keychain on iOS or Keystore on Android.
5. Exposing the Client Secret
Your 'client secret' is a password for your application itself. It should never, under any circumstances, be embedded in client side code like a JavaScript single page app or a mobile app. Public clients—those that can't keep a secret safe—should not be assigned a client secret. This is another reason why the Authorization Code grant with PKCE is essential for them; it was designed specifically for scenarios where a client secret cannot be protected. Exposing a client secret allows an attacker to impersonate your application entirely.
6. Requesting Overly Broad Scopes
OAuth scopes define what your application is allowed to do on the user's behalf. It's tempting to request broad access (like full read/write permissions to their profile and files) upfront for future features. This violates the principle of least privilege. If an access token with excessive permissions is ever leaked, the damage an attacker can do is magnified. Instead, request only the minimum scopes needed for a specific action. Modern best practices even encourage incremental authorization, where you ask for additional permissions only when the user wants to access a feature that requires them.
7. Using Long Lived Access Tokens
An access token is a powerful credential. The longer it stays valid, the greater the window of opportunity for an attacker to steal and reuse it. Best practice is to use short lived access tokens (lasting minutes, not hours or days) paired with long lived refresh tokens. When an access token expires, the application uses the refresh token to get a new one without forcing the user to log in again. This model provides a better security posture because refresh tokens can be revoked, giving you a way to cut off access if you detect a compromise.













