Smuggling the Archive Through the Backend
One day the archive just broke. The historical-imagery tool (UCSD's Seeker, at
tools.alertcalifornia.org) had been living in a simple iframe — until UCSD, fighting off a
scraping attack, blocked outside IPs. Every operator's browser was an outside IP. The iframe
went dark overnight.
The fix is a classic pattern worth learning beyond this feature: a reverse proxy. If users' browsers can't reach the archive, let the server reach it on their behalf — one whitelisted IP, one set of system credentials, and an iframe that never leaves home.
How a blocked site appears inside the app
The iframe now points at our own backend — /api/archive/seeker?id=…×tamp=… — and
pages/api/archive/[...path].ts does the smuggling:
Four moves make it work, and each solves a specific problem:
1. The user still has to be our user. The proxy checks the next-auth JWT before touching anything — unauthenticated requests get a 401. UCSD sees one system identity; access control stays on our side.
2. One login, shared by everyone. The proxy signs into the archive with system credentials and caches the session cookie in memory for 55 minutes (just under its 1-hour expiry). If the archive ever answers 401/403 anyway — an expired session — the proxy clears the cache, re-authenticates, and retries once, invisibly.
3. URL rewriting closes the loop. Here's the subtle part: the archive's HTML is full of
absolute URLs back to tools.alertcalifornia.org — scripts, styles, images. Served as-is,
every one of those would escape the proxy and hit the blocked host. So HTML responses (and
redirect Location headers) get their absolute URLs rewritten to /api/archive/..., pulling
every subsequent request back through the tunnel. Non-HTML passes through untouched.
4. Same origin, fewer problems. Since the iframe now loads from our own origin, the old
sandbox attribute and its cross-origin contortions were simply deleted.
Configuration
Four env vars: ARCHIVE_BASE_URL, ARCHIVE_LOGIN_URL, ARCHIVE_USERNAME,
ARCHIVE_PASSWORD. The credentials come from UCSD and are server-side only — in production
they belong in Key Vault, never in source control. The route is also listed in proxy.ts's
protected matcher, so the auth middleware guards it like any other API
path.
Wrapping up
When the archive's front door closed, the app grew a tunnel: authenticate our user, borrow one system session, rewrite every URL so nothing escapes, and serve it all same-origin. If you ever need to embed another IP-restricted tool, this file is your template.
Back to the auth deep dive — the machinery that guards this tunnel.