I've developed simple REST API using a expressJs. I'm using React as my client side application. So the problem is anyone can see my API endpoints because of react app is in client side. So they will also able to make request and fetch data from my REST API. (May be they will build their own client side apps using my API.) I've seen some question about this and couldn't find any comprehensive answer. How these kind of a security problem should be handled? Is it possible to give the access for API to only my client app? If not how huge brands that using REST API prevent that? (Also I don't have a user authenticating scenario in my product as well. People can just visit and use the website. They don't need to register).
Authentication can be a way but it can be bypassed. Another way is you can create a proxy server which strictly blocks cross origin requests, hence it blocks requests from other domains to make request to your API, and you can make your API call from that proxy server. In this way your API server endpoint will also be not compromised.
If, as you state in your comment, this is about users on your own website being allowed to use your site's API, while disallowing off-site use (e.g. other websites, wget/curl, etc) then you need to make sure to set up proper CORS rules (to disallowed cross-origin use of your API) as well as CSP rules (to prevent user-injected scripts from proxying your API), and you also make sure to only allow API calls from connections that have an active session (so even if you don't want user authentication: use a session managemer so you can tell if someone landed on your site and got a session cookie set before they started calling API endpoints).
Session management and CORS come with express itself (see https://expressjs.com/en/resources/middleware/session.html and https://expressjs.com/en/resources/middleware/cors.html), for CSP, and lots of other security layers like HSTS, XSS filtering, etc, you typically use helmet.
It's a hot debate on how to securely handle API Keys.
And almost all of us know that it's the best solution to have them stored on the server side, and never exposed in client-side applications.
Our clients can send requests to our APIs, and our APIs can act as proxy to send/receive data to/from the third party API and return the response back to our client.
However, there are some third party SDKs that you can integrate into your client-side app and they also have their API Keys.
For example, Zoom has SDKs for Web, Android, iOS, Windows, etc., or Pusher has Pusher Key.
When you want to work with these libraries, you CAN NOT send request to your API to hide API Key. You have to initialize these libraries in your client-side code (react for example).
An example from Zoom to join a meeting inside your web app:
client.join({
apiKey: apiKey,
signature: signature,
meetingNumber: meetingNumber,
password: password,
userName: userName
})
What are the best practices to secure API Keys for client-side SDKs and libraries?
Your Problem
When you want to work with these libraries, you CAN NOT send request to your API to hide API Key. You have to initialize these libraries in your client-side code (react for example).
What are the best practices to secure API Keys for client-side SDKs and libraries?
Well you found yourself a very hard problem to solve (but not impossible to some degree), because once the API Key is in the client side it's public. So, no matter how well you hide it will always be possible to retrieve it on a browser or mobile app.
Web Apps
On browsers is very trivial to get hands on the API key, just open the developer tools and in the network tab look for the request you are interested in extracting the API key and click on it to inspect the request headers.
Mobile Apps
In mobile devices id more laborious to extract an API key from a mobile app, but not that difficult has many may think.
JNI/NDK - Hide API Key in Native C Code
For example, you can hide the the API key in C native code via JNI/NDK:
Using Android Studio 2.2 and higher, you can use the NDK to compile C and C++ code into a native library and package it into your APK using Gradle, the IDE's integrated build system. Your Java code can then call functions in your native library through the Java Native Interface (JNI) framework.
This approach aims to protect the AP/i key from being extracted from your mobile app binary via static binary analysis, as exemplified in this repo and blog post I wrote:
During this article we will use the Android Hide Secrets research repository that is a dummy mobile app with API keys hidden using several different techniques.
Extract the API Key hidden in Native C Code with a MitM Attack
In the above blog post the API key hidden in the source code with JNI/NDK interface was not possible to extract via static binary analysis, but it was easy to extract with a MitM attack as I demo in the article Steal that Api Key with a Man in the Middle Attack:
In order to help to demonstrate how to steal an API key, I have built and released in Github the Currency Converter Demo app for Android, which uses the same JNI/NDK technique we used in the earlier Android Hide Secrets app to hide the API key.
So, in this article you will learn how to setup and run a MitM attack to intercept https traffic in a mobile device under your control, so that you can steal the API key. Finally, you will see at a high level how MitM attacks can be mitigated.
Prevent MitM Attack with Certificate Pinning
The first thing one can do to prevent a MitM attack is to use certificate pinning and I wrote about how to do it in the article Securing HTTPS with Certificate Pinning:
In order to demonstrate how to use certificate pinning for protecting the https traffic between your mobile app and your API server, we will use the same Currency Converter Demo mobile app that I used in the previous article.
In this article we will learn what certificate pinning is, when to use it, how to implement it in an Android app, and how it can prevent a MitM attack.
I see the smile on your face now, but will not be for long because certificate pinning can be bypassed.
Bypassing Certificate Pinning
You can do it repackaging the mobile app without pinning or by using an instrumentation framework at runtime to disable it.
Repackaging the mobile app to bypass pinning
This is not hard to achieve when you have the correct tools and open source is full of them. I wrote how to do it in the article Bypassing Certificate Pinning
In this article you will learn how to repackage a mobile app in order to make it trust custom ssl certificates. This will allow us to bypass certificate pinning.
Using an Instrumentation Framework to bypass pinning
This is my preferred method and my instrumentation framework of preference is Frida, and guess what, I also have an article on it with the title How to Bypass Certificate Pinning with Frida on an Android App to show you how to do it:
Today I will show how to use the Frida instrumentation framework to hook into the mobile app at runtime and instrument the code in order to perform a successful MitM attack even when the mobile app has implemented certificate pinning.
Bypassing certificate pinning is not too hard, just a little laborious, and allows an attacker to understand in detail how a mobile app communicates with its API, and then use that same knowledge to automate attacks or build other services around it.
Possible Solutions
You may employ an array of different approaches and techniques to defend your API server and mobile app, but give preference to use a security solution that spans both the mobile/web app and API server.
The solution(s) to use will depend on your threat model, your budget and your resources and I will give you below pointers to some options.
For Mobile Apps
I recommend you to read this answer I gave to the question How to secure an API REST for mobile app?, especially the sections Hardening and Shielding the Mobile App, Securing the API Server and A Possible Better Solution.
For Web Apps
You can learn some useful techniques to help your API backend to try to respond only to requests coming from what you expect, your genuine web app, and to do so I invite you to read my answer to the question Secure api data from calls out of the app, especially the section dedicated to Defending the API Server.
Do You Want To Go The Extra Mile?
In any response to a security question I always like to reference the excellent work from the OWASP foundation.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
For Mobile Apps
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
For Web Apps
The Web Security Testing Guide:
The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.
What do you want to secure exactly? I assume you want to avoid someone from misusing your API key, but you should ask yourself, from what security risk or threat do you want to protect?
You should also understand what kind of API key are you dealing with, as not all of them are intended for the same use-case and could 'offer' different level of security.
For example, you could have an API key in the form of a personal access token (in GitHub, for instance), where the token is directly tied to a user/employee and should be considered a secret, or you may have an API key in the form of a machine token that it's tied to your organization or your repository (still in GitHub, for instance) and that can be configured with different permissions (read-only, read-write).
It is also possible that the API key can be configured and restricted to some clients, according to the possibility of the client itself.
For example some of the Google Maps APIs allow you to configure a trusted origin that it is allowed to perform requests using your specific API key, however this protection works by checking the referrer header of the request and it could be spoofed by arbitrary clients. Browsers should still honor the convention and send the correct referrer, protecting you from people that want to use your API key on their website.
Another example in the mobile application world: there are some vendors that allow you to bind your API key to a specific package name that it is then validated at runtime by the vendor's SDK, however this kind of protection is usually as a licensing mechanism, to avoid developers to configure for free an SDK with a leaked API key.
Most generally, if the API key is intended to be used on public clients, then the developers of the API already considered the threat of having this leaked and you should not have a repercussion. This means that you will be covered from huge API usage billings or from rate-limit/usage quota limit (but better check yourself!).
The general rule is to always check the developer's documentation of the application you're trying to configure and see how to create a proper API key for your use-case and if it's fine for you to have this 'leaked' from your client. Additionally, if the API key allows you to configure permission, remember to follow the Principle of Least Privilege.
Another golden rule is to always threat model your implementation:
What are the capabilities of the API key?
What is the worst an attacker can do if they access the API key?
Am I protecting myself from these threat? How? Can I put more controls or monitors on back-end side (i.e. notification on high usage, etc)?
Finally, if your API key need to be kept secret, then you must not use this on a public client, no matter how hidden it is. There will always be at least one person able to retrieve it (And don't rely on client-side check either!). In this case what you want is probably to have your own back-end service responsible both for querying the APIs using the secret API key and for authenticating and authorizing your customers/users, and also to implement additional security measures like rate limit.
One thing I found very helpful is to always document any generated/used API key and its capabilities along with the threats of having them leaked and some preventive measures to minimize the risk.
I'm building a browser based application in Javascript. I've tried to access the docusign api via jQuery:
$.support.cors = true;
$.ajax({crossDomain:true, url:"https://demo.docusign.net/restapi/v2"})
I get the error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://demo.docusign.net/restapi/v2?_=1407189114238. This can be fixed by moving the resource to the same domain or enabling CORS.
Accessing other APIs such as yahoo, totally works:
$.ajax({crossDomain:true, url:"https://query.yahooapis.com/v1/public/yql"})
Is there a special thing that I need to do for docusign api? Thanks. (Note: My examples here use blank queries to illustrate whether an api is accessible at all. The actual code uses real queries. This problem is not caused by not having a real query. You can see this yourself by pasting the above url into your browser and see that it returns some xml.)
DocuSign does not support CORS (Cross-Origin Resource Sharing) in its platform. There are too many potential security risks with CORS and for DocuSign to maintain its extremely high level of security and certification compliance it can not support CORS.
is there a way to block REST API calls to a non authorized client?
is there a way to make the API "limited" to (public for) only small number of well defined clients?
thanks :-)
You can deploy mutually-authenticated SSL between your clients and your server. You can use self-signed certificates here so you don't need to buy any from a CA. This will ensure that your server only accepts requests from clients that have the client-side certificate (configure your server to only accept the self-signed client certificates deployed on your clients for client authentication).
If you are using RESTFul HTTP
you can add an HttpServletFilter to your web.xml which prevents unauthorized clients from accessing your REST Methods.
See
Securing JAX-RS and RESTeasy
If you use the Spring Framework you and you don't want to implement your own HttServletFilter you can use Spring Security
You just need to implement security mechanisms in your RESTful Service, so it denies access to unauthorized clients (with a 404 or 401 response code). There are several ways to achieve this:
Relay on HTTP authentication mechanisms, like Basic Authentication
Implement a Custom Authentication framework, that overcomes HTTP Basic Authentication limitations. Amazon has an interesting approach that includes custom HTTP headers and supports hashing.
Use an existing security framework and add its capabilities to your service. Spring Security sounds like a great option.
The purpose of this question is to confirm (or not) my understanding of the purpose of W3C Access Control. If I'm reading this correctly, it allows a resource to control who can access it from a page loaded from some other resource. It does not protect a page against malware injection making cross-script requests. In other words, any bad hat can create a (e.g.) restful service that cheerfully accepts stolen information, so long as it returns the headers from this spec to tell that browser that it is happy to do so. Have I missed anything?
Your understanding sounds correct. The CORS spec only details how code from one domain can access data from another domain, thereby getting around same-domain restrictions. The same security considerations as any other web request are still in effect with CORS, and you should trust the remote server you are loading data from. If you are implementing CORS on the server side, you should not rely on CORS as your sole security mechanism. If giving access to some protected resource, you should layer an auth mechanism such as OAuth2 on top of your CORS requests.