Skip to content
This repository has been archived by the owner on Feb 8, 2023. It is now read-only.

Authenticated HTTP API for using IPFS from browsers #13

Open
grncdr opened this issue May 31, 2015 · 1 comment
Open

Authenticated HTTP API for using IPFS from browsers #13

grncdr opened this issue May 31, 2015 · 1 comment

Comments

@grncdr
Copy link

grncdr commented May 31, 2015

@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.
@jbenet
Copy link
Member

jbenet commented May 31, 2015

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.

Agreed! This is very much needed. We already had plans to eventually make the API use tokens to authenticate, but hadn't spec-ed anything out.


Reading through the above, it overall SGTM. some other notes:

  • we wanted to be able to "install" apps into a node, and enable access to them -- like the webui -- in a granular way (i.e. app developer asks for a list of permissions and user decides whether or not to give them (and possibly uncheck some in a list!).
  • this is hard to do totally distributed, but a user browsing a webapp across different gateways should be able to use the same auth tokens. all the stuff should be done clientside. we could do it by associating a private key with the user and then storing a signed auth record on ipfs (i.e. after the user accepts, the record is added to some keychain (encrypted or not) that the app can query on behalf of the user) -- (actually, maybe this is less of an API thing, and more of a "full js ipfs node in the browser tab" thing)

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.

one problem with Oauth is that --afaik-- it always requires servers at a domain. we should have a serverless auth.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants