OAuth 2.0 is an open standard authorization protocol that enables secure, delegated access to resources without sharing passwords. Instead of giving an application your credentials, OAuth 2.0 lets you grant limited permissions directly to that app—keeping your actual password safe while maintaining control over what data it can access.
Before OAuth 2.0 became widespread, users faced a security nightmare. Want to let a third-party app access your Google contacts? You'd give it your Google password. That app could then access everything—emails, files, photos—without any restrictions. If the app got hacked, your credentials were compromised.
OAuth 2.0 solves this by introducing a middleman—the authorization server. Instead of sharing your password with every service, you authenticate once with a trusted provider (like Google, GitHub, or Facebook), then grant specific permissions to the requesting application. The app receives an access token—a temporary credential that grants only the permissions you approved.
This approach protects you and benefits service providers too. They don't need to store passwords, reduce breach risk, and maintain an audit trail of what data gets accessed and when.
Understanding OAuth 2.0 requires knowing four key players in the flow:
That's you. The person who owns the data and controls permissions. You decide what the application can do with your information.
The app requesting access to your data. It could be a web app, mobile app, or desktop application. The client never sees your password—it only handles tokens.
The trusted intermediary that verifies your identity and issues tokens. Google's OAuth server, GitHub's OAuth server, and Facebook's are examples. It handles the login process and decides whether to grant the client application access.
The API that actually holds your data. When the client has a valid token, it contacts the resource server to fetch information. Often, the authorization server and resource server are the same organization.
OAuth 2.0 defines several "grant types"—different methods for exchanging user credentials for access tokens. Choosing the right one depends on your application architecture.
This is the most common flow, especially for web applications. Here's how it works:
The critical step is #6: the authorization code is exchanged for the token on the backend, never exposing the token to the browser. This prevents malicious scripts from stealing tokens.
Older single-page applications (SPAs) used this flow, but it's now considered less secure. The browser receives the access token directly, making it vulnerable to XSS attacks. OAuth 2.0 security best practices now recommend PKCE (Proof Key for Code Exchange) for SPAs instead.
Used when an application needs to access resources on its own behalf, not a user's behalf. For example, a backend service calling another API. The client directly provides its credentials to get a token.
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
The user provides their username and password directly to the client application. The client then exchanges these for an access token. This flow requires high trust and is rarely recommended since it exposes credentials to the client.
Once you've granted permission, the client gets two types of tokens:
A temporary credential that grants access to protected resources. It typically expires within hours (often 1-2 hours). When you make an API request, you include it in the Authorization header:
GET /api/user/profile HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
A long-lived credential (days or months) that lets the client get a new access token without asking you to log in again. When the access token expires, the client exchanges the refresh token for a fresh access token.
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=YOUR_REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
Refresh tokens stay on the backend and are never exposed to the browser, making them much safer than access tokens.
Let's walk through a real scenario: a web app using "Login with GitHub."
You register your app with GitHub and receive a Client ID and Client Secret:
Client ID: a1b2c3d4e5f6g7h8
Client Secret: xyz789abc456def123
Your login button links to GitHub's authorization endpoint:
https://github.com/login/oauth/authorize?
client_id=a1b2c3d4e5f6g7h8
&redirect_uri=https://yourapp.com/callback
&scope=user:email
&state=randomstring123
The state parameter prevents CSRF attacks by verifying that the response came from the same browser that made the request.
GitHub shows the user what permissions you're requesting (user:email in this case). The user clicks "Authorize."
GitHub redirects to your callback URL with an authorization code:
https://yourapp.com/callback?
code=abc123def456
&state=randomstring123
Your backend verifies the state parameter, then exchanges the code for a token. This happens server-to-server:
POST https://github.com/login/oauth/access_token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
client_id=a1b2c3d4e5f6g7h8
&client_secret=xyz789abc456def123
&code=abc123def456
GitHub responds with an access token:
{
"access_token": "ghu_16C7e42F292c6912E7710c838347Ae178B4a",
"expires_in": 28800,
"token_type": "bearer"
}
Now your app can request the user's GitHub profile:
GET https://api.github.com/user HTTP/1.1
Authorization: Bearer ghu_16C7e42F292c6912E7710c838347Ae178B4a
You get back user details (email, name, avatar, etc.) and can create a session for them.
A common point of confusion: OAuth 2.0 is for authorization (granting permissions), while OpenID Connect is for authentication (verifying identity).
OpenID Connect layers on top of OAuth 2.0, adding an ID token that contains information about the user. If you only need to let users log in, OpenID Connect is the better choice. If you need API access permissions, OAuth 2.0 is correct. Many modern providers support both.
OAuth 2.0 is secure by design, but implementation matters. Follow these practices:
You encounter OAuth 2.0 everywhere:
Even with OAuth 2.0, mistakes happen:
OAuth 2.0 has become the industry standard for delegated access, powering billions of login interactions daily. Understanding how it works isn't just useful for engineers building authentication systems—it's essential knowledge for anyone developing secure, modern applications.
No. OAuth 2.0 is an authorization protocol that defines how to grant access. JWT (JSON Web Token) is a token format. OAuth 2.0 can use JWTs as access tokens, but it doesn't have to. You could use OAuth 2.0 with opaque token strings instead. Many implementations combine