I’ve written up an idea for the addition of a token exchange in the remote storage protocol, which would allow a broker app to act as an intermediary and issue downstream clients short-lived tokens without the need of additional oauth handshakes. This would open up a lot more possibility for RS solutions, auth brokers, aggregation platforms, native app hosts, development tools etc.
Questions, comments, critiques welcome!
opened 10:16PM - 23 Mar 26 UTC
The remoteStorage authorization model assumes a direct 1:1 relationship between … a web application and the storage server. Each app authenticates independently via OAuth and receives its own bearer token. This works well for the common case, but there’s a class of clients — auth brokers, aggregation platforms, native app hosts, development tools — that need to authenticate once and then distribute scoped credentials to multiple downstream clients.
Today, an intermediary that manages access on behalf of multiple apps must either:
1. Hold a single *:rw token and enforce scope restrictions itself — no server-side isolation between downstream clients
2. Run a full interactive OAuth flow per downstream client per scope set — redundant authentication, poor UX
Neither option is great. (1) means the server has no visibility into per-client access boundaries. (2) means the user re-authenticates for every new app, even though they already trusted the intermediary.
## Proposed solution
Section 10.1 already introduces an optional token endpoint for PKCE. The same endpoint could accept an additional grant type — urn:ietf:params:oauth:grant-type:token-exchange [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693) — allowing a trusted client to exchange a broad token for a narrower one with:
1. Restricted scope: e.g., *:rw → notes:rw (server-enforced, not just client-side)
2. Different audience: the delegated token is bound to the downstream client’s origin, so the server’s existing audience validation works naturally
The intermediary never exposes its broad token. Each downstream client gets a short-lived, least-privilege token that works with the standard storage API — no protocol changes to Section 4 (Requests) or Section 9 (Bearer tokens).
## Related issues
- #171 (write-only tokens for third-party agents) — touches on giving scoped tokens to external parties
- #183 (client_id / origin matching) — relevant since an intermediary’s origin differs from the downstream client’s
- #174 (redirect_uri for non-web clients) — intermediaries face similar challenges
- #88 (per-app sandboxing) — discusses scoping storage access per origin
## Draft proposal
I’ve drafted a proposal covering discovery (WebFinger), the token exchange request/response format, scope validation rules, audience I’ve written up the full protocol details — discovery via WebFinger, token exchange request/response format, scope validation rules, audience binding, security considerations:
https://gist.github.com/silverbucket/4b193993cf56b36811cfedbdd8b5f985
Looking for feedback on whether this is a direction the spec wants to go, and whether building on the PKCE token endpoint is the right foundation.