OAuth 2.0
OAuth 2.0 is an authorization framework that allows users to delegate access to specific resources to a third-party application without directly sharing their password with it. When you log into another app with your Google account, or grant a CI tool access to your GitHub repositories, OAuth is the protocol working behind the scenes. It defines four roles -- Resource Owner (user), Client (third-party app), Authorization Server, and Resource Server (protected resource) -- and standardizes the flow by which authorization codes and access tokens are exchanged among them. OAuth focuses on authorization, not authentication; OpenID Connect is the layer built on top of OAuth that standardizes authentication as well.
βΆArchitecture Diagram
π ProcessDashed line animations indicate the flow direction of data or requests
Suppose an app needs to read a user's Google Calendar events. The simplest approach would be to ask the user for their Google password. But that would give the app access not just to the calendar but also to email, Drive, payment information, and everything else. When the user no longer trusts the app and wants to revoke access, they must change their password -- which disconnects every other app using that same password. Directly handing over a password makes it impossible to narrow the scope of access, to revoke it, or to audit it -- three problems at once. What was needed was a way to allow a third party access to only part of your resources, for a defined period, in a form that can be revoked at any time.
Before OAuth there were ways to link authentication between services, but no standard existed. Each platform invented its own token-issuance scheme, and third-party app developers had to implement a different authentication flow for each service. In 2007, engineers from Twitter, Google, Yahoo, and others came together to create OAuth 1.0, but its cryptographic signing requirements were complex enough that implementation was difficult. OAuth 2.0, published as RFC 6749 in 2012, reduced that complexity by instead requiring TLS. By delegating security to tokens and HTTPS rather than signatures, implementation became simpler and the framework could be extended to accommodate new client types such as mobile apps and SPAs. Today most major platforms -- Google, GitHub, Kakao, and others -- manage API access permissions based on OAuth 2.0.
Let us trace the Authorization Code Grant flow, the most widely used flow in OAuth 2.0. When a user clicks 'Sign in with Google' in a third-party app, the app redirects the user to Google's authorization server. At that point it sends via URL parameters what permissions it is requesting (scope) and where it wants the response delivered (redirect_uri). Google's authorization server shows the user a consent screen: 'This app wants to read your Calendar events. Do you permit this?' When the user consents, the authorization server returns a single-use authorization code to the redirect_uri. The backend server of the third-party app receives this authorization code and sends it back to the authorization server in exchange for an access token. This exchange happens on the backend, so the token is never exposed to the browser. The app places the received access token in the Authorization header of API requests to the resource server. The resource server verifies the token's validity and scope, then responds with only the data permitted by those scopes. To defend against interception of the authorization code, there is an additional mechanism called PKCE. The client includes the hash of a random value in the authorization request and sends the original value when exchanging the token, allowing the server to verify they match. PKCE is mandatory for public clients (SPAs, mobile apps).
The most frequent confusion with OAuth is the distinction between authentication and authorization. OAuth 2.0 is an authorization framework. It deals with 'is this app allowed to read my calendar?' -- not with 'is this person really who they say they are?' An access token is proof of permission, not proof of identity. To verify identity as in 'Sign in with Google', OpenID Connect must be layered on top of OAuth to receive an ID Token. The relationship with JWT is another source of confusion. OAuth is a framework that defines the procedure for exchanging tokens, and JWT is one of the formats those tokens can take. An OAuth access token does not have to be a JWT, but in practice JWT format is commonly used. OAuth defines 'who delegates what permissions to whom, and how'; JWT defines 'what structure the token carrying that permission information takes'. API Keys are also worth comparing. An API Key is a simple approach where an issued key is placed directly in requests, but there is no per-user permission separation or consent process, and if the key is leaked, all access is compromised. Where fine-grained user-consent-based permission delegation is needed, OAuth is the appropriate choice.
Commonly Compared Concepts
JWT
A self-contained token that identifies the requester without the server storing any state
OAuth defines the procedure for delegating permissions (the framework), while JWT defines the format (data structure) of the tokens used in that procedure.
WebAuthn
A web authentication standard that proves the user with a public-key credential instead of a password
OAuth is a flow for delegating permissions to another service, while WebAuthn is a login method that proves the current user to the current site with a public-key credential. The focus differs between delegation and identity proof.
Social login is the most visible use of OAuth 2.0, but in reality it plays the role of the standard for controlling API access between services. When a third-party app needs to access a user's data, OAuth is the natural choice. CI/CD tools accessing GitHub repositories, analytics tools reading Google Analytics data, and Slack bots posting messages to channels all go through an OAuth flow. OAuth is also used between internal microservices. For server-to-server communication where no user is involved, the Client Credentials Grant allows a service to obtain a token using its own credentials. When implementing, the key caution is to request the minimum scope necessary. Requesting full account access when only calendar read is needed destroys user trust and increases the blast radius if the token is leaked. Failing to validate redirect_uri precisely can allow an authorization code to fall into an attacker's hands, so it must be verified to match exactly the registered URI.