I'm calling a webservice using the REST methodology using JSON/JS/jquery and am wondering if there is a way to call the webservice without exposing my API keys in the source code. Anyone know of a way to hide the API keys from the public and still make the call?
I'm worried that if someone goes through my source, they will be able to use my API key.
You could delegate the calls to your own server, so instead of:
Browser sends HTTP request to external REST API, with API key
External REST API sends response to browser
you have
Browser sends HTTP request to your server
Your server sends HTTP request to external REST API, with API key
External REST API sends response to your server
Your sever sends response to browser
I'm not sure that someone else "stealing" your API key is a huge problem, though, since API keys (Google, for example) are frequently associated with specific domains.
There's no way to send the API keys to the client, and have them be usable, and not have them be exposed. What you more likely want is to have a translation layer, where you allow external (non-validated) clients to make requests against an exposed endpoint, then you use some sort of logic to validate the request, then pass through the request.
API keys are typically for your use as a partner, not for distribution; this is the way to avoid distributing them.
Related
There's lots of general info about preventing API key leaks, but I'm having trouble finding proper procedure specifically for making an HTTP GET request with an API key as a parameter. Any user can easily inspect the request and grab an app's private API key as far as I can tell.
Is there any way to safely make GET requests? I'd use something other than GET if it was made available by the third party API. Might just be bad design.
Example from an app I'm working on. When I make a GET request to a third party API, my API key can easily be seen in the inspector:
Code:
const response = await fetch('https://www.someexampleimadeup.com?var=something&key=LOOKITSMYPRIVATEKEY'
Inspector:
You are right.
If you pass a private API key with your GET request initiated by client-side javascript, you are exposing the key. And no, there's no way around it if you want to do this client-side (if you are fetching the API from a javascript file that runs on the browser).
That's because by definition HTTP requests messages are composed of textual information encoded in ASCII (as properly explained in this MDN article). All HTTP requests of any protocol are always available to the user of the browser who initiated the request, even if you use HTTPS.
It's important to address that the simple fact of your private API key being present on client-side javascript code makes it insecure - public.
If running server-side javascript is an option for you, something like a Node.js backend server, you can fetch your server fetch("https://yourserver.com/resource"), and then your server can fetch the API with the private key fetch('https://api.com/?api_key=XXXXX'). Now your backend server is the middle man (or the black box) responsible for getting the API data without exposing the private key.
You won't be exposing the key because the user only knows about the GET request to your server and the data you choose to return. As well, as you have control over your server, you can choose not to expose your private API key by not serving the file in which it is written.
In Node.js webservers, you usually store your API key in a ".env" file PRIVATE_API_KEY=XXXXXXX, which is not served. This file is then added to the rules present in .gitignore, to prevent it from being pushed to any public repository. With the help of a node package like dotenv, you can access it on your code as a property of the process.env object process.env.PRIVATE_API_KEY (some examples in their npm page).
In this case, the key will not be leaked over the network because the request uses TLS (https://). This is because the querystring is entirely in the HTTP request, whose data is entirely sent across a secure connection.
However, it is never safe to use private API keys in a web client—with any kind of request, GET or otherwise. The frontend is rendered and run entirely on the machines of your users, so any information you put in that HTML or JavaScript can be seen. If the API you use only provides private API keys, then any requests you make must be done on your own server.
On the other hand, some API keys are meant to be used on the client. For example, consider the Google Maps API. In this, the only risk associated with having a visible API key is the fact that other users could use that key for their own websites and incur charges. Google mitigates this by allowing developers to specify allowed origins: that is, it limits what domains can use the key.
I recently learned about webhooks and am trying to implement one for a full-stack app that I'm building. However, I haven't been able to find information on how to create my own webhook. This is how my app is expected to work:
My client side is a website built with React, and when it loads, it will make a GET request to my server (built with Node and Express). The response will provide data that will be displayed on the website. The user will click a button on the website, which will send a (POST? GET?) request to my server, which will make its own POST request to send some of the data to an external API. When that external API data completes work on the data, it will send a POST request to my webhook URL (which I assume is part of my server), and the data from the external API needs to be sent to the client, which will display it alongside the original data. Additionally, when work on the first batch of data is completed, my server sends another POST request (with some more of the original data) to the external API, which will then make a POST request to my webhook/server with new data that then gets passed to the client again, and this repeats until all the original data from my server has been passed to and processed by the external API, and the all the processed data gets sent to my server and then to the client.
From my understanding, the webhook will allow my client to make a single request to my server, and then, my server can make multiple response to my client: one response for each POST request received from the external API. However, I have not been able to find information on how to create a webhook. Everything that I have found has been about how to use webhooks with pre-existing apps/websites like Dischord or GitHub or Stripe. Or using 3rd-party services to use their webhooks to connect pre-existing app/websites.
How do I go about making a webhook for my little project that will update my website every time that my server receives a POST request from the external API? Or am I misunderstanding how a webhook works? Can they only be created by 3rd-party services and/or only used on pre-existing apps?
For a simple use case, it just means another endpoint on your server that will receive a request from the external API when it's done with the task. It's a common way REST APIs work to let you know they are done with something, or communicate anything back to you in general. You have one endpoint that will receive a request from the React client, and send information off to the external API (as you said), and another endpoint (this "webhook") that will receive requests from the external API. That's it.
You described the client-server communications for this problem just fine with the exception that the server cannot send requests to the client over HTTP. If the client needs anything from the server, it needs to send a request and ask for it. A common way to do for this would be to store the information on the server once the external API hits your "webhook", and the client can ask the server if the data is back every X seconds (long-polling).
Example (payment flow):
Client -> Server: Heres my credit card number
Server -> Client: Thanks! Let me process that.
Server -> External API: Please process this credit card for the amount of $X and ping me at this webhook when you're done.
External API -> Server: OK, will let you know when I'm done.
Client -> Server: You done yet?
Server -> Client: Nope!
External API -> Server (to webhook): Hey, I'm done, here's the receipt.
Server -> External API: Thanks!
Client -> Server: You done yet?
Server -> Client: Yes! Here's your receipt.
More advanced ways to solve the problem would be using a long-lived bidirectional communication protocol such as websockets. And as others have mentioned, all of the endpoints don't have to be on the same server. You can have one server for each endpoint, and you can have turn them on only when they get a request and then go back to sleep (that's a Lambda). Pros and cons to this approach. That's more advanced stuff and if you're just learning I wouldn't really worry about it now.
AFAIK, webhooks are just normal web APIs. Properties that make an API a webhook:
The client sending requests to your server, in this case, is another server
This client will send you a request when there's a triggered event
In your case, your server POSTing data to the external API. What makes webhook different is that the external API's server doesn't have to respond right away, instead, it sends back you, for example, an HTTP 200 OK to acknowledge that it received the request and has started to process the data. When the external API's server finishes processing the data (which is an event), it will call your server's endpoint to inform you about the process along with the processed data (if succeeded).
Your server, correspondingly, will then have to inform your client (the user) about the processed data. I would suggest implementing some kinds of persistent connection (WebSocket or SSE), or simply just make the client poll request every some second.
"(which I assume is part of my server)"-- The webhook is part of the third party API that points back to either your server or maybe some serverless function/lambda(that you set up) that in turn can parse and perform computations on the data and then send it back to your server.
It really depends on the use case and architecture of your API. If you don't want your main API server to get overloaded, if say you need to perform heavy I/O, CPU/GPU processing, you could create Serverless Lambda Functions to handle this data processing and be the endpoint you supply to the third party's webhook post endpoint.
If you're not concerned with it, you could just create another endpoint in your server to handle this webhook.
Just keep in mind, when you're trying to scale up, you want your systems to be as distributed as possible-- within reason-- so your API can handle more requests and not be overloaded with a bunch of processes.
I'm building a vue js web app and I would like to make respective calls to the to my prismic repo, but I don't know how to do it without exposing my access token. I am using the rest api approach shown here.
Any ideas?
The http request syntax is as follows. I want to do this inside my vue components while not exposing the access_token.
http://your-repository-name.prismic.io/api/v2/documents/search?ref=Your_Ref&access_token=Your_Token
In my API/Security settings I'm also given a Client ID and Client Secret. I can't figure out how I can use these either.
Thanks
You'd have to store your access token on your server and make it process the requests on behalf of the client.
In the end, you'd send requests to your server instead of directly to prismic.io, your server will then send the access token authorized request, fetch whatever you need and return it back in response to the client.
The work flow would look like this:
Client sends request to i.e. http://localhost:8000/api/endpoint
Server sends request to prismic.io endpoint associated with the above endpoint.
Server gets prismic.io response and sends it back to the client.
Client gets the response.
If you want to hide your access token client-side, then it's impossible. To protect your access token the other two options are:
Make users use their own prismic.io access tokens.
Allow access only to authorized users.
The two options above are probably not what you want, so setting up a proxy server is what's left.
We offer a web service, where a user can execute a POST request and get HTML. This is done server to server. The post that is sent with the request data includes his secret key, and other parameters.
We want to allow for this to be loaded via AJAX. So the request will be done client side, after the page has loaded. This way, no server side implementation will be required to install our service, beyond a slight modification to output the script.
We are not sure how to secure this operation, because we can not output the secret key as a JavaScript parameter (it is exposed that way). We usually use a user ID + apiKey combination to authenticate the request when it is don't server to server.
We know the users's key, and their valid domain, so if there's a way to make absolutely sure the domain that is sending the request cannot be faked, it may also solve our issue.
How can we make it so that we can differentiate requests coming that way, without exposing our secret key, so that we may provide the information only the authenticated requests?
I need to send the response of a api call to another server, is there a secure way of doing this? I need to make sure that the client server doesn't tamper with the data too.
The goal is to allow the user (with there own api key) to make a request to a 3rd party api, and securely give the response to me to verify information. This needs to be done, given that the the 3rd party api doesn't have oauth support.
As you've not had a response for a month, I'll have a pop at a broad answer.
The 3rd party API server would need to store a return URL against the client's API key. When they receive a request using the client's API key they will match the key with the URL in their database and send the response to that URL instead of back to the client.
This will require cooperation with the 3rd party API provider, and implementation specifics would depend on them.
An aside, oAuth wouldn't necessarily help you here as the token generation system (that I rather assume you are referring to) is only relevant for the authentication part of any API interaction, and you didn't mention specific uses.