Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

OAuth security best practices

The attacks in this series were not discovered all at once. They were found over the years after OAuth 2.0 was published, in research and in real incidents, and the defenses were written down as they were understood. The OAuth 2.0 Security Best Current Practice, published as RFC 9700 in January 2025, collects them. It updates the original specification, the bearer token specification, and the original threat model, and it turns several defenses that were once optional into requirements.

Most of its advice has appeared in earlier lessons, one attack at a time. Read by role, it becomes a short list for each party. The document separates what a party must do from what it should or may do, and the tables below keep those words. Advice phrased without them comes from the earlier lessons.

Practices for clients

PracticeExplained in
Public clients must use PKCE, and it is recommended for confidential clients. Clients should use the S256 method.PKCE; Code interception and injection
The password grant must not be used, and the implicit grant should not be.Choosing a flow
Clients must prevent forged callbacks, with one-time state bound to the browser session, or with PKCE once they have confirmed that the server enforces it.Correlating requests and responses; Request correlation and CSRF
A client working with more than one authorization server must defend against mix-up, and should do so by checking iss.Authorization server mix-up
Clients must not run open redirects. The callback page should not include third-party resources or links to other sites.Redirects and authorization codes; Redirect URI validation
Clients must not send access tokens in a URL query parameter. Send each token only to the API it was issued for.Using access tokens; Token theft and replay
Request only the access the task needs.Grants, scopes, and consent; Scopes and audiences
Refresh tokens must be kept confidential in storage. Under rotation, run one refresh at a time.Server-rendered web applications; The refresh token grant; Refresh token theft

The guidance also recommends that authorization servers publish metadata and that clients configure themselves from it where it exists, which reduces the chance of a mistyped or attacker-supplied endpoint.

Practices for authorization servers

PracticeExplained in
Redirect URIs must be compared as exact strings, allowing only a varying port on a native app's loopback address, and the server must not redirect to an invalid one.Redirects and authorization codes; Errors and denied access; Redirect URI validation
The server must not allow http redirect URIs, except a native app's loopback address.Redirect URIs and client metadata; Redirect URI validation
The server must support PKCE, enforce it whenever a challenge was sent, refuse a verifier for a code issued without one, and give clients a way to detect its support.PKCE; Request correlation and CSRF
Codes must expire shortly after they are issued and work only once. The server must refuse a reused code and should revoke the tokens issued from it.Errors and denied access; Code interception and injection
Include iss in authorization responses so clients can detect mix-up.Correlating requests and responses; Authorization server mix-up
Access tokens should carry the minimum privileges, be restricted to their intended API, and be sender-constrained.Scopes and audiences; Token theft and replay
Refresh tokens for public clients must be sender-constrained or rotated. Unused refresh tokens should expire, and the server may revoke them after security events such as a password change.Refresh tokens and rotation; Refresh token theft
The server should authenticate clients wherever that is feasible, and asymmetric methods such as signed assertions are recommended.Client authentication methods; Secrets and signed assertions

Three practices for authorization servers have not had a lesson of their own.

Clickjacking is an attack in which another site loads a page inside an invisible frame and positions it so that your clicks land on its buttons. A site could frame the photo service's consent page beneath a harmless-looking button and collect your approval without you ever seeing the screen. Authorization servers must prevent it. They tell the browser not to display their pages inside frames on other sites, apart from any specifically allowed, on the authorization, sign-in, consent, and error pages alike:

Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY

The first header is the current mechanism, and the guidance says authorization servers should use it. The second covers older browsers that do not understand the first, and the guidance says servers should combine the two.

Redirect status codes. After you submit your password on the photo service's sign-in form, the server redirects your browser toward the printer. If it used status 307, the browser would repeat the POST, form body included, to the new address, and your password would arrive at the printer. Authorization servers must not use 307 after a form that might contain credentials, and should use 303 See Other, which always turns the next request into a GET.

The authorization server as an open redirect. Refusing to redirect to an unregistered address is not the whole story. An attacker who registers a client, for example through open self-service registration, owns a valid redirect URI pointing at a phishing site. A deliberately broken request then makes the photo service forward your browser there with an error, lending its trusted address to the attacker's link. The guidance says the server must take precautions. It must authenticate the person before redirecting, prompting for credentials when needed except in silent requests, and should redirect automatically only to addresses it trusts. For an address it does not trust, it may tell the person where they are going and let them decide.

Practices for resource servers

PracticeExplained in
Validate every token completely. The API must refuse any token not issued for it.Token formats and validation; Scopes and audiences
Check scope and access to the specific object on every request, and never treat a token issued to a client acting for itself as a person's token.Enforcing access at an API
The API must treat received tokens like other sensitive secrets, never storing or passing them on in plain form, which also keeps them out of logs.Token theft and replay
APIs should use sender-constrained tokens. When a token is bound, verify the proof of possession on each request.Token theft and replay

Underneath all three roles sits transport security. Authorization responses must never travel over unencrypted connections, which is why the loopback exception is the only place http appears. Between client and API, the guidance recommends TLS from end to end. When a proxy ends the TLS connection in front of an API, it must sanitize every incoming header the API relies on for security, such as a forwarded client certificate or address, so an outside caller cannot supply a forged one, and the connection from the proxy to the API must be protected too.

From best practice to OAuth 2.1

Many of these rules change defaults rather than add features, so the OAuth working group has been folding them into the framework itself. OAuth 2.1, a revision the working group began as an Internet-Draft, consolidates OAuth 2.0 with PKCE, the guidance for native and browser applications, bearer token usage, and this best current practice. In it, the code flow includes PKCE by default, redirect URIs are compared exactly, the implicit and password grants are left out, tokens never appear in query strings, and public clients' refresh tokens must be sender-constrained or used only once.

Because OAuth 2.1 gathers existing guidance rather than inventing new mechanisms, a deployment that follows the original specification together with RFC 9700, as the tables above do, already behaves as OAuth 2.1 describes in most respects. The mechanisms those tables kept pointing toward, such as sender-constrained tokens, issuer identification, and server metadata, belong to Advanced OAuth, which takes the extensions one at a time. It begins with the authorization request itself, which every redirect-based flow so far has sent through the browser, where anyone along the way can read or alter it.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2A team builds the photo API, which receives access tokens from many clients. Which practice from current guidance is theirs to carry out?

QUESTION 2 OF 2A game site loads the photo service's consent page in an invisible frame beneath its Play button. Which defense addresses this?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity