"upstream": {
"headers": { "Authorization": "Basic ${SERVICE_BASIC_AUTH}" }
}Call services with the user's credentials
Useful if you want to…
let a route or an MCP tool call an external API as the user, not as a shared service account;
keep the provider’s client secret out of Gate One;
let every user reach the upstream with their own rights;
give users a page where they connect, pause and erase those services.
The two credential shapes
When a route calls an external API, the credential can be:
static — one shared value for every caller, set with
upstream.headers(for example a service token);delegated — the signed-in user’s own token, obtained after they authorize the service once.
Gate One implements the delegated shape with the token broker.
upstream.tokenBroker on a route tells Gate One to fetch the caller’s
token from the broker and inject it into the upstream request. It applies
to plain proxied API routes and to the REST/MCP tools a route exposes —
see MCP tools.
Important | If the upstream needs the same credential for every caller, do not
delegate. Set it once with upstream.headers, for example: |
Delegation is only for credentials that belong to the individual user. A shared service account, a static bearer token or a Cloudflare Access service token is simpler and has no connection page to manage.
What delegation is not
Delegation is not an identity provider and not SSO:
the IAM/IdP still decides who the user is (
auth,auth.identity);the token broker only stores a token the user granted for one upstream service.
The names are easy to confuse, so see
IAM, IdPs and provider types for the
cladone-auth IAM (an OIDC issuer/IAM), the http-bridge
provider type and the token broker side by side.
The token broker and the connections page
The token broker is a small, internal-only service: a registry of OAuth
providers plus an encrypted per-user token store. It is never exposed
directly; only its browser routes are published through the login host,
served by Gate One (tokenBroker.browserHost, provider-agnostic).
auth-bridge no longer holds the broker secret and cannot proxy them: only
Gate One (and the broker) has TOKEN_BROKER_SHARED_SECRET.
Users authorize a service on the connections page ("Service connections"). Gate One links to it from the user badge as Services, and shows that link only when an exposed route declares delegation.
For the user
The link is always present when the token broker is configured, even if no route currently delegates: it is also where the user erases stored credentials.
Open Services from the user badge (or follow the
connect_urla delegated call returned).Next to the service (for example GitHub), choose Connect and authorize it at the provider.
The broker stores the token; the next call to a delegated route uses it.
Disconnect pauses the delegation. It does not delete the credential and does not contact the provider; Connect resumes the same credential.
Erase deletes the stored credential locally (and its metadata). The provider is not contacted: the same credential can still be used elsewhere. Erase all my data does this for every service.
If the token can no longer be refreshed, the connection is marked
reauthorization required and Gate One sends the user back to this
page (409 reauthorization_required for an API call, a redirect for a
browser route). A paused delegation answers 403 delegation_disabled
with the Services URL.
Stored rows whose provider was disabled or removed from the registry are still listed, with Erase only: the user can always delete their own data.
Add a delegation service
A provider is a registry entry, not code: the token broker’s
providers.json lists each OAuth 2.0 service (endpoints, client id,
scopes, …). Adding GitHub, Google, Slack or an internal OAuth service is
a registry entry; its client secret comes from the broker’s environment,
never from the file.
Gate One only references the provider name
(upstream.tokenBroker.provider). See
the token broker for
the fields and an example.
Declare delegation on a route
{
"tokenBroker": {
"url": "http://token-broker:4000",
"secretEnv": "TOKEN_BROKER_SHARED_SECRET",
"browserHost": "login.example.com",
"links": {
"services": {
"label": "Services",
"url": "https://login.example.com/connections"
}
}
},
"routes": [
{
"host": "api.example.com",
"path": "/github/*",
"stripPrefix": "/github",
"backend": "https://api.github.com",
"auth": {},
"upstream": {
"host": true,
"tokenBroker": { "provider": "github" }
}
}
]
}authis required: the broker needs an authenticated user id.provideris a broker provider name (github), validated against the broker at startup.the token is sent as
Authorization: Bearer …by default; setheaderandprefixto change the header or the prefix.browserHostis where Gate One serves the connections page and the OAuth callback (/connections,/connect/,/oauth//callback), authenticating the user with the configured provider and injecting the identity. Empty = derived fromlinks.services.url. The browser routes must not be proxied directly to the broker, and auth-bridge does not receive the broker secret.the shared secret is read from the environment named by
secretEnvand is never written in the file.the operator can list connections (metadata only), pause/resume a delegation and delete credentials through a separate admin API (
TOKEN_BROKER_ADMIN_SECRET, never held by Gate One). The operator cannot add or replace a credential.retention is unlimited by default (
TOKEN_BROKER_RETENTION_DAYS=0); when enabled, it only purges paused connections.
Note | The tokenBroker block and the route are shown together because a route
that declares upstream.tokenBroker requires the top-level
tokenBroker block; without it the configuration is refused at load.
This is a partial extract (the providers and other routes are omitted) —
the complete file is
examples/mcp-tools/routes.json. |
When the user has not connected the service
Gate One never sends a request without credentials:
an API/JSON call gets 401/409 with a
connect_urlthe client can open;a browser (frontend) route redirects to the connections page.
Important |
|
Complete example
MCP tools shows the token broker with a delegated API route and delegated MCP tools.
Configuration reference
routes[.upstream.tokenBroker]Token broker (endpoints, provider registry, installation)