@ehd and myself have been playing around with a concept that is sort of like an ipfs-backed-in-browser-code-editor-and-live-coding-environment.* For this to work properly the browser clearly needs access to IPFS. Luckily there is a nice API! Unfortunately, it defaults to disallowing CORS.
I'm aware of API_ORIGIN
and ipfs/kubo#1215, but that approach requires the user to understand a lot of stuff: environment variables, IPFS, CORS, and other 4-letter-initialisms to make it work. This is way too high of a barrier for anybody but the most committed tech-savvy user. It also subtly encourages allowing too broad of access (e.g. allow origin of *
), which is pretty sketchy in my opinion.
I'd like to propose that the IPFS API offer a more holistic approach to this problem, and will even dust off my pre-1.0 golang skills to implement it if people agree...
* I'll leave it up to him to present the proper German compound word 😉
The new "protected" API will:
- Run on a separate port (e.g. 5002)
- Deny viewing/editing configuration
- Only allow connections from
localhost
- Require Bearer Token Authentication
- Set
Access-Control-Allow-Origin
based on the token used. - Implement a new
/request-token
endpoint (described below). - Otherwise defers to the same handlers as the "real" API
- User browses to the URL for MyCoolApp. (possibly served by an IPFS gateway)
- JavaScript checks for an stored auth token (cookie or local storage).
- If none is found, a test request is made to
http://localhost:5002/version
. - If this request fails due to a network error, the user should be presented with the option to choose an alternate API host:port combo.
- Otherwise, we begin the "auth dance". The user is redirected to
http://localhost:5002/request-token?redirect_uri={window.location}&suggested_name=ReallyCoolApp
. - The protected API presents a dialog asking the user to confirm access. This dialog will prominently display the redirect URI (non-editable) and the suggested name for the application (editable).
- If the user authorizes the token request, a new
Token
/TokenDetails
pair is generated and stored in the config. They are then redirected to the redirect URI with the token appended as a query parameter. - If the user rejects the token request, they are redirected back to the redirect URI with no token appended.
- If none is found, a test request is made to
The Token
is just a string, generated with a SRNG. The TokenDetails
is a struct like this:
type TokenDetails struct {
FriendlyName: string,
AllowOrigin: string,
CreatedAt: uint64
}
When a new token is requested, the redirect_uri
must be shown to the user. This is intended to prevent JS injection attacks from stealing tokens by redirecting users to an attackers server. AllowOrigin
will be derived from the redirect_uri
.
These Token
/TokenDetails
pairs would be stored as a map in a new config section: AuthorizedApplications
. Tokens are revoked by removing them from the config.
- This is practically Oauth, it might make sense to just use Oauth and be done with it. Full-blown Oauth would also be desirable if somebody wanted to run a public multi-node IPFS API.
- This could be implemented as a separate service backed by the existing API.