OAuth2

OAuth2 is a standardized authorization framework that lets a user grant a third-party application limited access to their account on another service without sharing their password. It defines several flows for different application types and is the foundation for social login buttons such as "Continue with Google" or "Sign in with GitHub".

✅ When is it appropriate

OAuth2 is suitable if most of the following apply:

  • users must be able to log in using an existing account from an external provider such as Google, GitHub, or Microsoft instead of creating a new account
  • a third-party application needs read or write access to a user's data on another platform, such as a calendar or cloud storage, without the user sharing their password
  • multiple independent client applications such as a web app, a mobile app, and a CLI tool all authenticate through one central authorization server
  • access tokens must be revocable immediately, so that revoking a token stops access at once rather than waiting for an expiry time
  • different clients need different scopes of access, such as one client that can only read data and another that can also write

OAuth2 separates the role of the authorization server from the resource server. The authorization server issues tokens and manages which clients have which scopes. The resource server accepts a token and uses the scopes it contains to decide what the caller is allowed to do. Neither server needs to know the user's password.

❌ When is it NOT appropriate

OAuth2 may not be ideal if:

  • the API is used only by the application's own users and no external provider login is needed, meaning a simpler token-based approach handles all requirements
  • the application has one client type and there is no need to issue tokens with different scopes to different callers
  • setting up and operating an authorization server would take longer than building the actual feature the project needs to ship
  • the team has never implemented an OAuth2 flow before and there is no budget for the learning, testing, and security review it requires

OAuth2 requires running an authorization server, registering client applications, implementing at least one grant type flow, handling token storage securely on both server and client, and writing tests for each flow. For an internal API with one client, this infrastructure takes significantly more time to set up than issuing a signed JWT directly.

👍 Advantages

  • tokens can be revoked immediately at the authorization server, stopping access without waiting for an expiry time
  • each client application gets its own token with only the scopes it needs, so a compromised client cannot access resources it was never authorized for
  • users log in with an existing trusted account and never share their password with the application requesting access
  • many identity providers such as Auth0, Keycloak, and Google Identity implement OAuth2, so the authorization layer can be delegated to a proven external service
  • well-defined flows for each client type: Authorization Code for web and mobile apps, Client Credentials for server-to-server calls

👎 Disadvantages

  • running an authorization server is an additional piece of infrastructure to deploy, monitor, and keep available; if it goes down, no client can authenticate
  • the Authorization Code flow involves multiple redirect steps and requires understanding of PKCE, state parameters, and token endpoints before it works correctly
  • misconfiguring a redirect URI or scope allows attackers to intercept authorization codes or obtain tokens with more access than intended
  • for a single internal API with one client, the setup time is disproportionate to the security benefit compared to a signed JWT

🛠️ Typical use cases

  • web and mobile apps that need "Continue with Google" or "Sign in with GitHub" login buttons
  • SaaS products that connect to third-party services on the user's behalf, such as reading calendar events or posting to a social platform
  • platforms that issue APIs consumed by multiple independent clients with different permission levels
  • server-to-server communication where one backend service calls another and proves its identity using a Client Credentials token
  • enterprise applications that require single sign-on across multiple services using a shared identity provider

⚠️ Common mistakes (anti-patterns)

  • using the Implicit grant type, which was deprecated in OAuth 2.1 because it passes tokens directly in the browser URL where they can be captured by browser history or referrer headers
  • registering a wildcard or overly broad redirect URI such as https://example.com/*, which allows an attacker to redirect the authorization code to a different path they control
  • skipping PKCE on the Authorization Code flow for a public client such as a mobile app or SPA, making it possible for an attacker to exchange a stolen authorization code for a token
  • storing access tokens in localStorage where any JavaScript on the page can read them, including injected scripts from compromised dependencies
  • not testing token revocation, expired token handling, and scope enforcement before going to production

The Implicit flow was once the recommended approach for browser-based apps but is now considered insecure because the access token appears in the browser URL. Existing implementations should be migrated to the Authorization Code flow with PKCE, which is the current recommended approach for all public clients including SPAs and mobile apps.

💡 How to build on it wisely

Recommended approach:

  1. Use the Authorization Code flow with PKCE for any client that runs in a browser or on a mobile device. Use the Client Credentials flow for server-to-server calls where no user is involved.
  2. Use an established authorization server rather than building one. Auth0, Keycloak, and AWS Cognito all implement OAuth2 correctly and handle token issuance, revocation, and scope management.
  3. Register exact redirect URIs for each client application. Never use wildcards. Validate the state parameter on every callback to prevent cross-site request forgery attacks.
  4. Store tokens in httpOnly cookies rather than localStorage. Set the Secure and SameSite=Strict attributes so the cookie is only sent over HTTPS to the same origin.
  5. Test token revocation, expired token rejection, invalid scope rejection, and the full Authorization Code callback before releasing to production. Use OWASP's OAuth2 security checklist as a reference.

If the application only needs to authenticate its own users with no external providers and no need to issue tokens to third-party clients, a simpler JWT-based approach will get the job done with significantly less setup. Move to OAuth2 when external login providers, token revocation, or scope-based access control across multiple clients become concrete requirements.

Feedback & Sharing

Give us your thoughts on this page, or share it with others who may find it useful.

Share with your network:

Feedback

Found this helpful? Let me know what you think or suggest improvements 👉 Contact me.