Skip to content

Agentic AI & Orchestration

One OAuth Token Can Let an Agent Read the Whole Inbox

A narrow tool menu does not guarantee narrow access. This walkthrough scopes a refund-closeout agent across Gmail, Drive, and Slack without handing its runtime a reusable master credential.

Mara QuinteroAgents & Orchestration Writer

October 21, 2026 · 8 min read

Laptop displaying OAuth scopes beside a refund workflow diagram and a dedicated mailbox settings page.
Laptop displaying OAuth scopes beside a refund workflow diagram and a dedicated mailbox settings page.

Consider a refund-closeout agent with a modest job. After a human approves a refund, the agent reads the approval email from Gmail, saves its receipt in Google Drive, and posts a completion notice to a Slack channel. It cannot decide whether to refund the customer, change the amount, or contact the customer.

The tool menu appears to enforce that boundary. The agent has functions named `find_approved_refund`, `store_receipt`, and `post_closeout_notice`. Yet the first version uses an employee's existing Google OAuth token, which can read and modify that employee's mailbox and files, plus a Slack user token with access to several channels.

That token is the real permission boundary. If the agent runtime, a compromised connector, or an injected instruction can call the underlying APIs outside the intended wrapper, the narrow function names do little. The refund-closeout agent may be able to read unrelated email, replace files, or speak as an employee even though none of those actions appears in its tool list.

Translate the workflow into API operations

OAuth is a delegated authorization system that lets an application act with a user's or service's permission. A scope is the named category of access requested by that application, but scopes are often broader than one workflow step.

Start with verbs, not products. For the refund-closeout agent, the required operations are: search one controlled inbox for approved messages, read the matching message and attachment, create a receipt file in one controlled Drive location, and post text to one Slack channel. It does not need to send email, delete messages, read Slack history, or edit existing receipts.

Now map each operation to the vendor's documented authorization requirement. Gmail's `gmail.readonly` scope permits reading mailbox resources without write operations. That still covers the whole mailbox available to the identity; a query such as `label:approved` filters what the application requests, but it does not prevent the token from requesting other messages.

This distinction matters. An application filter expresses intended behavior. An authorization boundary blocks unintended behavior.

The Gmail API does not offer a scope limited to one label. Giving the agent `gmail.modify` merely so it can mark a processed message as read would widen its authority to modify mailbox content. A narrower design keeps `gmail.

readonly` and records processed message IDs in the workflow database. That adds state management and a duplicate-check before each run, but avoids granting mailbox write access for a cosmetic status change.

For Drive, Google's `drive.file` scope limits the app to files it creates or files explicitly used with it, rather than every file the identity can reach. The receipt uploader can create a new file in the designated location and retain its file ID. Access to the destination should also be restricted through Drive's own sharing controls, because an OAuth scope and a resource permission answer different questions: what API category the app may use, and which files its identity may reach.

Slack's `chat:write` scope lets an app post messages. The bot should join only the refund operations channel, and the app should omit broader scopes for reading channel history or posting to public channels it has not joined. The agent supplies the approved template fields; the connector fixes the destination channel rather than accepting an arbitrary channel ID from the model.

Use separate identities where scopes stay broad

Gmail remains the awkward part of this case. `gmail.readonly` is narrower than a read-write grant, but it is not narrow enough if the identity belongs to an employee whose inbox contains contracts, password resets, and personnel discussions.

Move approvals into a dedicated mailbox used only for refund closeout. The token can still read that entire mailbox, yet the mailbox itself now contains only the records needed for the job. This is resource isolation: limiting the data available to an identity when the vendor's scope model cannot express the desired boundary.

Do not solve one-inbox automation with unrestricted Google Workspace domain-wide delegation, which allows a service account, an identity intended for software rather than a person, to impersonate users when an administrator authorizes it. Google lets administrators limit the API scopes approved for that delegation, but a Gmail read scope combined with broad impersonation remains excessive for this workflow. A dedicated user identity is easier to reason about.

Apply the same separation to Slack. The refund agent gets its own bot installation and channel membership instead of borrowing a human user's token. Audit logs then attribute its posts to the automation identity, offboarding an employee does not break the workflow, and revoking the bot does not interrupt unrelated integrations.

Separate identities create administrative work. Someone must own their lifecycle, test their access, and rotate or revoke credentials when the workflow changes. That cost is visible. The cost of a shared token appears later, during an incident, when responders cannot revoke the refund agent without also disabling other jobs.

Keep durable credentials away from the agent

An OAuth access token is presented to an API, while a refresh token is a longer-lived credential used to obtain new access tokens. The agent worker should not receive the refresh token. Store it in a secrets manager or credential broker, a service that releases or uses credentials under policy, and let the connector obtain an access token only when it needs to call Gmail, Drive, or Slack.

This changes the execution path. The model proposes `find_approved_refund` with a message identifier. A connector validates that the identifier belongs to the dedicated mailbox and matches the approval query, obtains the Gmail access token, makes the API call, and returns only the fields the next step needs. The model never sees the bearer token, which is a credential accepted from whoever presents it.

Repeat that boundary for Drive and Slack. Each connector holds a separate grant, fixes resource identifiers where possible, validates arguments, and returns a reduced response. A prompt injection, an instruction hidden in content that attempts to redirect the model, may still persuade the agent to request an improper action, but the connector should reject an unapproved mailbox, an existing Drive file, or a different Slack channel before an API call occurs.

Short-lived access credentials reduce the useful window after exposure. Google documents limited lifetimes for access tokens, and Slack documents token rotation for apps that enable it. Expiration adds a network exchange and another dependency to long-running jobs; if renewal fails midway, the orchestrator must pause the refund-closeout run, preserve its completed-step state, and retry after credential recovery rather than restarting every side effect.

Expiration is not revocation. A refresh token left in the agent container can mint replacement access after the original token dies, so shortening access-token life while exposing the durable credential changes little.

Test the token, not just the tool schema

Review the deployed grant against the workflow worksheet. Vendor consent screens and application settings should show only the scopes tied to required API calls. Remove scopes retained from prototypes, especially write permissions added to make debugging convenient.

Next, test with controlled data. Put an unrelated message in the dedicated mailbox, an existing file outside the receipt destination, and a private Slack channel that has not added the bot. The connector should refuse or lack access to each resource. A successful test proves less if the agent merely chooses not to request them.

Inspect runtime boundaries as well. The model process should not be able to print environment variables containing tokens, invoke a generic HTTP tool with authorization headers, or call an unrestricted connector method. Logs should record the automation identity, operation, target resource, grant used, approval reference, and result, while excluding token values and unnecessary message content.

Finally, rehearse revocation. Revoke the Gmail grant and confirm that only inbox retrieval stops; Drive receipt storage and Slack posting should retain their own credentials, while the orchestrator holds the run at the failed step. If revoking one token disables every connector, the architecture still has an all-purpose credential regardless of how narrow the visible tools look.

The refund-closeout agent is ready when its permissions match its fixed job, not when it can recover from any missing permission by borrowing a broader token.

Questions people ask

Can

OAuth scopes restrict an agent to one Gmail label?

No. Gmail scopes distinguish categories such as read-only and modify access, but they do not make a label an authorization boundary. Use a dedicated mailbox when the agent must not see unrelated mail, then treat label queries as workflow filters rather than security controls.

Is a service account always safer than a user token?

No. A service account gives automation a separate identity, which improves lifecycle control and attribution, but domain-wide delegation can let it impersonate users across a Workspace domain. Safety depends on the approved scopes, impersonation rights, resource permissions, and where its credentials are stored.

Why hide tokens if the agent only has narrow tools?

A tool schema limits the calls the orchestrator intends to expose. It does not protect a bearer token leaked through logs, environment access, a generic HTTP tool, or a compromised connector. Keeping credentials in a validating gateway preserves the boundary even when the model requests an action outside its job.

What should happen when a short-lived token expires mid-run?

The orchestrator should save which side effects completed, obtain a replacement through the credential broker, and retry only the failed step. For the refund-closeout agent, that prevents a token-renewal failure after receipt upload from creating a second file when Slack posting resumes.

ShareFacebook
ai agentstool use and function callingworkflow automationoauthleast privilegeai agentscredential securityworkflow design

One story a day

The story of the day, in your inbox

One real story about AI each morning — no hype, no alarm, just company for the road.

Read next

A laptop showing an approval diff beside a vendor catalog record for a USB-C dock order.

Agentic AI & Orchestration

Make Your AI Agent Recheck a Price After Approval

A sandbox purchasing agent submitted an approved order from stale data. Binding approval to a source snapshot made the same agent stop when the catalog price changed.

Mara Quintero · 8 min read

A laptop showing a citation ledger with one claim marked partially supported beside its quoted source passage.

Agentic AI & Orchestration

A Second Pass Can Catch AI Citations That Do Not Fit

A research agent can check whether a cited passage supports its claim, but only after claims are split into testable units. The extra pass catches mismatches, not bad sources or missing evidence.

Mara Quintero · 7 min read