Modern apps with agentic workflows need access to user data without asking for passwords. The OAuth 2.0 authorization protocol enables access, whether reading calendar events or posting to Slack.
OAuth 2.0 is the standard for authorization, replacing the broken model of credential sharing. Instead of asking for login credentials, apps use OAuth to request scoped access tokens. These tokens act as temporary, permission-limited keys to user data without revealing passwords or long-term secrets.
Legacy systems relied on users sharing their user credentials with third-party applications — a dangerous pattern that led to:
OAuth introduced a secure delegation model with three core advantages:
OAuth 2.0 is now the backbone of secure access delegation across the web, used by Google, Microsoft, GitHub, Amazon, Slack, and nearly every major API provider.
By the end of this guide, you’ll understand:
OAuth 2.0 operates through four key roles in the authorization flow. Each one plays a specific part in the flow and defines the trust boundaries.
1. Resource owner: The entity that owns the data is usually the user. They decide whether to grant access to their data (e.g., email, photos, repos) via the authorization server.
2. Client: The app requesting access on behalf of the user. This could be:
OAuth treats the client as an untrusted third party — it never sees the user’s credentials and must request access via tokens.
3. Authorization server: The trusted identity provider. It:
Google, GitHub, Okta, Auth0, and Azure AD are common examples of authorization servers.
4. Resource server
The API or service that stores the user’s data and accepts access tokens. It validates incoming tokens and checks if the token grants the required scopes to access a specific endpoint or resource.
Slack can access your GitHub pull requests using OAuth, without asking for your password. Here’s how that works:
This flow:
OAuth 2.0 provides multiple grant types designed for different app types, trust levels, and security boundaries.
Choosing the right grant type isn’t just about what works — it’s about minimizing risk.
Best for: Web apps, SPAs, and mobile apps
Security posture: Strongest option for apps with user-facing logins
The authorization code flow uses a secure handshake to exchange credentials for tokens, which is especially suited for apps with user-facing logins.
This flow involves a multi-step handshake:
Public clients (like SPAs or mobile apps) can’t safely store secrets. PKCE — Proof Key for Code Exchange — adds a cryptographic challenge-response layer to block token interception. It replaces older, insecure flows like the Implicit Grant, which is now deprecated.
💡 Dev tip: Even if your app is server-rendered, use PKCE — it's now the recommended default across the board.
Best for: Machine-to-machine (M2M) apps — no user involved
Security posture: Simple and secure — if used correctly
In this flow:
Use cases:
⚠️ Security note: Never expose client_secret in frontend or mobile apps. This flow assumes the client runs in a secure, server-controlled environment.
OAuth 2.0 controls access through scopes, claims, and permissions - each handling a specific part of access control at runtime.
These three components work together to define:
Scopes define the boundaries of access requested by the client app. They’re passed during the initial access token request and displayed to the user during user consent.
Examples:
The Authorization Server uses scopes to:
💡 Dev Tip: Request only the minimum scopes you need. Over-requesting increases the risk surface and may get your app flagged or rejected.
Claims are metadata baked into the token, especially in JWT-based tokens.
They describe:
Sample decoded JWT claims:
💡 Resource servers rely on claims to make access decisions. If the token lacks a role or tenant claim, your API may deny the request.
Scopes and claims are inputs, but permissions are what actually get enforced.
For example:
Permissions logic typically happens:
🔐 For fine-grained access control, use custom claims to encode roles, org IDs, or permissions, and validate them inside your app.
OAuth 2.0 uses access tokens to authorize client apps, typically short-lived and actionable. Optional refresh tokens are used to extend access without user interaction.
There are two main types:
These tokens are sent in API requests to prove authorization. They’re typically JWTs or opaque strings.
Rotate access tokens frequently to limit damage if exposed.
Access tokens expire fast. Refresh tokens let clients get new access tokens without bothering the user again.
But they must be handled with care:
💡 Dev tip: Use refresh tokens only from secure, trusted environments — never from the frontend in a browser.
Machine-to-machine flows like CI/CD and microservices rely on the Client Credentials Grant. Here's what the access token request exchange looks like:
The server responds with:
This model works well for:
There’s no user — just secured system-to-system communication.
OAuth combines convenience and risk. Follow these authorization best practices to reduce exposure and improve control:
Tokens are credentials. Transmitting them over HTTP exposes users to interception.
Mobile apps and SPAs can’t keep secrets safe. Avoid using client_secret in any public client.
PKCE secures the Authorization Code flow when the client can't protect secrets. It’s essential for mobile and browser-based apps.
The state value prevents CSRF by linking authorization requests to client sessions. Always validate it on return.
Access tokens should expire quickly — minutes, not hours. Use refresh tokens to re-authenticate securely.
To further reduce risk, rotate refresh tokens after each use. This ensures compromised tokens can’t be reused.
OAuth 2.0 handles authorization, not identity. OpenID Connect builds on OAuth to add user authentication and identity claims.
OpenID Connect (OIDC) builds on OAuth 2.0 to add identity authentication.
Key components added by OIDC:
OIDC enables:
💡 If you’re building login flows — not just API access — you need OpenID Connect, not just OAuth.
You’ve learned how OAuth 2.0 secures application access without sharing passwords and the different authorization grants used to authorize client apps. We covered how the Client Credentials Flow enables machine-to-machine communication, allowing secure backend interactions. Additionally, you now understand the roles, scopes, claims, and security best practices essential for OAuth 2.0 implementations.
To deepen your understanding, try building OAuth flows with authorization endpoints like Google or GitHub. Explore OpenID Connect to add an authentication protocol and SSO to your apps. Learn about token introspection and revocation to strengthen your token management.
Start building your OAuth 2.0 integrations today and secure your app’s access with confidence.
The OAuth 2.0 protocol enables users to let external applications access their data points while protecting their user credentials. Users authorize the app before the app receives an authorization code, which serves as the basis for obtaining an access token to access protected data. The system uses temporary tokens that enable users to obtain refreshed access tokens through requests that bypass authentication requirements.
As an OAuth 2.0 authorization process, the Client Credentials Flow provides M2M (machine-to-machine) services that operate without requiring user interaction. The system allows a client entity or service (or backend system) to self-authenticate through client_id and client_secret credentials in order to obtain access tokens needed to access APIs or services.
The Client Credentials Flow differs from other OAuth flows (like the Authorization Code Flow) because it does not require user involvement. While other flows are used when accessing user data, the Client Credentials Flow is used for backend services or systems interacting with each other, where the client acts on its own behalf.
Use the Client Credentials Flow in scenarios where: