OAuth breaks in production because engineers treat it as a configuration checkbox rather than a protocol with moving parts. OAuth 2.0 sits between high-level concepts and implementation code: authorization codes move between parties, tokens carry specific claims with expiration clocks, and PKCE (Proof Key for Code Exchange) binds the whole exchange to the client that initiated it. 

AI engineers who build agents need these mechanics because their systems run without a user present to click "re-authorize" when a token expires, a scope request is denied, or a refresh cycle fails silently at 3 AM.

TL;DR

  • OAuth 2.0's Authorization Code flow with PKCE is the only flow AI engineers should use for production agent connections.
  • Access tokens expire in minutes to hours; refresh tokens keep agents running for weeks without user interaction, but they require proactive management.
  • Scopes control which API operations a token can call, not which records it returns. Data-level permissions are a separate problem OAuth does not solve.
  • Agents that treat OAuth as a setup-and-forget step will silently lose access to data sources when tokens expire or get revoked.


How Does the Authorization Code Flow Work?

The Authorization Code flow moves specific data between specific parties across five steps. Each step has a defined input, output, and failure mode.

Step 1: Authorization request

The client application constructs a URL pointing to the authorization server's /authorize endpoint and redirects the user's browser to it. The URL includes these parameters:

  • client_id: identifies the application
  • redirect_uri: where to send the user back after consent
  • response_type=code: requests an authorization code
  • scope: the permissions being requested (space-separated strings)
  • state: a cryptographically random string for Cross-Site Request Forgery (CSRF) protection
  • code_challenge and code_challenge_method=S256: the PKCE proof (covered below)

Before constructing this URL, the client generates a code_verifier: 32 bytes of cryptographically random data, base64url-encoded into a 43-character string. It then computes the SHA-256 hash of the code_verifier and base64url-encodes it to form the code_challenge. The plain method (sending the verifier as the challenge) should never be used; many providers reject plain.

Step 2: User consent

The authorization server authenticates the user (prompts login if no session exists), then displays a consent screen showing which permissions the application is requesting. The user approves or denies. The client receives no data during this step, which means no error handling is possible here. For agents, this is the only moment a human is in the loop.

Step 3: Code return

If the user approves, the authorization server redirects the browser back to the redirect_uri with two parameters appended: a short-lived authorization code (typically valid for 1–10 minutes) and the state parameter. The client must validate state before proceeding. A mismatched or missing state value indicates a potential CSRF attack, and the client should abort the flow immediately.

Step 4: Code exchange (with PKCE)

The client sends a server-to-server POST request to the authorization server's /token endpoint. This request never passes through the browser. It includes the grant_type (set to authorization_code), the authorization code, the client_id, the client_secret (for confidential clients), and the redirect_uri (exact match). When PKCE is in use, the request also includes the code_verifier, the original random string whose hash was sent as the code_challenge in Step 1.

The authorization server verifies the code hasn't expired or been reused, checks the client credentials, and hashes the code_verifier to compare against the stored code_challenge. PKCE prevents interception at this exact point: even if an attacker captured the authorization code in Step 3, they cannot exchange it for tokens without the code_verifier, which was never exposed in the browser redirect. The authorization code is a bearer credential traveling through a browser redirect, and PKCE is the only mechanism that binds it to the client that started the flow.

Step 5: Token issuance and API access

The authorization server returns an access token (short-lived, typically 30 minutes to 1 hour), a refresh token (longer-lived, used to get new access tokens), the token type (typically Bearer), and the granted scopes. The scopes may differ from what you requested. Always validate the scopes in the response, not the scopes in your request, because a user might approve a subset or the provider might downgrade permissions silently.

The client includes the access token in the Authorization: Bearer <token> header of each API request. The resource server validates the token and returns data if the token is valid and the scopes permit the operation. From this point forward, the agent is on its own.

What Do OAuth Tokens Actually Contain?

An access token represents a set of granted permissions for a specific client to access a specific resource, valid for a limited time. Depending on the provider, it takes one of two forms, and the form determines how your agent validates and handles revocation.

Opaque tokens

An opaque token is an arbitrary string with no client-readable content. The resource server must call the authorization server's introspection endpoint on every request to validate it. Revocation is immediate because the server stops accepting the token on the next introspection call. The cost is a network round-trip on every API request, which adds latency and creates a dependency on the authorization server's availability.

JWT tokens

A JWT (JSON Web Token) is a compact, URL-safe representation of claims encoded as a JSON object, typically used as the payload of a JSON Web Signature (JWS) or the plaintext of a JSON Web Encryption (JWE). The resource server can validate locally by checking the signature and expiration, so it does not need a round-trip. The tradeoff is that revocation is harder: the token remains valid until its exp claim passes, even after the server revokes it. For agents running continuously, a revoked JWT can keep making successful API calls for up to an hour.

When the token is a JWT, it typically contains these RFC 9068 claims: iss (issuer, which authorization server created it), sub (subject, which user authorized it), aud (audience, which resource server it targets), exp (expiration timestamp), iat (issued-at timestamp), client_id (which application requested it), jti (unique token ID for replay prevention), and scope (what operations it permits).

What tokens do NOT contain

Access tokens typically omit user data, passwords, or data-layer permissions specifying which records the user can see. The token grants access to API endpoints; which data those endpoints return depends on the provider's internal permission model. Engineers who assume a valid token means "access to all the user's data" are confusing authentication with authorization at the data layer.

Refresh tokens vs. access tokens

A refresh token has one purpose: requesting a new access token at the /token endpoint when the current one expires. It cannot call APIs. Some providers rotate refresh tokens on each use (issuing a new refresh token alongside the new access token), while others keep the same refresh token until it is explicitly revoked. Microsoft has a rotation quirk worth noting: old refresh tokens are not automatically revoked when new ones are issued, so you must explicitly delete them. For agents managing hundreds of connections, these provider-specific behaviors create a matrix of token lifecycle logic that compounds with every new integration.

How Do Scopes Define What an Agent Can Access?

Scopes are strings included in the authorization request that specify what permissions the application is requesting. The user sees these scopes on the consent screen and approves or denies them. The resulting access token is limited to the approved scopes.

Scopes operate at the API level, not the data level

Engineers building agent systems misunderstand this more than any other aspect of OAuth. A scope like Mail.Read in Microsoft Graph grants permission to call the mail read endpoint. It does not specify which messages or folders are readable; that is determined by the provider's internal permission model (Salesforce profiles, Google organizational units, Microsoft 365 access policies).

For multi-user agents, this distinction is critical: two users may both have tokens with identical scopes, but their tokens return different data based on each user's internal permissions. Scopes cannot enforce Row-Level Security (RLS), multi-tenancy boundaries, or relationship-based access. Data-level permissions must be enforced separately, typically through retrieval access controls. An agent that relies solely on OAuth scopes for data isolation has a compliance gap, not a feature.

Scope design for agents

Requesting too few scopes means the agent cannot access data it needs, and adding scopes later requires re-authorization, which means pulling the user back into the loop. Requesting too many scopes triggers security review flags and increases the blast radius of a compromised token.

Scope syntax varies across providers: 

Every new provider integration means learning a new scope vocabulary, and getting it wrong means either broken functionality or a failed security review.

How Does OAuth 2.0 Work Differently for AI Agents?

The protocol mechanics are identical. What changes is the operating context, and that context affects every component in the flow.

OAuth Component Traditional Web App AI Agent Why It Matters
Authorization request User clicks "Connect" in the browser, app redirects to authorization server interactively User clicks "Connect" once via embeddable widget or onboarding flow; agent operates autonomously afterward The agent cannot prompt the user for re-authorization during normal operation. The initial consent must request all needed scopes upfront.
Consent User reviews consent screen and approves in the same session User reviews and approves once; the agent uses the granted access for weeks or months without further user interaction Scope requests must be carefully designed. Too narrow and the agent cannot function; too broad and the security team rejects the integration.
Access token usage App makes API calls during user's active session; user present for error handling Agent makes API calls continuously in the background; no user present to handle errors The agent must detect token expiration, API errors, and scope changes programmatically and surface failures through monitoring, not UI alerts.
Token refresh Triggered when user returns to app and token has expired; user available for re-auth if refresh fails Triggered proactively on a schedule before expiration; no user available if refresh fails Proactive refresh prevents gaps in data access. Failed refresh requires automated alerting and potentially queuing a reconnection request to the user.
Revocation handling User revokes access; app detects on next user-initiated request User or admin revokes access; agent must detect via polling or webhook without user interaction The agent must monitor for revocation independently. Undetected revocation means the agent silently loses access to a data source.
Multi-connection management App manages one user's token at a time per session Agent manages hundreds of users' tokens concurrently, each with different providers and expiration schedules Token storage must be tenant-isolated, refresh orchestration must handle concurrent operations, and monitoring must scale across all connections.

A documented failure in Claude Code's GitHub repository shows what happens when agent-specific OAuth handling is missing: the agent had no automatic refresh mechanism and required manual intervention, breaking the autonomous workflow entirely. The assumption that someone would be around to fix expired tokens caused the failure, not the OAuth protocol itself. 

How Does Airbyte's Agent Engine Handle OAuth Mechanics?

Airbyte's Agent Engine implements these OAuth mechanics across 600+ connectors so that agent teams interact with a connection identifier, not raw tokens or OAuth endpoints. The embeddable widget handles the authorization request, consent, and code exchange. Token storage uses AES-256 encryption via secret managers with tenant-level isolation. Refresh orchestration runs automatically, handling provider-specific token lifetime and response variations.

Scope requests are pre-configured per connector to follow least-privilege principles. When the protocol mechanics require provider-specific handling (PKCE parameters, refresh token rotation, scope format), the connector handles it. Your agent team writes retrieval logic and tool definitions while Agent Engine manages every OAuth handshake, refresh cycle, and token rotation underneath.

What Should AI Engineers Understand About How OAuth Works?

The engineers who debug auth failures fastest are the ones who can trace a token from its authorization request through consent, code exchange, issuance, refresh, and eventual revocation. That mental model turns opaque 401 errors into diagnosable problems: a scope mismatch, an expired refresh token, a provider that silently downgraded permissions.

Airbyte's Agent Engine gives your team that operating context without requiring them to build it from scratch.

Talk to sales to see how Airbyte handles OAuth mechanics across your data sources.

You build the agent. We'll bring the data.

Authenticate once. Fetch, search, and write in real-time.

Try Agent Engine →
Airbyte mascot


Frequently Asked Questions

What is the difference between an access token and a refresh token?

An access token travels with every API call and expires quickly, so a compromised token has a limited window of exposure. A refresh token stays on the server side and never touches a resource server, but it carries higher risk if leaked because it can generate new access tokens indefinitely until revoked. Store refresh tokens with the same security controls you apply to database credentials.

What is PKCE and why does it matter for AI agents?

Without PKCE, any process that intercepts the authorization code during the browser redirect can exchange it for tokens. PKCE closes this gap by requiring proof that only the original client possesses. The OAuth 2.1 draft makes PKCE mandatory for all clients using the authorization code flow, though confidential clients that authenticate at the token endpoint may be exempt under Section 7.5.1.

What happens when an OAuth token expires and the agent is running autonomously?

The agent's refresh logic detects the approaching expiration and sends a refresh request using the refresh token; if successful, the agent receives a new access token and continues operating. If the refresh fails (token revoked, provider policy changed, refresh token expired), the agent must log the failure, alert the monitoring system, and queue a reconnection request for the user. Never overwrite existing credentials during a failed refresh attempt, because destroying a still-valid refresh token while trying to obtain a new one leaves the agent with no recovery path.

Does OAuth 2.0 control which specific records an agent can see?

No. An agent with a Mail.Read scope and an admin's token may see every mailbox in the organization, while the same scope with a standard user's token returns only that user's inbox. The provider's internal permission model (admin roles, organizational units, sharing policies) determines record-level access, so agents that need data isolation between users must enforce it through a separate retrieval access control layer.

How is OAuth 2.1 different from OAuth 2.0 mechanically?

OAuth 2.1 consolidates security best practices from RFC 9700: PKCE is required for all clients using the authorization code flow, the Implicit Grant and Resource Owner Password Credentials flows are removed, redirect URI matching is strict exact-match only, and bearer tokens in query strings are prohibited. Model Context Protocol (MCP) requires OAuth 2.1 with PKCE for its authorization flow, but agents connecting to MCP servers do not universally use OAuth 2.1 by default and may rely on other authentication methods such as API keys or long-lived tokens.

Table of contents

Loading more...

Try the Agent Engine

We're building the future of agent data infrastructure. Be amongst the first to explore our new platform and get access to our latest features.