Direct answer: the 2026 OAuth migration is not "whether to use OAuth" but "which tighter rule set to follow." RFC 9700 (BCP 240, 2025) turns years of best practice into MUST/SHOULD: authorization-code flows must use PKCE (S256), redirect URIs must match exactly, open redirectors are forbidden, public-client refresh tokens must be sender-constrained or rotated, access tokens should be audience-restricted, and resource servers must reject the wrong audience. RFC 10017 (BCP 212, August 2026) further splits browser applications into BFF (most secure) → token-mediating backend → browser-based OAuth client (most exposed) and states that browser storage cannot guarantee encryption and XSS can steal tokens. OAuth 2.1 draft -17 (30 October 2026) codifies these rules: PKCE is the default, Implicit and ROPC are removed, bearer tokens are no longer allowed in the query, and PKCE plain is prohibited. Note: OAuth 2.1 is not an RFC yet; do not call a deployment "OAuth 2.1 certified".
This guide is for SaaS/API, identity, frontend/backend and security teams. It explains RFC 9700, RFC 10017 and the OAuth 2.1 draft, BFF vs browser-client selection, PKCE/redirect/refresh-token/audience/mix-up implementation, common failure modes and a 90-day migration checklist. Rules come from IETF RFC 9700 (BCP 240), RFC 10017 (BCP 212), OAuth 2.1 draft-ietf-oauth-v2-1-17 (30 October 2026) and RFC 7636/9207/9449, all accessed 8 November 2026. Official facts, editorial advice and items to confirm are kept separate. This is not compliance or procurement advice.
(1) PKCE is the default: use S256 in the authorization-code flow; required for public clients, recommended for confidential clients; plain is prohibited in OAuth 2.1. (2) Storing a token in the browser is not an architecture: BFF keeps tokens in a server-side cookie session; token-mediating backend is next; a pure browser client is most exposed. (3) Migration order: inventory clients/flows → PKCE + exact redirect → remove Implicit/ROPC → refresh rotation/sender-constraint → audience/iss validation → BFF/token storage.
Versions and timeline: 9700, 10017, OAuth 2.1 draft
RFC 9700 is the OAuth 2.0 security best current practice (BCP 240), updating/extending the threat model of RFC 6749/6750/6819 and marking some modes as insecure. RFC 10017 is the browser-application BCP (BCP 212, August 2026), describing BFF, token-mediating backend and browser-based client architectures. OAuth 2.1 draft -17 was updated on 30 October 2026 and is intended to replace RFC 6749/6750, but it is still an Internet-Draft (expires May 2027), not an RFC. The relationship: 9700 is the "do this now" security baseline, 10017 is "how browsers should do it", and 2.1 codifies both into the next framework.
| Document | Status/date | Why it matters for migration |
|---|---|---|
| RFC 6749 / 6750 | 2012 / 2012 | OAuth 2.0 base; some modes are now insecure |
| RFC 9700 | BCP 240, 2025 | PKCE, exact redirect, refresh rotation/sender-constraint, audience, mix-up |
| RFC 10017 | BCP 212, August 2026 | BFF / token-mediating / browser-client architectures and token storage |
| OAuth 2.1 draft -17 | 30 Oct 2026, draft | PKCE default, Implicit/ROPC removed, no bearer in query, plain prohibited |
| RFC 7636 / 9207 / 9449 | PKCE / iss / DPoP | PKCE S256, mix-up defense, sender-constraint |
Sources: IETF RFC 9700, RFC 10017, OAuth 2.1 draft-ietf-oauth-v2-1-17 (30 October 2026), RFC 7636/9207/9449 (accessed 8 November 2026). Editorial summary; OAuth 2.1 is still a draft and final clauses may change.
Key OAuth 2.1 changes vs 2.0
The draft turns "best practice" into defaults: the authorization-code flow requires PKCE code_challenge/code_verifier; redirect URIs must match exactly; Implicit (response_type=token) and ROPC are removed; bearer tokens are no longer allowed in the URI query; public-client refresh tokens must be sender-constrained or one-time-use; browser refresh tokens have additional lifetime constraints; PKCE plain is explicitly prohibited; and the token endpoint no longer needs redirect_uri when exchanging a code. For existing systems these are interoperability gates, not options.
| Topic | OAuth 2.0 / old implementations | OAuth 2.1 draft |
|---|---|---|
| PKCE | Optional extension | Default requirement for authorization-code flow; AS must support/enforce |
| PKCE plain | Allowed | Explicitly prohibited; use S256 |
| Redirect URI | Prefix/wildcard matching | Exact string matching (localhost ports exception) |
| Implicit | Allowed | Removed (response_type=token) |
| ROPC | Allowed | Removed |
| Bearer in query | Allowed | No longer used; header only |
| Public-client refresh | Long-lived fixed token | Sender-constrained or one-time/rotated |
| iss / mix-up | Optional | AS sends iss; client implements mix-up defense |
Sources: OAuth 2.1 draft-ietf-oauth-v2-1-17 §1.8/§10 and change list (30 October 2026); RFC 9700 §2.1/§4. Editorial summary; exact MUST/SHOULD follows the draft text.
Browser architecture: BFF, token-mediating, browser client
RFC 10017 gives three patterns, in decreasing security: BFF has a backend act as a confidential client, keeps access/refresh tokens in a server-side cookie session, and forwards all API requests, so the browser never sees tokens; token-mediating backend handles OAuth on the backend but the browser uses the access token to call resource servers directly; browser-based OAuth client performs all OAuth in the browser as a public client and stores tokens in the browser. The latter two expose tokens to XSS/malicious JavaScript; BFF uses HttpOnly cookies to reduce session hijacking and is the usual choice for new applications.
| Pattern | Where the token lives | Security | Fit |
|---|---|---|---|
| BFF | Server session/cookie; no token in browser | Highest | New SPAs, same/cross-domain APIs, sensitive business |
| Token-mediating backend | Backend handles OAuth; browser uses access token directly | Medium | Existing direct API calls, token exposure acceptable |
| Browser-based OAuth client | localStorage/sessionStorage/IndexedDB/memory | Lowest | No backend, low risk, acceptable trade-off |
| Same-domain frontend/backend | May avoid OAuth; same-site cookie/session | Implementation-dependent | Same domain, no third-party API |
Sources: RFC 10017 §6/§8/§9 (August 2026); RFC 9700. Editorial summary; architecture also depends on same-domain, CORS, CSP and third-party API constraints.
Migration checklist: from "login works" to "2.1-tight"
Start with an auditable inventory: each client's type (public/confidential), grant/response type, redirect URI, PKCE method, token storage, refresh policy, audience/scope and number of authorization servers. Then prioritize by risk: PKCE + exact redirect first; remove Implicit/ROPC second; refresh rotation/sender-constraint and audience/iss validation third; BFF/token-storage as an architecture workstream in parallel. Every item needs regression tests and monitoring; do not switch all clients at once.
| Area | Action | Acceptance evidence |
|---|---|---|
| PKCE | Add S256 challenge/verifier; reject plain | AS enforces; no-verifier request rejected |
| Redirect | Exact match; remove wildcard/prefix; no open redirector | Full URI registered; negative tests |
| Grant | Remove Implicit/ROPC; use code+PKCE | Legacy endpoint disabled/alerted |
| Refresh | Public client rotation or DPoP/mTLS; revoke on reuse | Replay test, revocation log |
| Audience | Bind access token to resource server; RS checks aud/iss/exp | Wrong audience rejected |
| Mix-up | Multi-AS client validates iss per RFC 9207 | Wrong issuer aborts |
| Token storage | Prefer BFF/HttpOnly; avoid persistent browser tokens | XSS drill, CSP |
| Bearer | Authorization header only; never in query | Log/gateway rules |
Editorial migration checklist, not an official template; MUST/SHOULD, compatibility and acceptance follow RFC 9700/10017, the OAuth 2.1 draft and the authorization-server documentation.
Common failure modes: why "we use OAuth" still gets stolen
OAuth flaws usually live in implementation details: redirect URI prefix matching, PKCE plain or client-only "pretend" validation, tokens in localStorage stolen by XSS, refresh tokens that never rotate, access tokens without audience validation ("use service A's token on service B"), multi-AS clients that do not validate iss (mix-up), bearer tokens in query strings leaking into logs, JWT validation that checks only the signature but not alg/iss/aud/exp, and overly broad CORS letting malicious sites call the API. OAuth 2.1 tightens each of these.
| Failure mode | Impact | Control |
|---|---|---|
| Redirect prefix/wildcard | Code/token redirected to attacker | Exact match + register full URI |
| PKCE plain / not enforced | Code injection/interception | S256 + AS enforcement + reject no-verifier |
| Token in localStorage | Direct XSS theft | BFF/HttpOnly; CSP; short lifetime |
| Refresh not rotated | Long-term replay | One-time/rotation + revoke on reuse |
| No audience check | Cross-service token abuse | RS checks aud/iss/exp; resource binding |
| No iss check with multiple AS | Mix-up attack | RFC 9207 iss; per-issuer redirect |
| Bearer in query | Log/Referer leakage | Authorization header only |
| Incomplete JWT validation | Algorithm confusion/expired token | Pin alg, verify iss/aud/exp, key rotation |
| Broad CORS | Malicious site calls API directly | Minimal origin allowlist + CSP |
Editorial failure list, not an official checklist; attacks/mitigations follow RFC 9700, RFC 10017, RFC 9449/9207 and the authorization-server documentation.
90-day migration checklist
Use the first 90 days to inventory, tighten and verify: weeks 1-2 inventory clients/flows/token storage; weeks 2-4 add PKCE S256 + exact redirect; weeks 4-6 retire Implicit/ROPC; weeks 6-8 add refresh rotation/sender-constraint and audience/iss validation; weeks 8-10 move to BFF or harden token storage; weeks 10-12 run replay/XSS/wrong-audience drills and monitoring. Do not switch all clients without rollback and monitoring.
| Phase | Action | Output |
|---|---|---|
| Weeks 1-2 | Inventory clients, grant/response types, redirects, PKCE, token storage, number of AS | OAuth asset list, risk ranking |
| Weeks 2-4 | PKCE S256; AS enforcement; exact redirect; no open redirector | Code-flow hardening, negative tests |
| Weeks 4-6 | Retire Implicit/ROPC; migrate to code+PKCE | Legacy alerts/disablement |
| Weeks 6-8 | Refresh rotation/DPoP/mTLS; aud/iss/exp validation | Replay/wrong-audience tests |
| Weeks 8-10 | BFF/HttpOnly or browser-token hardening; CSP/CORS | Architecture change, XSS drill |
| Weeks 10-12 | Monitoring/alerts/rollback; update docs and audit evidence | Runbook, compliance material |
Editorial migration advice, not an official template; scope, priority and acceptance follow enterprise architecture, RFC 9700/10017, the OAuth 2.1 draft and authorization-server capabilities.
FAQ
Is OAuth 2.1 final?
No. OAuth 2.1 is still an Internet-Draft (draft-ietf-oauth-v2-1-17, 30 October 2026, expires May 2027), intended to replace RFC 6749/6750. Follow the RFC 9700/10017 BCPs now; do not claim "OAuth 2.1 compliant".
Is PKCE mandatory?
RFC 9700 requires PKCE for public clients and recommends it for confidential clients; the OAuth 2.1 draft makes it the default for authorization-code flows. Use S256, not plain; the AS must enforce code_verifier validation.
Can we still use Implicit or ROPC?
No. RFC 9700 says Implicit should not be used and ROPC MUST NOT be used; OAuth 2.1 removes both. Migrate to authorization code + PKCE.
Should an SPA use BFF?
Most new applications should: the backend acts as a confidential client, keeps tokens in a server-side cookie session and the browser never sees them. Token-mediating backend is next; a pure browser client is most exposed and only fits no-backend/low-risk cases.
How should refresh tokens be protected?
Public clients must use sender-constraint (DPoP/mTLS) or one-time rotation; reusing an old refresh token should revoke the chain. Browser refresh tokens also have additional lifetime constraints (RFC 10017).
Why audience-restrict access tokens?
To prevent "use service A's token on service B". RFC 9700 recommends binding access tokens to a specific resource server; the resource server must verify aud/iss/exp and reject the wrong audience.
What is the iss parameter for?
Mix-up defense: when a client talks to multiple ASes, the iss value in the authorization response confirms which issuer produced the code. RFC 9700 recommends RFC 9207; the OAuth 2.1 draft requires the AS to send iss.
Can access tokens go in localStorage?
High risk: XSS can read them and browser storage is not guaranteed encrypted. Prefer BFF/HttpOnly; in a pure browser scenario, use memory/short lifetimes/sender-constraint plus CSP and minimal CORS.
Research method and limitations
This article separates "official rule facts" from "editorial advice." RFC 9700's PKCE/exact redirect/refresh rotation/sender-constraint/audience/mix-up requirements come from IETF RFC 9700 (BCP 240, 2025). RFC 10017's BFF/token-mediating/browser-client architectures, browser storage and refresh constraints come from RFC 10017 (BCP 212, August 2026). OAuth 2.1's PKCE default, Implicit/ROPC removal, no bearer in query, plain prohibition and iss changes come from draft-ietf-oauth-v2-1-17 (30 October 2026). PKCE/iss/DPoP details come from RFC 7636/9207/9449. The migration checklist, failure modes and 90-day plan are editorial.
Eight limitations: (1) this is not compliance/legal advice; (2) OAuth 2.1 is still a draft, so final clauses may change; (3) authorization-server/library implementation differences are not checked individually; (4) OpenID Connect, PAR, JARM and Rich Authorization Requests are not covered in depth; (5) SDK/framework default configurations are not assessed; (6) no real attack/penetration test is included; (7) mobile/native/IoT client rules are not fully covered; (8) standards/implementations may change, so recheck IETF/vendor documentation before implementation.
Sources and basis
- IETF RFC 9700, Best Current Practice for OAuth 2.0 Security (BCP 240, 2025): rfc-editor.org/rfc/rfc9700. PKCE, exact redirect, refresh rotation/sender-constraint, audience, mix-up. Accessed 8 November 2026.
- IETF RFC 10017, OAuth 2.0 for Browser-Based Applications (BCP 212, August 2026): rfc-editor.org/rfc/rfc10017. BFF/token-mediating/browser client, browser storage, refresh constraints. Accessed 8 November 2026.
- IETF OAuth 2.1 draft-ietf-oauth-v2-1-17 (30 October 2026): datatracker.ietf.org/doc/draft-ietf-oauth-v2-1. PKCE default, Implicit/ROPC removal, no bearer in query, plain prohibition. Accessed 8 November 2026.
- IETF RFC 7636 (PKCE), RFC 9207 (iss), RFC 9449 (DPoP): rfc7636 / rfc9207 / rfc9449. PKCE S256, issuer identification, sender-constraint. Accessed 8 November 2026.
Data cut-off 8 November 2026; OAuth rules follow the IETF RFCs/draft and authorization-server documentation; this is not compliance, legal or procurement advice.