100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Choosing the Right Grant

OAuth 2.0 offers several grant types built for different trust boundaries; picking the wrong one is one of the most common real-world sources of OAuth vulnerabilities.

Grant TypesIntermediate9 min readJul 10, 2026
Analogies

The Core Question: Who Is the Actor?

Every grant selection decision reduces to one question: is there a human resource owner delegating access, or is the client acting purely as itself? If a specific user needs to grant an application access to their own data, that's Authorization Code with PKCE, full stop, regardless of whether the client is a web app, SPA, or mobile app. If there's no user at all, a backend job talking to another backend service, that's Client Credentials. Almost every OAuth misconfiguration traces back to conflating these two cases: using Client Credentials where per-user delegation was actually needed, or building a custom non-standard flow because a team wasn't sure which standard grant fit.

🏏

Cricket analogy: It's like deciding whether a substitute fielder needs the captain's specific on-field authorization for that match (a delegated, person-specific grant) versus a groundstaff member who just needs their own staff badge to enter the facility, no captain involved at all.

A Practical Decision Framework

In practice: web apps with a server-side back end and browser-based SPAs and mobile apps should all use Authorization Code with PKCE for anything involving a logged-in user, the difference is only in where the code exchange happens (server-side directly, or via a BFF for SPAs). Backend services calling other backend or third-party APIs with no user context use Client Credentials. Devices with limited or no input capability, smart TVs, CLI tools without a browser, use the Device Authorization Grant (not covered in depth here, but worth knowing it exists specifically for that case). Anything reaching for the Implicit or Password grants should stop and reconsider, per the deprecated-grants discussion, there is essentially always a better modern option.

🏏

Cricket analogy: It's like a team having a clear playbook: a specific batter walking to the crease follows the standard umpire sign-in procedure (Authorization Code), while the groundskeeper follows a totally different facility-access procedure (Client Credentials), and nobody improvises a third, undocumented way in.

Scoping and Least Privilege Across Grants

Whichever grant you choose, scope design should follow least privilege: request only the specific permissions the current operation needs, not a broad 'everything' scope out of convenience. A read-only reporting dashboard should request orders:read, not orders:write or admin:*; a Client Credentials service that only reorders inventory should never also carry a scope that lets it issue refunds. This matters doubly for Authorization Code flows, where overly broad scope requests also erode user trust at the consent screen, users are more likely to abandon a login flow that asks for access it clearly doesn't need for its stated purpose.

🏏

Cricket analogy: It's like giving a substitute fielder specific permission to field at deep cover for one over, not a blanket pass to bowl, bat, and make tactical decisions for the rest of the match; the access should match the exact job at hand.

text
Decision checklist:

1. Is a specific human user delegating access to their own data/actions?
   -> YES: Authorization Code + PKCE
        - Web app with server back end: exchange code server-side
        - SPA: exchange code via CORS-enabled /token, or better, a BFF
        - Native/mobile app: exchange code in-app, PKCE mandatory
   -> NO, continue to 2.

2. Is this a backend/service calling another API with no user context?
   -> YES: Client Credentials

3. Is this a device with no/limited browser or keyboard input
   (smart TV, CLI without local browser, IoT)?
   -> YES: Device Authorization Grant

4. Are you about to reach for Implicit or Password (ROPC)?
   -> STOP. Re-evaluate against options 1-3; a fitting modern
      grant almost always exists.

A related but distinct pattern worth knowing: when a backend service needs to call a downstream API on behalf of a user who already authenticated to it (not itself), the right tool is typically token exchange (RFC 8693) or an 'on-behalf-of' flow, not Client Credentials with a bolted-on user_id parameter. This preserves the original user's identity and scope constraints through the whole call chain.

Red Flags in a Grant Selection Review

When reviewing an OAuth integration, several signals reliably indicate a wrong grant choice: a Client Credentials token being used with a caller-supplied user or account ID parameter (should be Authorization Code or token exchange); a mobile or SPA app embedding a client_secret in its binary or bundle (the app is public, so it needs PKCE, not a secret it can't actually protect); a backend prompting users to type their password into a custom form that then calls another provider's API (ROPC in disguise, likely violating that provider's terms of service); and any homegrown 'bearer token' scheme invented because a team found OAuth's standard grants 'too complicated' for their use case, which usually means missing expiration, rotation, or scope enforcement entirely.

🏏

Cricket analogy: It's like a review flagging a groundstaff pass being used to admit a specific spectator by name, a clear sign the wrong kind of pass is being used for the wrong job, and the spectator should have gone through the normal ticketing gate instead.

If a design doc says 'we'll just use Client Credentials and pass the user ID as a parameter', that is almost always a red flag for an authorization bypass waiting to happen. The fix is nearly always Authorization Code with PKCE (if a user is present and interactive) or token exchange/on-behalf-of (if a backend needs to relay an already-authenticated user's identity downstream).

  • The first question in grant selection is always whether a specific human resource owner is delegating access, or whether the client is acting purely as itself.
  • Authorization Code with PKCE covers essentially every user-facing login scenario across web, SPA, and mobile clients.
  • Client Credentials is for backend-to-backend calls with no user context, never for fetching per-user data via an ID parameter.
  • Device Authorization Grant exists specifically for input-constrained devices like smart TVs and CLI tools.
  • Implicit and Password (ROPC) grants should be treated as deprecated red flags, not viable options, in any new design.
  • Least-privilege scoping applies to every grant: request only the exact permissions the current operation needs.
  • Token exchange (RFC 8693) or on-behalf-of flows, not Client Credentials with a bolted-on user ID, is the correct pattern for relaying user identity through a service chain.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#OAuth20StudyNotes#ChoosingTheRightGrant#Choosing#Right#Grant#Core#StudyNotes#SkillVeris#ExamPrep