Summary
A server-side credential broker so a shared or embedded project can use a service that needs a key, without that key ever reaching the viewer's browser.
Why
There is currently no way to share a map that depends on a credentialed service. The author holds tokens in Settings — Cesium ion, Google Maps, map service tokens, custom request headers for authenticated 3D Tiles, geocoding apiKeys — and those are device-local. So when they share the project, exactly one of two things happens:
- The credential is not in the shared file (correct, and the current behavior), and the layer is simply broken for every recipient. This is a frequent "shared project doesn't work" report.
- Or the author works around it by putting the key somewhere the viewer can read, which publishes a paid credential to anyone who opens the map or views source.
Neither is acceptable, and the second is the one people quietly choose because it is the only one that produces a working map. A published embed on a public site with a live API key in it is a billing incident waiting to happen.
The container already has the right shape for the answer: docker/entrypoint.sh writes an authenticated /ai reverse-proxy location that injects the key server-side and strips the inbound Authorization header, so the browser never sees the credential. That pattern generalizes.
Proposal
1. A brokered-request endpoint
A proxy — in the web container's nginx for self-hosted deployments, and as a Worker for share.geolibre.app-hosted projects — that holds the credential and signs the upstream request. The project references the broker path instead of the upstream URL, so the served .geolibre.json contains no secret.
2. Registration, per credential
The author registers a credential with the broker and gets back an opaque reference. Each registration carries:
- the exact upstream host and path prefix it may be used for (never an open proxy — the same discipline
workers/viewer/src/proxy.ts applies with its allowlist and redirect checks);
- an origin/referrer allowlist for who may invoke it;
- a rate limit and a monthly request cap, so a leaked broker reference is a bounded cost rather than an unbounded one;
- an optional expiry, and revocation.
3. Usage visibility
Per-reference request counts and a cap-reached state that surfaces in the app as a clear message, not a silent blank layer. The author should find out from the app, not from an invoice.
4. Self-hosted parity
Configured through environment variables in the container, matching how the /ai proxy is already set up, so a self-hoster can broker their own keys without depending on share.geolibre.app.
Scope notes
- Must not become an open proxy. Upstream host allowlist, method allowlist, no credential forwarding from the client, and no following redirects off the allowlisted host — the viewer proxy is the model to copy.
- The desktop app can keep calling upstreams directly with the user's own credential; the broker is for shared and embedded contexts.
- Depends on identity for registration ownership; the request path itself is anonymous by design, which is exactly why the per-reference allowlist and cap carry the weight.
- Related: the share-readiness check should recognize a credential-gated layer and point the author here.
Effort
Wishlist.
Part of #1665 (access control umbrella).
Summary
A server-side credential broker so a shared or embedded project can use a service that needs a key, without that key ever reaching the viewer's browser.
Why
There is currently no way to share a map that depends on a credentialed service. The author holds tokens in Settings — Cesium ion, Google Maps, map service tokens, custom request headers for authenticated 3D Tiles, geocoding
apiKeys— and those are device-local. So when they share the project, exactly one of two things happens:Neither is acceptable, and the second is the one people quietly choose because it is the only one that produces a working map. A published embed on a public site with a live API key in it is a billing incident waiting to happen.
The container already has the right shape for the answer:
docker/entrypoint.shwrites an authenticated/aireverse-proxy location that injects the key server-side and strips the inboundAuthorizationheader, so the browser never sees the credential. That pattern generalizes.Proposal
1. A brokered-request endpoint
A proxy — in the web container's nginx for self-hosted deployments, and as a Worker for
share.geolibre.app-hosted projects — that holds the credential and signs the upstream request. The project references the broker path instead of the upstream URL, so the served.geolibre.jsoncontains no secret.2. Registration, per credential
The author registers a credential with the broker and gets back an opaque reference. Each registration carries:
workers/viewer/src/proxy.tsapplies with its allowlist and redirect checks);3. Usage visibility
Per-reference request counts and a cap-reached state that surfaces in the app as a clear message, not a silent blank layer. The author should find out from the app, not from an invoice.
4. Self-hosted parity
Configured through environment variables in the container, matching how the
/aiproxy is already set up, so a self-hoster can broker their own keys without depending onshare.geolibre.app.Scope notes
Effort
Wishlist.
Part of #1665 (access control umbrella).