Skip to main content

What is managed auth?

Managed auth lets Proxy Hopper automatically attach a fresh, valid Authorization header (or Cookie, or any other auth header) to every request forwarded to a target — without your application code fetching or refreshing that token itself. You implement a small HTTP service, a token server, that knows how to acquire and refresh whatever credential the upstream API requires. Proxy Hopper calls it before forwarding a request, caches the result, and refreshes it before it expires — all outside your application’s request path.
Managed auth is unrelated to Authentication (who’s allowed to send traffic to Proxy Hopper) and to Client Identities (the browser persona Proxy Hopper presents to a target). Managed auth is specifically about credentials the upstream API requires — OAuth access tokens, session cookies, rotating API keys — that Proxy Hopper acquires on your behalf via your token server.

Why each proxy IP needs its own token

This is the actual reason managed auth exists, not just a convenience feature — read this before the rest of the page. Proxy Hopper’s whole purpose is to spread requests across a rotating pool of IPs so a target site can’t easily tell they all come from the same caller — to stay under per-IP rate limits, or to avoid one address getting flagged for excessive use. Your application doesn’t choose which pool IP handles a given request; Proxy Hopper does. If every request carried the same Authorization header no matter which IP sent it, that token would be the one constant thread running through an otherwise-rotating pool — trivially letting the target correlate every IP back to the same caller regardless of how many different addresses were used. That silently defeats the entire reason Proxy Hopper exists. Managed auth prevents this structurally: Proxy Hopper acquires and caches a separate token per (target, proxy-IP) pair, never one shared token reused across the whole pool. Combined with client identities (a consistent browser fingerprint and cookie jar, also scoped per IP) and, where the target’s login flow allows it, IP-pinned acquisition (logging in from the same IP that will later use the resulting token), each proxy IP can present as a fully independent, self-consistent caller — fingerprint, cookies, login, and auth token all bound together, none of it shared with any other IP in the pool.
This only holds if your token server actually issues a distinct, IP-scoped credential. Proxy Hopper caches whatever get_token() returns under a per-IP key regardless — but a TokenProvider that ignores req.ip and returns the same static token for every IP quietly reintroduces the exact correlation the pool was rotating IPs to avoid. This is the single most important thing to get right when implementing one — see Building a Token Server — scope credentials per IP.

Other reasons to centralise this in a token server

Even setting the correlation problem aside, offloading token lifecycle to a dedicated service beats fetching it in your application directly:
  • Refresh happens off the request path. Proxy Hopper refreshes proactively, before expiry — your application never blocks on a token fetch or retries because of a 401.
  • Credentials never leave the token server. Client applications never see the upstream credentials, only Proxy Hopper does, and only in memory (or Redis, if configured) as the resolved header value.
  • No duplicated fetch/refresh logic. Every service routing through Proxy Hopper for a target reuses whichever IP’s token is already cached and fresh, instead of each one independently implementing the same OAuth/session dance.

How caching works

Tokens are cached per (target, proxy-IP) pair — never globally and never per-target-only. Each IP in the pool carries and refreshes its own credential independently of every other IP. A cached token is reused until it nears expires_at, at which point Proxy Hopper proactively calls the token server again — before the current token actually expires, so in-flight requests never hit a 401 from a token that ran out mid-request.

The cursor mechanism

Your token server is stateless from Proxy Hopper’s perspective, but many real auth flows aren’t — a refresh token, a session ID, a call counter. The cursor is an opaque JSON object Proxy Hopper stores per (target, proxy-IP) pair and echoes back on every subsequent token request for that pair, so your token server can carry state between calls without running its own database.

Broken-state and recovery

If the token server fails (errors, times out, or is unreachable), Proxy Hopper tracks failures per IP rather than failing every request immediately:
  1. Each failure is retried after a cooldown, up to a configured limit.
  2. Once that limit is reached, the IP enters an AUTH_BROKEN state — requests for that IP fail fast with 502 without calling the token server again.
  3. After a further cooldown, Proxy Hopper retries; success returns the IP to normal rotation.
Only the auth layer for that IP is affected — the IP itself is not quarantined, and the pool keeps routing requests through other IPs normally. See Token Server (Admin) — Broken-state and recovery for the exact thresholds and how to monitor this state.

Enabling it

Managed auth is opt-in per target. Point server.authServer at your token server, then flag the targets that need it:
See Config Reference for the full field list, Token Server (Admin) for deployment and operations, and Building a Token Server for implementing one.

When to use managed auth

Use managed auth when the target requires:
  • An OAuth access token that expires and needs periodic refresh
  • A session cookie obtained by logging in, that multiple requests should reuse
  • Any credential your application shouldn’t need to know how to fetch itself
For targets that need no per-request auth beyond what’s baked into proxyProviders (e.g. proxy-level Basic auth to your IP supplier), or that use a static, never-expiring API key, managed auth adds a moving part you don’t need — set that key as a normal header on your client requests instead.