namebasehq / api-documentation

Public documentation for the Namebase exchange and marketplace API.
https://namebase.io
67 stars 12 forks source link

JS-API ‘Access-Control-Allow-Origin’ missing #11

Open gagdiez opened 4 years ago

gagdiez commented 4 years ago

Hello, I am working on my application for the ongoing hackaton, and I run into a problem while using the namebase API.

My project is a web hosted in skynet, that uploads files and registers the link into a handshake-URL using the namebase API.

The problem is that, whenever I call the API using fetch (a js function) from my web, I get the error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://namebase.io/api/v0/dns/domains/bunnu/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Any solution for this?

Best! Guillermo.

troq commented 4 years ago

Thanks for reporting this @gagdiez. I'm not sure if we'll be able to update this in time for the hackathon. In the meantime you may want to use a cors proxy like cors-anywhere https://cors-anywhere.herokuapp.com/

gagdiez commented 4 years ago

cors-anywhere is not working, it keeps responding with an "internal server error".

I have now created a small service to easily update sialinks in namebase: https://skynet-namespace.glitch.me/. The server takes the _access_key, secretkey, sialink, and domain through a PUT request. It automatically creates the authorization token needed, the api-url, and the records, and contacts the namebase API to update the TXT registers.

The code is freely available in: https://glitch.com/edit/#!/skynet-namespace

To see an example on how to use please visit the web: https://skynet-namespace.glitch.me/

I have submitted to the hackaton, but I share it now because someone could find it useful for their projects.

Best, Guillermo

troq commented 4 years ago

Thanks @gagdiez and great job on your submission! Am I understanding correctly that you no longer need CORS support?

gagdiez commented 4 years ago

My server has CORS support, and its configured so anyone can interact with it.

This is in contrast with the current namebase API, which is missing a field in the header ( ‘Access-Control-Allow-Origin’) when responding to PUT requests. Since that field is not present, and for security reasons, ALL browsers block the interaction between the local JS code (the one executed in the browser when visiting a website) and the namespace.io/api.

This error (not being able to communicate with the API) doesn't happen with your NodeJs API, because NodeJs servers do not check for those CORS-fields in the header.

Now... why cors-anywhere didn't work? I honestly don't know, we need to further investigate this. I tried again this morning and I keep getting the same error. But that, after the hackathon.

troq commented 4 years ago

I'm not sure if it makes sense from a security perspective to let the API be called from browsers since the API key can be used to place trades on Namebase Pro as well. With that said we could whitelist CORS support for DNS management only. @turbomaze what do you think

turbomaze commented 4 years ago

This is a cool project and I'm glad you're making it!

Unfortunately, allowing cross-origin requests is not acceptable for security reasons. We explicitly do not want to allow other websites to make any API calls to Namebase on behalf of our users. The only endpoints that can safely permit cross-origin requests are those that 1) do not modify any state (GETs only), and 2) do not require any authentication. The exchange market data, marketplace, and auction status APIs fit this description, but the DNS API does not.

My recommendation is to simply have a button that "copies" the DNS record you want to set and links to the Namebase domain manager page. The user can copy paste the record and click "save" without too much hassle. It seems that the purpose of permitting cross-origin requests would be to save this automatically for the user, which would certainly be easier, but not essential.

Long term solution that requires integration on our end (which isn't out of the question, depending on how much users want this feature!): we can add a query parameter like /domain-manager/:domain?recordData=base64, which, when set, will autopopulate additional DNS records, so the user just needs to hit "save".

gagdiez commented 4 years ago

Thanks for taking the time to reply.

1) Let me see if I understand your concern. In the general case, you want to avoid calls from websites because the user will have to give its private-keys. In this case, if the website is malign, it could use the keys to trade, change the domain, etc. Right? This, I completely understand.

2) In my particular case, I am both the user, and the website (a blog). When I create a new entry in my blog, the whole HTML gets copied, and uploaded to skynet as a new website. As a return, I get a new sialink. Since I don't want to manually update the domain each time, I will add a form, so I can input my private-keys in my blog, and it will automatically handles the domain-update (through my server https://skynet-namespace.glitch.me/). This is because I trust my web (I did it), and my server (I coded it).

I understand why you don't want to enable cross-origin requests (see 1) in your server, indeed I think is a good thing for the final user.

For those developing their own skynet-apps that run into my problem, I still think that https://glitch.com/edit/#!/skynet-namespace can serve as a simple example on how to make your own server, to truly integrate namebase into skynet-app. Of course, being careful of never exposing your private-keys (do not put them on a public server on glitch.com, nor as plain text on your website).

Thanks for your time!

P.S. In the long run maybe you could do as the exchange Kraken? And have specific rights (trade, update-domains, withdraw) associated to each api-key? In this way, if a user is not interested in trading (I am not), but it's in updating domains (I am), the whole system is more secure. But that is maybe another issue for the future.

Best!

troq commented 4 years ago

@gagdiez that's not likely to be done in the near-term but we definitely intend on giving more control over api key permissions in the future!

turbomaze commented 4 years ago

Since I don't want to manually update the domain each time, I will add a form, so I can input my private-keys in my blog, and it will automatically handles the domain-update (through my server https://skynet-namespace.glitch.me/). This is because I trust my web (I did it), and my server (I coded it).

Yes, this is a good idea and makes a lot of sense since you're the one operating the server. It is essentially your user agent acting on your behalf. People that want the convenience can do something like this, and people that don't can just set the records themselves

P.S. In the long run maybe you could do as the exchange Kraken? And have specific rights (trade, update-domains, withdraw) associated to each api-key? In this way, if a user is not interested in trading (I am not), but it's in updating domains (I am), the whole system is more secure. But that is maybe another issue for the future.

Yup 100% agree!