What is OAuth 2.0? How OAuth works and how to secure it
OAuth 2.0 is an open standard for delegated authorization defined in RFC 6749. It lets a user (the resource owner) grant a third-party application (the client) limited access to resources on another server without sharing their password. This guide explains the four roles, the main grant types, the recommended authorization-code flow with PKCE, and the security best practices from RFC 9700.
On this page
- OAuth is authorization, not authentication
- The four roles
- Tokens: access tokens and refresh tokens
- The main grant types
- The recommended flow: authorization code with PKCE
- How to secure an OAuth implementation
- FAQ
- What is the difference between OAuth and OpenID Connect?
- What are the four roles in OAuth 2.0?
- What is the difference between an access token and a refresh token?
- Why is the implicit flow deprecated?
- Does OAuth allow a website to see my password?
OAuth 2.0 is an open standard for delegated authorization, defined by the Internet Engineering Task Force in RFC 6749. It lets a resource owner (typically a user) grant a third-party application (the client) limited, scoped access to resources hosted on another server — without ever giving that application their password. Instead of sharing credentials, the client receives an access token from an authorization server. Designed specifically to work over HTTP, OAuth 2.0 is the standard behind features like "Sign in with Google" and the way third-party apps read a limited set of your data on platforms such as GitHub or Google.
OAuth is authorization, not authentication
The most common confusion is thinking OAuth is a login system. OAuth 2.0 is an authorization framework: it decides what a client is allowed to do with the user's resources. It does not, by itself, tell the client who the user is. To add identity, OpenID Connect (OIDC) builds an authentication layer on top of OAuth 2.0 and issues an ID token alongside the access token. When you log in with a third-party account, the workflow you experience is usually OAuth for authorization combined with OIDC for authentication.
The four roles
RFC 6749 defines four roles that every OAuth interaction involves:
- Resource owner — the entity that can grant access to a protected resource. When it is a person, this is the end-user.
- Resource server — the server that hosts the protected resources and accepts authorized requests using access tokens.
- Client — the application making requests on behalf of the resource owner, with its authorization. The client can be a web app, a mobile app, or a server-to-server service.
- Authorization server — the server that authenticates the resource owner, obtains authorization, and issues access and refresh tokens.
The resource owner's credentials are used only at the authorization server — never at the client. That separation is the core security win of OAuth.
Tokens: access tokens and refresh tokens
An access token is the credential a client presents to the resource server to access protected resources. It represents the authorization granted by the resource owner and is typically short-lived. A refresh token lets the client obtain a new access token after the current one expires, without forcing the user to log in again. Refresh tokens are sensitive: if they leak, an attacker can mint new access tokens indefinitely, so they must be stored securely and protected like secrets.
Bearer tokens, defined in RFC 6750, are the most common access token type. A bearer token is used by the client by putting it in the Authorization: Bearer <token> header of an HTTP request. Because anyone who holds the token can use it, bearer tokens require HTTPS to protect them in transit and must never be embedded in query strings, browser history, or logs.
The main grant types
RFC 6749 defines four grant types, each for a different client and use case:
- Authorization code — the recommended flow for web and native apps that can keep a secret. The client redirects the user to the authorization server, the user logs in and consents, and the server returns an authorization code to the client. The client then exchanges that code for tokens at the token endpoint.
- Implicit (deprecated) — originally designed for browser-only apps. It returned the access token directly in the URL fragment. Because the token leaks through browser history and referrers, RFC 9700 formally deprecates this flow.
- Resource owner password credentials (ROPC) — the client collects the user's password directly. The user's credentials end up in the client's hands, which defeats the point of delegation and breaks with MFA and passkeys, so RFC 9700 strongly discourages it.
- Client credentials — used for server-to-server communication where there is no user. The client authenticates with its own credentials and gets a token for a consented scope.
A fifth flow, the device authorization grant (RFC 8628), handles login on devices without browsers, like smart TVs and CLI tools.
The recommended flow: authorization code with PKCE
The current baseline, from RFC 9700, is the authorization code flow combined with Proof Key for Code Exchange (PKCE, RFC 7636):
- The client creates a random secret called a code verifier and derives a code challenge from it (usually a SHA-256 hash).
- It redirects the user to the authorization server's
/authorizeendpoint, sending the challenge, the requested scope, and astatevalue. - The user logs in and consents. The server redirects back to the client with an authorization code (and echoes the
state). - The client exchanges the code for tokens at the
/tokenendpoint, sending the code verifier along with it. - The server verifies that the verifier matches the original challenge, then issues an access token (and optionally a refresh token).
PKCE binds the authorization request to the token request. Even if an attacker intercepts the authorization code, they cannot exchange it because they do not hold the code verifier. This prevents authorization-code injection and some CSRF attacks, which is why PKCE is now recommended for all client types, not just mobile apps.
How to secure an OAuth implementation
Best current practice is codified in RFC 9700 (BCP 212, published January 2025). The key requirements are:
- Use the authorization code flow with PKCE for everything, including single-page and mobile apps. Do not use the implicit grant.
- Do not use the resource owner password credentials grant. Prefer the authorization code flow.
- Match redirect URIs exactly. The server compares the
redirect_uriin each request against the exact registered value — no pattern matching, no wildcards, no prefix rules — so an attacker cannot redirect the authorization code to their own site. - Use the
stateparameter as an anti-CSRF token and validate it on return. - Protect tokens in transit and at rest. Bearer tokens travel over HTTPS only and are stored server-side in secure storage, never in URLs or logs.
- Keep refresh tokens separate and protected, and revoke them when no longer needed.
- Where supported, use sender-constrained tokens such as mutual TLS (RFC 8705) or DPoP (RFC 9449) so a stolen token cannot be replayed.
FAQ
What is the difference between OAuth and OpenID Connect?
OAuth 2.0 is an authorization framework that lets a client access a user's resources with limited, scoped tokens. It does not identify the user on its own. OpenID Connect (OIDC) is an authentication layer built on top of OAuth 2.0 that adds an ID token carrying the user's identity, so a client can both verify who the user is and access their resources.
What are the four roles in OAuth 2.0?
The resource owner (the user who grants access), the resource server (which hosts the protected resources), the client (the application requesting access on the user's behalf), and the authorization server (which authenticates the user and issues tokens). The user's credentials are only ever shared with the authorization server, never with the client.
What is the difference between an access token and a refresh token?
An access token is the short-lived credential a client presents to get protected resources. A refresh token is a longer-lived credential the client exchanges for new access tokens after the current one expires, letting a session continue without asking the user to log in again.
Why is the implicit flow deprecated?
The implicit flow returned the access token directly in the URL fragment, where it leaked through browser history, referrers, and logs, and it could not use refresh tokens. RFC 9700 (BCP 212) deprecates it in favor of the authorization code flow with PKCE, which modern browsers and CORS fully support.
Does OAuth allow a website to see my password?
No. With OAuth, you authenticate only at the authorization server. Your password never reaches the third-party client; the client receives a scoped token that lets it access only the resources you approved.
Sources
- RFC 6749 — The OAuth 2.0 Authorization Framework (rfc-editor.org
- IETF)
- RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage (rfc-editor.org
- IETF)
- RFC 7636 — Proof Key for Code Exchange (rfc-editor.org
- IETF)
- RFC 9700 — Best Current Practice for OAuth 2.0 Security (rfc-editor.org
- IETF
- BCP 212)
- Wikipedia — OAuth (en.wikipedia.org
- CC BY-SA 4.0)
Share this guide
Related guides
- JWT explained: what a JSON Web Token is and how it works
What a JSON Web Token is, how the header.payload.signature structure works, which claims and algorithms exist, and how to validate JWTs safely.
- How to add JWT authentication to a Node.js API: a practical guide
Step-by-step implementation of JWT authentication on a Node.js/Express API: password hashing, login endpoint, token verification middleware, refresh tokens, and the common security pitfalls.
- What is authentication? Passwords, biometrics, SSO, and modern methods explained
Authentication is the process of verifying who you are. Learn how passwords, multi-factor authentication, biometrics, SSO, OAuth, and password managers work — and which methods offer the best protection for your application.