Oauth2 Provider Design
Design the OAuth2 authorization-server surface a B2B SaaS offers third-party apps - the OAuth 2.1 protocol baseline (PKCE for every client, no implicit or password grants, exact redirect matching), token TTL and refresh-rotation policy, scope taxonomy and granularity, consent-screen design with partial and incremental grants, client registration posture, and the tiered app-verification program. Use whenever the user mentions OAuth, "Sign in with X", access and refresh tokens, scopes, consent screens, PKCE, or third-party apps acting on a customer's behalf - even if they never say "OAuth provider". Issuer side only, not integrating against someone else's OAuth. Do NOT use for API-key design - use samber/developer-platform-skills@api-auth-key-management instead.
- Skill ID
- samber/developer-platform-skills/oauth2-provider-design
- Publisher
- samber
- Repository
- developer-platform-skills
- Installs
- 326
- Files
- 6
- License
- MIT
- Synced
- Oct 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
samber/developer-platform-skills/oauth2-provider-designInstalls these files- SKILL.md
- evals/evals.json
- references/app-verification-program.md
- references/consent-screen-design.md
- references/protocol-baseline.md
- references/scope-taxonomy-archetypes.md
What this skill tells the agent
OAuth2 Provider Design
You are an OAuth provider designer. Design the authorization-server surface a platform offers third-party apps: protocol profile, token lifecycle, scope taxonomy, consent screen, registration, verification. Do it so a compromised app or leaked token is a contained event, and so the platform never faces the forced retrofit Salesforce's ISV ecosystem lived through in 2026.
This is decision guidance for a platform/API team, not an RFC tutorial. The target profile is OAuth 2.1, with one precision to carry everywhere:
- RFC 9700 (BCP 240, the OAuth Security Best Current Practice) is final and ratified (January 2025).
- The consolidated OAuth 2.1 document (draft-ietf-oauth-v2-1) remains in draft. Check its current status before citing it as published.
The requirements are settled convergence regardless of the document's own publication status. Never state that OAuth 2.1 itself is a published RFC without first confirming that's still accurate.
Memory (advised): When memory lives in a file, consider using developer-platform-context.md; if a different memory system is in use, rely on that instead. The file is an advisory reference, not a mandatory requirement. Separate task info in different sections. Remove finished tasks. Add a date to a task; no date for general project context. Some interview responses may differ between 2 tasks.
Clarifying questions
Ask before designing anything; each answer changes a later step. Batch them - this is tactical design, not a strategy interview.
- Greenfield or retrofit? If retrofit: which grants run today, do any clients depend on the implicit or password grant, is refresh rotation on, and roughly how many registered apps exist.
- Client population: server-side confidential apps, browser SPAs, native/CLI apps, AI agents or MCP hosts? (public vs confidential changes token policy - see step 1)
- Do apps act only on behalf of a signed-in user, or also with their own identity (bot/app tokens, org-wide access)? (drives scope-to-token-type binding and admin consent - see step 2)
- Data-sensitivity ceiling: can any scope reach _other users'_ data, bulk data, or regulated financial/health data? (sets the verification tier - see step 3 - and whether step 4 ever matters)
- Who approves an install: individual end users only, or org admins too? (see the consent-surface split below)
- Build substrate and effort ceiling: authorization server from scratch, or on an identity product that already ships rotation/DPoP as configuration? When must this ship, and is it a one-off unblock (an enterprise deal demanding OAuth) or the foundation of an app ecosystem? The menus below diverge sharply on effort - re-rank them against these answers.
If your harness has persistent memory, store the core decisions: grant list, TTLs and rotation posture, scope naming convention and token-type binding, verification tiers and thresholds. A later run (a scope addition, a review-program escalation, a token-theft incident) then starts from the design instead of re-deriving it.
Who consents: end user, org admin, or both
The B2B/B2C split that matters here is who stands between the app and the grant:
- B2C / individual users: one consent surface - the end user's screen. Consent copy quality and scope minimalism carry the entire trust decision.
- B2B / org-owned workspaces: two consent surfaces. The end user consents, and an org admin can gate installs before or above that (Slack admin-approved apps; Microsoft admin consent, where app-identity permissions can only ever be consented by an admin). Slack's developer guidance names the consequence: "Asking for more permissions than necessary can cause users or admins to reject the installation" - over-scoping is a conversion risk at a gate the end user's "yes" cannot pass for you.
The protocol core, token lifecycle, and plain-language consent-copy rules are identical for both - only the approval topology and the app-identity/org-wide scope tier differ. A B2B provider must design the admin surface (approval queue, org-wide grant review, app-identity permission tier) as a first-class part of steps 2-3, not bolt it on when the first enterprise customer asks.
Workflow
Build in this order - each stage is load-bearing for the next, and the order is the staged sequence the cross-provider research converged on:
- Protocol core.
- Scope taxonomy and consent screen.
- Registration and verification program.
- Advanced hardening - only when justified.
1. Protocol core
Implement authorization_code with PKCE (S256, mandatory for every client - public and confidential alike), client_credentials, refresh_token, and device_authorization (RFC 8628, for CLIs and headless clients). Do not implement implicit or the password grant - both are removed under OAuth 2.1; a greenfield server has no reason to ever support them.
- Exact string matching on redirect URIs, with the single standard exception of the port number in native-app
localhostredirects. RFC 9700's own justification: pattern matching "turned out to be more complex to implement and more error-prone", with "several successful attacks exploiting flaws in the pattern-matching implementation... observed in the wild" (RFC 9700). - Never accept bearer tokens in URI query strings - Authorization header or POST body only; query strings leak into logs, history, and Referer headers.
- Authorization codes: single-use, maximum 10-minute lifetime (RFC 6749 §4.1, reinforced by RFC 9700).
- Access tokens: default ~1 hour - the cross-provider convergence point (GitHub App and Google tokens ~1h, Microsoft Entra 60-90 min; provider docs - full table in references/protocol-baseline.md). Keep JWT access tokens short specifically because a JWT can't be revoked mid-lifetime the way an opaque database-backed token can.
Refresh-token posture - three candidates, ranked:
- security value:
sender-constrained (DPoP) > rotation + reuse detection > non-rotating with a per-client cap - third-party client-library compatibility:
non-rotating > rotation > DPoP - effort:
DPoP > rotation > non-rotating - efficiency:
rotation + reuse detection > non-rotating > DPoP
- Default rung: rotation with token-family reuse detection. Every refresh token belongs to a family traceable to the original grant; a consumed token presented again revokes the whole family (the Auth0/Keycloak/Django OAuth Toolkit convergent pattern). Ship a reuse grace window from day one - around 10-30 seconds - or multi-tab SPAs and network retries will read as attacks and log real users out. RFC 9700 §4.14 states what the tripwire buys: the server "cannot determine which party submitted the invalid refresh token, but it will revoke the active refresh token" - it's a tripwire, not an investigation tool.
- DPoP is the starved option: strongest posture, and near-zero ecosystem support - 0 of 18 mainstream issuers with a working discovery document advertised DPoP support (MojoAuth issuer survey). Promote it when tokens guard financial or health data (FAPI 2.0 accepts DPoP or mTLS as its baseline) or when long-lived AI-agent tokens widen the theft blast radius; Bluesky's mandatory-DPoP deployment proves it production-viable at scale. Otherwise it's a support burden few client libraries can even meet yet - Stage 4, not here.
- Non-rotating survives only in two bounded forms:
- Confidential clients, whose client authentication already sender-constrains redemption (RFC 9449's own carve-out - this is why 2.1 mandates "sender-constrained or rotated" only for public clients).
- Google's capped-population model (max 100 refresh tokens per account per client, oldest silently invalidated; Google docs - this figure moved from a cached "50", re-verify at implementation).
An indefinitely-reusable refresh token for a public client is not a rung to demote - it's banned under 2.1; delete it from the menu.
More from samber
Use this skill in a project
Open any RiverX project, search the Skills panel for samber/developer-platform-skills/oauth2-provider-design, and install it in one click.
