Skip to main content

Upstream Authentication

Two separate questions get conflated in MCP setups. How does the client authenticate to the gateway? (Your Waxell OAuth session or an API key — covered in the Quickstart.) How does the gateway authenticate to each upstream? That's this page, and it's per-upstream — the auth_mode on the upstream row.

MCP OAuth (mcp_oauth_dcr) — the zero-credential default

Most modern vendor MCP servers (Notion, Linear, Calendly, Stripe, Monday, 100+ in the catalog) implement the MCP authorization spec. For these, nobody ever touches a vendor developer console:

  1. Discovery — the gateway asks the server itself how to authenticate: the server's 401 response points at its protected-resource metadata (RFC 9728), which names its authorization server, whose metadata (RFC 8414) provides the authorize, token, and registration endpoints.
  2. Dynamic client registration — the gateway registers itself as an OAuth client programmatically (RFC 7591), preferring a public client secured by PKCE. Happens once per tenant, on the first connect.
  3. Per-user authorization — each user does a standard consent dance (authorization code + PKCE, with the token bound to the specific MCP server via RFC 8707 resource).
  4. Silent refresh — tokens refresh automatically for the life of the grant, including providers that rotate refresh tokens.

Discovery results and the registered client are cached on your tenant's upstream row; everyone after the first user goes straight to the consent screen. This is what the Auto OAuth badge means in the catalog, and it works for any spec-compliant server you add as a custom upstream.

A few servers speak MCP OAuth but don't offer dynamic registration (DocuSign, PagerDuty, Smartsheet, the Google Cloud services). Same mode, one extra step: an admin registers an OAuth app with the vendor once and stores the client credentials on the upstream — the discovery and per-user flows are unchanged.

Open (no_auth)

Some servers are simply public — Microsoft Learn, PubMed, AWS Marketplace, Open Targets. The gateway sends no Authorization header at all to these (forwarding a stray token to a third party would leak it). Why route an open server through the gateway? Because the caller still authenticates to Waxell, and policy, rate limits, and audit still apply. Open upstream ≠ ungoverned upstream.

Classic per-user OAuth (oauth_per_user)

The traditional flow for providers without MCP-spec auth: an admin registers an OAuth app with the vendor (or uses Waxell's platform-registered app where available), pastes the client ID and secret on the catalog entry or upstream row, and users connect individually. Per-provider protocol quirks (token endpoint auth style, body encoding, scope separators, PKCE) are handled by a built-in dialect engine that discovers, learns, and remembers each provider's dialect.

The rest of the modes

ModeWhat it doesUse when
tenant_api_keyOne tenant-wide key, resolved from the Waxell secret store at call time — the key itself never sits on the gatewayVendor offers API keys, per-user identity not needed
shared_service_account / byo_token_envA token the gateway holds (secret store or environment variable)Internal servers, legacy setups
forward_caller_tokenPasses the caller's own Waxell bearer throughUpstream shares Waxell's auth (e.g. Waxell's own MCPs)

Credential precedence

When multiple credentials could apply, the gateway resolves: tenant's own (BYO) credentials → Waxell platform credentials → environment fallback. Per-user grants are always stored encrypted at rest and scoped to (user, upstream) — revocable individually from the Connections page.