Skip to main content

On-Prem OAuth (Run-Hosted Connect)

By default the OAuth "connect" flow — where a user authorizes an integration and Willow stores the resulting tokens — runs on the Willow SaaS connect service. Run-hosted connect moves that flow onto your own run gateway instead, so the authorization-code exchange and token encryption happen entirely inside your infrastructure. The plaintext OAuth credentials never reach the Willow control plane.

You enable it per integration with a single toggle, and it only takes effect when that integration's run gateway is external (hybrid / on-prem).

When you need it

Use run-hosted connect when both are true:

  • You run a hybrid or on-prem deployment, i.e. the integration's effective run gateway is an external gateway you host (see Gateway Settings).
  • You must keep OAuth tokens and their encryption inside your boundary — for data-residency, network-isolation, or customer-managed-key (KMS) requirements — rather than having the SaaS connect service perform the code exchange.

If your run gateway is a Willow-hosted domain (mcp-s.com, withwillow.ai, or a custom domain still served by Willow), leave this off — the standard SaaS connect flow applies and there is nothing to gain here.

How it differs from the default

SaaS connect (default)Run-hosted connect
Renders the consent/redirect pagesWillow SaaS connectYour run gateway
Authorization-code → token exchangeWillow SaaS connectYour run gateway
Token encryptionSystem KMSYour gateway's key (static key or your AWS KMS)
Plaintext credentials reach the control planeYes (briefly, in memory)No
Where tokens are storeddb-service (encrypted)db-service (encrypted, already customer-owned ciphertext)

Prerequisites

  • A hybrid or on-prem deployment with an external run gateway configured for the organization. See Hybrid Deployment and Gateway Settings.
  • The integration uses an OAuth-family auth type (OAuth, Instant/Willow OAuth, or Proxy OAuth). See Configure MCP Server Authentication.
  • The run gateway can encrypt locally — either a static ENCRYPTION_KEY, or AWS KMS (KMS=true plus AWS_REGION / AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY and KMS_KEY_ID). See Environment configuration.
  • The customer's OAuth application allows the run gateway's callback URL: https://<your-run-host>/connect-auth/callback.

Enable it on an integration

The toggle lives on the MCP server's Settings tab and only appears when the integration's effective run gateway is external.

  1. Go to Build > MCP Servers and open the server.
  2. Select the Settings tab and expand Connect.
  3. Turn on Handle OAuth on the run gateway.

From then on, when a user connects that integration, Willow hands the OAuth flow to your run gateway's /connect-auth/init endpoint instead of the SaaS connect flow. See the Settings reference → Connect.

How it works

┌──────────────┐ 1. GET /auth/auth-url ┌───────────────────────────┐
│ SaaS connect │ ─────────────────────────────▶│ integration.connect_via_run│
│ (auth-url) │ │ + external run gateway? │
└──────┬───────┘ └────────────┬──────────────┘
│ yes: redirect browser to your gateway │ no: SaaS OAuth
▼ ▼
┌───────────────────────────────────────────────┐ (standard connect flow)
│ Your run gateway │
│ /connect-auth/init ── redirect ──▶ provider │
│ provider ── code ──▶ /connect-auth/callback │
│ exchange code → tokens (inside your network) │
│ encrypt tokens with your key (static / KMS) │
└───────────────┬────────────────────────────────┘
│ store already-encrypted credentials

db-service (ciphertext only; never sees plaintext)
  1. mcp-s-connect's auth-url route sees the integration has connect_via_run enabled and an external run gateway, so it redirects the browser to your gateway's /connect-auth/init (passing a signed state).
  2. Your run gateway builds the provider authorize URL with redirect_uri = https://<your-run-host>/connect-auth/callback. The redirect base is derived from the incoming request (X-Forwarded-Proto / X-Forwarded-Host, falling back to Host), so it matches the public URL the user is on.
  3. The provider redirects back to your gateway's callback, which exchanges the code for tokens inside your network, encrypts them with your gateway's key, and stores the ciphertext through db-service. The SaaS control plane only ever sees encrypted data.

Environment configuration

Set these on the run gateway (see .env.example):

VariableRequiredPurpose
ENCRYPTION_KEYOne of key pathsStatic key for local encryption (no AWS needed).
KMSFor AWS KMSSet true to use AWS KMS instead of a static key.
KMS_KEY_IDFor AWS KMSCMK id/ARN used to generate the data key. Required for this flow when using AWS KMS — unlike decryption, GenerateDataKey needs the key id.
AWS_REGION / AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEYFor AWS KMSAWS credentials for the KMS calls.
AUTH_SECRETYesVerifies the signed connect state; must match the value mcp-s-connect signs with.
DB_AUTH_SECRETOptionalFallback secret for verifying the signed state when it differs from AUTH_SECRET.

Security notes

  • Plaintext OAuth credentials never leave your infrastructure; db-service receives only ciphertext already encrypted with your gateway's key.
  • The callback redirect_uri must be registered on the provider's OAuth app, and your ingress must set X-Forwarded-Proto / X-Forwarded-Host correctly (otherwise the gateway falls back to the raw Host header, which must still be the public host).
  • Credentials encrypted this way are stamped for your external gateway, so decryption is always resolved locally and never routed to the system KMS.