Best way to implement “act as user” OAuth for agents (Authorization Code + PKCE) without building token storage/rotation
AI Agent Trust & Governance

Best way to implement “act as user” OAuth for agents (Authorization Code + PKCE) without building token storage/rotation

8 min read

Quick Answer: The cleanest way to implement “act as user” OAuth for agents with Authorization Code + PKCE—without owning token storage and rotation—is to offload it to an MCP runtime like Arcade that sits between the LLM and your systems: you call auth.start, let it handle OAuth, and then invoke scoped tools (e.g., Google.SendEmail) with zero token exposure to the model.

Frequently Asked Questions

How do I safely let an AI agent “act as the user” with OAuth without managing tokens myself?

Short Answer: Use an authorization layer that handles OAuth 2.0 + PKCE, token storage, and refresh for you, then expose user-scoped actions as tools the agent can call—never as raw tokens the model can see.

Expanded Explanation:
Most “act as user” experiments stall when you hit OAuth 2.0 in production. Getting a demo working isn’t hard; keeping refresh tokens alive, mapped to the right user, and locked down per integration is. Agents need to send emails, create events, or update tickets as the user, not as a global service account, but you don’t want to rebuild an auth service for every provider.

The pattern that scales is: centralize OAuth + PKCE and token lifecycle in a runtime, not in your prompts or agent graph. With Arcade’s MCP runtime, your agent kicks off an auth flow (client.auth.start(...)), Arcade runs the Authorization Code + PKCE flow with proper scopes, persists and refreshes tokens, and exposes tools like Gmail.ListEmails or Google.CreateEvent. The LLM only sees tool inputs/outputs—not access tokens—so you get “act as user” behavior with user-specific permissions and no token headaches.

Key Takeaways:

  • Don’t give models tokens; give them tools that execute with user-scoped OAuth behind the scenes.
  • Centralizing OAuth + PKCE in an MCP runtime like Arcade lets you avoid building token storage, refresh logic, and permission mapping yourself.

What’s the practical process for implementing Authorization Code + PKCE for agents without owning token storage/rotation?

Short Answer: Delegate OAuth flows to an external runtime (like Arcade), call a simple auth API from your agent, and let that runtime manage PKCE, token persistence, and refresh while you focus on tools and prompts.

Expanded Explanation:
If you roll your own “act as user” OAuth, you end up writing the same code again and again: generating code verifiers/challenges, storing state, exchanging codes, handling refresh tokens, and dealing with invalid_grant errors when something inevitably breaks. Multiply that by Google, Microsoft, Slack, GitHub, Salesforce, and you’ve quietly built an auth platform instead of an agent.

With Arcade, the process is: your app triggers an auth flow for a user; Arcade runs Authorization Code + PKCE with the provider, stores and refreshes tokens, and binds them to that user and that integration. Your agent then calls tools over MCP—Arcade injects the right credentials at runtime. You never touch tokens, and your agent logic stays focused on actions (“send email,” “create meeting”) instead of auth minutiae.

Steps:

  1. Initiate auth for a user from your backend or agent host using Arcade’s SDK (e.g., client.auth.start({ provider: 'google', user_id })) and send the user to the returned OAuth URL.
  2. Let Arcade complete the PKCE flow and persist tokens; it handles redirect callbacks, code exchange, token storage, and refresh behind the scenes.
  3. Call MCP tools as the user (e.g., Google.SendEmail, Google.CreateEvent, Gmail.ListEmails), and Arcade transparently applies the correct user-scoped credentials and permissions on each tool execution.

What’s the difference between building my own OAuth + token storage vs. using an MCP runtime like Arcade?

Short Answer: DIY means you own OAuth flows, token databases, refresh logic, and permission mapping; an MCP runtime like Arcade gives you managed OAuth, user-specific authorization, and ready-to-use tools without exposing tokens to the model.

Expanded Explanation:
When you build in-house, you implement Authorization Code + PKCE per provider, store tokens securely, design a token schema keyed by users and scopes, implement refresh logic, add rotation and revocation handling, and then wire it all into your agent’s tool layer. It works—until you need a second provider, a new team comes in, or security asks for audit logs, RBAC, and IDP integration.

Arcade inverts that burden. You integrate once with Arcade’s runtime. It runs OAuth 2.0 and PKCE with your existing providers, stores and refreshes tokens, and enforces user-specific permissions. You get a catalog of agent-optimized MCP tools—Gmail, Google Calendar, Slack, GitHub, Salesforce, HubSpot, Linear—that already implement the “act as user” pattern. The agent calls tools; Arcade handles the credentials and authorization gates.

Comparison Snapshot:

  • Option A (DIY OAuth + tokens):
    • Build and maintain OAuth flows, token storage, refresh, and audit yourself.
    • Tight coupling between auth, agent logic, and each provider.
  • Option B (Arcade MCP runtime):
    • Outsource OAuth 2.0 + PKCE, token lifecycle, and user identity to a single runtime.
    • Use MCP tools that execute actions with user-specific permissions and zero token exposure to the LLM.
  • Best for:
    • Teams who want multi-user, “act as user” agents in production without morphing into an auth team or reimplementing token storage for every integration.

How do I actually wire Authorization Code + PKCE into my agent stack with Arcade?

Short Answer: You call Arcade’s SDK to start auth, wait for completion, then let the agent call MCP tools; Arcade injects user-specific credentials at runtime and enforces scopes, so your implementation stays minimal.

Expanded Explanation:
In practice, integrating OAuth for agents should feel like adding one capability, not rebuilding your identity stack. With Arcade, you treat auth as just another agent capability: authenticate a user once, then let your agent use tools to act as that user across Gmail, Calendar, Slack, CRM, and more.

Your app (or orchestrator like LangGraph) triggers auth.start, gets back an OAuth URL and correlation ID, and redirects the user. Arcade handles Authorization Code + PKCE and signals back when the user is authorized (e.g., via webhook or polling wait_for_completion). From then on, any call to Google.SendEmail or Google.CreateEvent for that user runs with their actual OAuth-scoped permissions. No manual token lookups, no secrets in prompts, no reuse of a shared service account.

What You Need:

  • An Arcade account and SDK integration in your backend or orchestrator to call auth.start / wait_for_completion and invoke MCP tools.
  • Configured OAuth clients with your providers (Google, Slack, GitHub, Salesforce, etc.), connected to Arcade so it can run Authorization Code + PKCE and store tokens securely on your behalf.

How does this approach improve long-term security and scalability for “act as user” agents?

Short Answer: Centralizing OAuth and token management in an MCP runtime with user-specific authorization gives you clearer boundaries, better governance (RBAC, audit logs, SSO), and far less brittle code than scattered refresh logic and shared service accounts.

Expanded Explanation:
The security problem with most agent demos is simple: they either embed tokens in prompts or rely on a single, over-scoped service account. That may work in a hackathon, but it fails in a SOC review. Agents should act with the same permissions as the human user, through your existing identity provider and OAuth flows, with an audit trail of every action they take.

Arcade’s runtime enforces authorization in code, not in prompts. Each tool call is executed on behalf of a specific user with scoped OAuth tokens that never touch the model. You get enterprise controls—tenant isolation, audit logs, RBAC, SSO/SAML—so security teams can see exactly which agent did what, when, and under whose authority. Scaling from one integration to many becomes a matter of enabling more MCP tools, not copying fragile token storage patterns around your codebase.

Why It Matters:

  • Security & compliance: User-specific permissions, scoped OAuth, IDP integration, and audit trails reduce blast radius and make security reviews straightforward.
  • Operational sanity: Removing custom token storage/rotation logic from your app cuts down on 2 a.m. refresh token failures and lets your team focus on designing reliable, agent-optimized tools instead of patching auth.

Quick Recap

Letting agents “act as the user” safely is an authorization problem, not just a prompt trick. If you try to own Authorization Code + PKCE, token storage, and rotation for every provider, you’ve accidentally become an auth platform. Offloading that to an MCP runtime like Arcade gives you managed OAuth and user-specific authorization, plus a catalog of agent-optimized tools (Gmail, Google Calendar, Slack, GitHub, Salesforce, HubSpot, Linear) that execute with zero token exposure to the LLM. Your agents move from chat to action—sending emails, creating events, updating CRM records—as the user, with scoped access and full governance.

Next Step

Get Started