Skip to content

Instantly share code, notes, and snippets.

@grncdr
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grncdr/273cbc89b4e9cb21519b to your computer and use it in GitHub Desktop.
Save grncdr/273cbc89b4e9cb21519b to your computer and use it in GitHub Desktop.
Ideas about using IPFS from browsers

@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 😉

Proposal: "Protected" API

Highlights

The new "protected" API will:

  1. Run on a separate port (e.g. 5002)
  2. Deny viewing/editing configuration
  3. Only allow connections from localhost
  4. Require Bearer Token Authentication
  5. Set Access-Control-Allow-Origin based on the token used.
  6. Implement a new /request-token endpoint (described below).
  7. Otherwise defers to the same handlers as the "real" API

User flow for IPFS-backed web apps

  1. User browses to the URL for MyCoolApp. (possibly served by an IPFS gateway)
  2. JavaScript checks for an stored auth token (cookie or local storage).
    1. If none is found, a test request is made to http://localhost:5002/version.
    2. 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.
    3. Otherwise, we begin the "auth dance". The user is redirected to http://localhost:5002/request-token?redirect_uri={window.location}&suggested_name=ReallyCoolApp.
    4. 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).
    5. 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.
    6. If the user rejects the token request, they are redirected back to the redirect URI with no token appended.

Token / TokenDetails pairs

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.

Thoughts & Observations

  1. 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.
  2. This could be implemented as a separate service backed by the existing API.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment