Skip to main content

Overview

When a target has upstream credentials that expire and need refreshing — OAuth access tokens, session cookies, rotating API keys — Proxy Hopper can offload that lifecycle to a token server: a small HTTP service someone on your team writes and deploys, which Proxy Hopper calls before forwarding requests to authManaged: true targets. Proxy Hopper doesn’t ship a token server itself — it’s application-specific, since only you know how to authenticate against the upstream API. This page covers deploying and operating one; see Building a Token Server for implementing one, and Managed Auth for the underlying concept.
The token server is a separate deployable — its own container image, its own process, scaled independently of Proxy Hopper. Proxy Hopper only needs its URL.

Before deploying: verify credentials are scoped per IP

This is worth checking before you put a token server into production, whether you wrote it or inherited it from another team. Proxy Hopper exists to spread requests across a rotating IP pool so a target can’t easily attribute them all to one caller. It calls the token server separately for every (target, proxy-IP) pair specifically so each IP can carry its own distinct credential — but nothing stops a token server from ignoring the IP it’s given and handing back the same static token for every request regardless. Proxy Hopper will still cache that per IP without complaint; the failure mode is silent. If it happens, the token becomes the one constant tying every proxy IP back to the same caller, which quietly defeats the reason the pool exists. This is only a real problem for auth mechanisms that support per-session or per-login credentials (most OAuth authorization flows, session cookies) — a token server backing a single organisation-wide API key with no session concept is correctly returning one shared credential, because there’s nothing to scope. To check: call POST /token on the token server directly with two different fake ip values for the same target and compare the responses.
If the target’s auth is session/login-based and both calls return the same Authorization (or Cookie) value, that’s a bug in the token server, not expected behavior — see Building a Token Server — scope credentials per IP for what the implementation should be doing instead.

Enabling managed auth

1. Point Proxy Hopper at the token server via server.authServer:
2. Flag the targets that need it:

server.authServer fields

server.authServer is only configurable via the YAML config file — there are no PROXY_HOPPER_AUTH_SERVER_* environment variables or CLI flags for it. See Config Reference for how this fits alongside the rest of server:.
There is one required field per target:

Broken-state and recovery

Token server failures are tracked per proxy IP, not globally — one IP having trouble doesn’t stop the others from working:
  1. A failed POST /token call is retried after retryIntervalSeconds.
  2. After maxRetries consecutive failures for that IP, it’s marked AUTH_BROKEN — subsequent requests through that IP fail fast with 502, without calling the token server again.
  3. After a further retryIntervalSeconds, Proxy Hopper attempts recovery. Success returns the IP to normal rotation; failure restarts the cooldown.
The IP itself is not quarantined — this is independent of the regular quarantine mechanism (see IP Pools). A target can have IPs simultaneously in normal rotation, quarantined for connection failures, and AUTH_BROKEN for auth failures.
If every IP for a target enters AUTH_BROKEN at once, that’s almost always the token server itself being down or misconfigured, not a per-IP problem — check its /health endpoint and logs first.

Observability

Metrics

With server.metrics: true, four auth-specific Prometheus metrics are exposed alongside the standard ones: See Prometheus Metrics for the full reference alongside the rest of Proxy Hopper’s metrics.
proxy_hopper_auth_broken_ips_current is the single most useful alert to wire up for managed auth — a sustained non-zero value means the token server is failing for real traffic, not just a transient blip.

Structured logs

At logFormat: json, these event values appear in log lines related to managed auth:

Startup pre-warming

At startup, Proxy Hopper calls GET /health on the token server and waits for a 2xx before proceeding, then proactively calls POST /token for every (target, proxy-IP) pair across all authManaged targets. This means the first real client request never pays the cost of an on-demand token fetch — by the time Proxy Hopper accepts traffic, every IP already has a cached, valid token. This also means a token server that’s slow to start, or slow per call, directly delays Proxy Hopper’s own startup for large IP pools — size timeoutSeconds and the token server’s own capacity accordingly.

Deploying a token server

How you build the image is entirely up to you — see Building a Token Server for the two supported approaches (the proxy-hopper-token-server library, or a hand-rolled service implementing the same two-endpoint contract). For running it once built:

Helm

Set tokenServer.enabled: true and the chart deploys a Deployment + Service for your image, and derives the in-cluster URL for server.authServer.url automatically.

Docker Compose

Run the token server as its own service alongside Proxy Hopper — see the Docker Compose example in the repo.

Kubernetes manifests

Raw manifests are available in the Kubernetes example for non-Helm deployments.

Standalone

Any container platform works — the token server is a plain HTTP service with no dependency on Proxy Hopper’s process or backend. Point server.authServer.url at wherever it lives.

Scaling and availability

The token server should be able to run multiple replicas behind its own load balancer/Service if you need HA — nothing about the contract assumes a single instance. If your provider tokens require coordination across replicas (e.g. a shared refresh-token store), that coordination is your token server’s responsibility; Proxy Hopper’s own cursor mechanism only guarantees the same cursor is passed back for a given (target, proxy-IP) pair, regardless of which token server replica handled the previous call.
If you run Proxy Hopper itself with multiple replicas and the memory backend, each replica has its own independent token cache — the same (target, IP) pair may be re-acquired separately by each replica. Use the redis backend to share the token cache (and the rest of pool state) across replicas. See High Availability.