# Configure User-Delegated OAuth

> For the complete documentation index, see [llms.txt](https://docs.redpanda.com/llms.txt). Component-specific: [agentic-data-plane-full.txt](https://docs.redpanda.com/agentic-data-plane-full.txt)

---
title: Configure User-Delegated OAuth
latest-operator-version: v26.2.1
latest-console-tag: v3.10.0
latest-connect-version: 4.104.0
latest-redpanda-tag: v26.2.1
docname: user-delegated-oauth
page-component-name: agentic-data-plane
page-version: master
page-component-version: master
page-component-title: Agentic Data Plane
page-relative-src-path: user-delegated-oauth.adoc
page-edit-url: https://github.com/redpanda-data/adp-docs/edit/main/modules/connect/pages/user-delegated-oauth.adoc
description: Have each end-user authenticate against the MCP server's upstream system with their own credentials. Redpanda stores their token in the vault and injects it at call time.
page-topic-type: how-to
personas: platform_engineer, agent_builder, security_compliance_lead
learning-objective-1: Configure an MCP server to use user-delegated OAuth, with either automatic setup or a provider you registered
learning-objective-2: Walk an end-user through the consent flow and verify the connection
learning-objective-3: Troubleshoot scope upgrades, token expiry, and refresh failures
page-git-created-date: "2026-05-28"
page-git-modified-date: "2026-08-03"
---

<!-- Source: https://docs.redpanda.com/agentic-data-plane/connect/user-delegated-oauth.md -->

User-delegated OAuth means each end-user authenticates against the MCP server’s upstream system (for example, Slack, Jira, Google) with their own credentials. Redpanda stores their token in the token vault and injects it at call time. Contrast with service-account OAuth, where one shared identity is used for every caller.

For a self-managed server, Redpanda can set up the OAuth client for you from the server URL, or you can attach an OAuth provider your organization already registered. Managed servers always attach a provider.

After completing this guide, you will be able to:

-   Configure an MCP server to use user-delegated OAuth, with either automatic setup or a provider you registered

-   Walk an end-user through the consent flow and verify the connection

-   Troubleshoot scope upgrades, token expiry, and refresh failures


## [](#prerequisites)Prerequisites

-   For a **managed** MCP server, or to attach a provider your organization already manages on a **self-managed** server: an OAuth provider resource configured on the **Outbound providers** tab of **Integrations setup**. The provider declares the upstream’s `authorize_url`, `token_url`, supported scopes, and client credentials. See [Configure an OAuth Provider](https://docs.redpanda.com/agentic-data-plane/connect/oauth-providers/).

-   For automatic setup on a **self-managed** server: nothing, if the server supports dynamic client registration. If it doesn’t, you need an OAuth app registered with the upstream vendor, its client ID, and, for a confidential app, a client-secret reference already created in the secret store in `UPPER_SNAKE_CASE` (proto regex `^[A-Z][A-Z0-9_]*$`).

-   The scopes the upstream API needs, if you want to request a specific set rather than whatever the server advertises.

-   For **self-managed** MCP servers: the server URL must be `https://` (proto rule `remote_mcp.user_oauth_requires_https`). HTTP is rejected at create time.

-   For **managed** MCP servers: the type must support user-delegated OAuth. SQL doesn’t; Slack, Jira, and Google managed types do. Check [Managed catalog](https://docs.redpanda.com/agentic-data-plane/connect/managed/managed-catalog/) before configuring.


## [](#configure-the-server)Configure the server

1.  Create your MCP server (see [Create an MCP Server](https://docs.redpanda.com/agentic-data-plane/connect/create-server/)).

2.  Set up the OAuth client for the upstream. What you do depends on the server type:

    -   For a **self-managed** (remote) server, enter the server URL and let Redpanda check what it supports. For a server that authenticates users over OAuth, Redpanda recommends setting up OAuth automatically, which means Redpanda registers an OAuth client and manages each user’s tokens for you.

        If the server supports dynamic client registration, there is nothing else to configure. If it doesn’t, Redpanda walks you through the parts it can’t do for you: register an OAuth app in the upstream’s developer console, add the authorization callback URL that Redpanda displays to that app, then paste the app’s credentials back into the form. The credentials are the `Client ID` from the developer console and, for a confidential app, a client-secret reference from the secret store in `UPPER_SNAKE_CASE`, for example `GITHUB_CLIENT_SECRET`. Leave the reference empty for a public PKCE app.

        Either way, Redpanda records the provider it resolved or created for the server, marked with a **Discovered** badge in the **Outbound providers** list so you can tell it from a provider you registered by hand. See [Discover a provider from an MCP server URL](https://docs.redpanda.com/agentic-data-plane/connect/oauth-providers/#discover-a-provider-from-an-mcp-server-url).

        To attach an OAuth provider your organization already manages instead, click **Use a different authentication method**, set `Method` to `User-delegated OAuth`, then set `Setup` to `Attach existing provider` and select the provider (`UserOAuthAuth.provider_name`). Click **New** to register a provider without leaving the form. The same `Setup` toggle switches back to `Set up automatically`.

    -   For a **managed** server, select the OAuth provider in the type’s configuration (`UserOAuthAuth.provider_name`). Managed types always attach a provider, so automatic setup doesn’t apply.


3.  (Optional) Restrict the scopes Redpanda requests. Expand **Set specific scopes** and list the scopes the upstream API needs (`UserOAuthAuth.required_scopes`). Redpanda enforces them at consent time. Leave it empty to request whatever the server advertises.

4.  (Optional) Override token injection through the API or CLI. By default Redpanda sends `Authorization: Bearer <token>`. To use a different header, set `TokenInjection.header_name`. To omit the prefix entirely (for example, an upstream that expects a bare API key as the token), set `TokenInjection.header_prefix` to the empty string. The create form doesn’t expose these fields.

5.  Save.


> 📝 **NOTE**
>
> Choosing user-delegated OAuth instead of service-account OAuth **is** the credential-mode decision: there’s no separate field. User-delegated gives each caller a per-user upstream identity; service-account gives every caller one shared identity. Switching between them later requires re-consent for every active user.

> 📝 **NOTE**
>
> Editing an existing server works differently. The edit page doesn’t re-check the server URL, so you set `Method` and `Setup` yourself. Leaving the provider empty there keeps the provider the server already has, so switching an existing server to automatic setup is an explicit choice (`UserOAuthAuth.automatic_setup`): automatic setup re-runs discovery and can register a new upstream client. Setting both a provider name and automatic setup is rejected.

> 💡 **TIP**
>
> From the CLI, `--user-oauth-provider` and `--user-oauth-scopes` on `rpk ai mcp-server create` or `rpk ai mcp-server update` attach a provider you already registered; the flags don’t request automatic setup. To script automatic setup, set `automatic_setup: true` under the server’s `user_oauth` block in a GitOps manifest. See [Create an MCP Server](https://docs.redpanda.com/agentic-data-plane/connect/create-server/) and [Manage Resources with GitOps](https://docs.redpanda.com/agentic-data-plane/cli/gitops/).

## [](#the-user-connection-flow)The user connection flow

The first time a user calls a tool that needs this server’s authentication, Redpanda doesn’t have a stored token for them. The behavior is:

1.  The MCP RPC returns `FAILED_PRECONDITION` with an `OAuthConnectionRequired` error detail. The detail carries an `authorize_url`.

2.  Agentic Data Plane surfaces a consent prompt to the user, pointing at the `authorize_url`.

3.  The user completes the device-authorization flow with the upstream provider.

4.  The upstream provider redirects back to Redpanda with a token. Redpanda stores it in the token vault under that user’s identity.

5.  The original tool call retries automatically. Subsequent calls reuse the stored token.


After consent, the user can see and revoke their connection under **My Connections** in Agentic Data Plane.

## [](#manage-your-connections)Manage your connections

The **My Connections** page in the sidebar is each user’s view of their own third-party connections, so a user can authorize the providers their MCP servers need without waiting for a tool call to trigger the consent flow. It shows connections for your own identity only.

The page uses a two-pane layout. The left rail lists providers grouped by status:

-   **Available to connect**: Providers you haven’t authorized yet.

-   **Connected**: Providers with a usable connection.

-   **Needs attention**: Connections that have failed, or whose refresh token is close to expiring, and need to be reconnected.


Select a provider to open its detail pane on the right. The pane shows the granted scopes, a status badge (**Connected**, **Needs attention**, **Action required**, or **Not connected**), and the actions for that provider: **Connect** runs the consent flow and stores a token in the vault under your identity, **Reconnect** re-runs consent for an existing connection (for example, to grant additional scopes or recover after a refresh token expires), and **Disconnect** revokes it. A connection that the gateway can renew automatically from a stored refresh token stays **Connected** with no action from you; it moves to **Needs attention** or **Action required** only when it can no longer renew on its own.

> 📝 **NOTE**
>
> Connections are per-user. Each user authorizes their own accounts, and one user’s connections are not visible to or usable by another.

You can also manage your connections from the terminal: run `rpk ai connection list` to see the services you are signed in to, and `rpk ai connection revoke <provider>` to disconnect one. See [rpk ai connection](https://docs.redpanda.com/agentic-data-plane/reference/rpk/rpk-ai/rpk-ai-connection/).

## [](#scope-upgrades)Scope upgrades

If a user’s stored connection has fewer scopes than the server’s `required_scopes`, the gateway returns a `scope_upgrade_required` error and surfaces a new `authorize_url` requesting the additional scopes. The user re-consents; the connection is updated in place.

## [](#refresh-and-expiry)Refresh and expiry

Redpanda transparently refreshes tokens before they expire, using the refresh token returned at consent time. A connection is only considered expired when its access token has lapsed **and** the gateway can no longer renew it automatically. As long as a usable refresh token is stored, the connection stays active across access-token expiry, and the gateway renews access silently on the next call. This matters for upstreams that issue short-lived access tokens with long-lived refresh tokens: a GitHub App, for example, issues 8-hour access tokens backed by refresh tokens that last around six months, so an idle connection stays active for months rather than showing as expired within hours.

A connection is reported as expired, meaning the user must reconnect, only when the access token has lapsed and no usable refresh token exists: either none was stored, or the refresh token itself has expired. When that happens, the next tool call returns `OAuthTokenExpired` with a `reason`, and the user must re-consent through the same flow as the initial connection.

Each connection reports whether a refresh token backs it, so a client can tell a connection that renews automatically from one that needs reconnecting. The `OAuthConnectionService.ListConnections` and `GetConnection` responses expose this on the `Connection` message through two read-only fields: `refresh_token_present` (a refresh token is stored, so the gateway renews access automatically) and `refresh_token_expires_at` (when the refresh token itself expires, if the upstream reports it, as GitHub Apps do; absent when unknown or non-expiring).

## [](#service-account-oauth-contrast)Service-account OAuth contrast

If you want one shared upstream identity for every caller (instead of per-user identities), choose **Service-account OAuth** on the server instead of **User-delegated OAuth**. With service-account OAuth, every caller of every tool sees the same upstream identity; the upstream system has no idea which Agentic Data Plane user invoked the tool. With user-delegated OAuth, the upstream system sees each end-user as themselves and applies their own permissions.

For the field-by-field service-account-OAuth setup, see [Create an MCP Server](https://docs.redpanda.com/agentic-data-plane/connect/create-server/#configure-authentication).

## [](#worked-examples)Worked examples

-   [Slack](https://docs.redpanda.com/agentic-data-plane/connect/managed/slack/): consumer-facing user-delegated OAuth example. Shows the consent flow against a real Slack workspace.

-   [Jira](https://docs.redpanda.com/agentic-data-plane/connect/managed/jira/): enterprise user-delegated OAuth example. Atlassian’s OAuth flow differs from Slack’s; this page calls out scope-management gotchas.


## [](#troubleshooting)Troubleshooting

| Symptom | What to check |
| --- | --- |
| "OAuth provider not found" | The provider name on the server doesn’t match an OAuth provider in Agentic Data Plane. Check spelling and that the provider exists. |
| "HTTPS required" on save (self-managed only) | User-delegated OAuth requires https:// URLs on the MCP server (proto rule remote_mcp.user_oauth_requires_https). Switch the server’s URL to HTTPS. |
| OAuthConnectionRequired returned even after the user consented | The user’s vault entry might have been revoked or the token expired with no refresh. Have the user re-consent through My Connections. |
| scope_upgrade_required returned | The required scopes on the server changed (or the user originally consented with fewer scopes). The user re-consents with the higher scope. |
| My Connections shows stale entries | Connections persist until manually revoked. Have the user disconnect and reconnect the connection if upstream credentials changed. |

## [](#next-steps)Next steps

-   [Configure an OAuth Provider](https://docs.redpanda.com/agentic-data-plane/connect/oauth-providers/)

-   [Service-account OAuth setup](https://docs.redpanda.com/agentic-data-plane/connect/create-server/#configure-authentication)