I have an API endpoint https://api.example.com/api/v1/example/trending.
The API is intended for Android and iOS apps. Currently, if anyone browses the above URL they will get the public results because it is used for the mobile splash screen.
How can we restrict the results to be only available on the mobile app?
Public APIs vs Private API
I have an API endpoint https://api.example.com/api/v1/example/trending.
The API is intended for Android and iOS apps. Currently, if anyone browses the above URL they will get the public results because it is used for the mobile splash screen.
From the moment you publish an app that calls an API, that API is public, even if you have done your best to keep it private, like not having public docs for it anywhere, and/or having it behind authentication mechanisms, and this is because all the attackers needs is to perform a MitM attack in order to enumerate all the API endpoints and how they are used by the mobile app.
It seems that you have an API that is not behind any form of authentication. By other words your API seems to not try to distinguish between who vs what is calling it.
So, I would like to first clear a misconception that usually I find among developers of any seniority, that is about the difference between who and what is accessing an API server.
The Difference Between WHO and WHAT is Accessing the API Server
I wrote a series of articles around API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read in detail the difference between who and what is accessing your API server, but I will extract here the main takes from it:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
You can think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and think about the what as the software making that request in behalf of the user.
So, by your description your API doesn't seem to try to identify neither the who or the what, but at least you can modify it to identify what is doing the request to it in order to lock down your API server to only serve requests from genuine and untampered instances of your mobile app.
Possible Solutions
How can we restrict the results to be only available on the mobile app?
To lockdown your API server with your mobile app you can start by using an identifier in the mobile app, like an API key, as I wrote about in the article I already linked above, and where I wrote:
When Should I Use an API Key in a Mobile App?
I hope that by now that you understand the difference between who and what is accessing your API and the difference between a public and a supposed private API, thus being aware that an API server needs a way to know what it is serving the requests to, even before it is able to know who is making those requests.
It should now be clear that every time you build a mobile app that communicates with an API server, a secret must be used to identify it, and this secret is usually named by developers as an API key.
But now you have another challenge, and not an easy one, how do you will secure this API key from being extracted, and from the same article I will quote:
Is it Possible to Secure The API Key in a Mobile App?
This is a tricky one and the reply is NO and YES…
Well, it is NO because any static secret stored in the source code of a mobile app can be reverse engineered by using tools that decompile the binary of the mobile app, leaving it exposed to human eyes and tools like grep, but you can even try to use the strings tool to perform a lookup into a binary without the need to decompile it.
Let’s imagine that you are an advanced developer and went the extra mile to protect the API key and calculate it dynamically at run-time. Your effort is appreciated and will put off most of the script kiddies, but will not take away the hackers, that will use introspection frameworks like xPosed and Frida in conjunction with the already decompiled code to understand how and where the API key is generated at run-time in order to intercept and extract it. A better way exists though, using a proxy between the device that the hacker controls and the API server is a fast and easy way to grab an API key generated at run-time.
So, I just quote why is not possible to secure the API key, but I don't quote the bit about how it's possible to secure it, because first I want to point you out to how you can reverse engineer your mobile app and how to do a MitM attack.
To learn how to reverse engineer a mobile and at same time how to hide secrets in a mobile app, that are hard to extract with static binary analysis, I recommend you to read my article How to Extract an API key from a Mobile App with Static Binary Analysis:
The range of open source tools available for reverse engineering is huge, and we really can't scratch the surface of this topic in this article, but instead we will focus in using the Mobile Security Framework(MobSF) to demonstrate how to reverse engineer the APK of our mobile app. MobSF is a collection of open source tools that present their results in an attractive dashboard, but the same tools used under the hood within MobSF and elsewhere can be used individually to achieve the same results.
So, if you are not able to extract the API key, because it's hidden in native C code, then you do a MitM attack as I show in my 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.
By now you may be wondering that no matter what method is used to hide the API key, you are doomed to fail your mission to allow the API server to identify what is doing the request, but you can still do a lot more, and to learn about what more can be done 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.
The above answer will give you an overview about mobile app hardening, basic and advance API security defenses, and also would introduce you to a possible better solution by using the Mobile App Attestation concept.
In a nutshell the mobile app attestation will allow your API server to identify what is doing the request, therefore it bill be able to distinguish requests from genuine and untampered instances of your mobile app from requests made by bots, scripts, cURL, Postman, or any other tool.
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.
I am a new developer. I have a React SPA deployed on Firebase that queries Google’s Geocoding and Time Zone APIs. I cannot restrict access based on HTTP referrers/domain names because these APIs are web service APIs and have to be restricted based on IP address. However, there does not seem to be a way to get the IP address of a Firebase app.
So my question is, are there alternative approaches to using and securing API keys in my app? I am particularly interested in approaches that leverage any inbuilt capabilities of React or Firebase.
An IP restricted API is supposed to only be used in server-side applications.
I suppose you should configure your key restrictions for Android/iOS apps:
I am working on an app where I want to use the Google Maps API.
The problem is the connection to Google Maps API server is unstable. Sometimes it's OK but other times it's blocked because I'm in China.
The solution I've come up with is to make all the Google Maps API requests through a reverse proxy. I can setup a server as a reverse proxy in American or Hong Kong where there is a steady connection to Google maps server.
Then I have to change the urls of all the Google Maps APIs in my app to point to my reverse proxy and the proxy will proxy_pass all the requests to Google Maps server.
There are a few questions I have about this:
How would I go about implementing the client side libraries? Do I have to change them? If so, can I just download the Google Maps JavaScript API file and change the domain names of the urls in it to the domain of my proxy server?
And how would I go about Android and iPhone apps? I'm uncertain whether the Android and iPhone SDKs will make the request with http protocol. If it is, how can I replace the domain names of the APIs with the domain name of my proxy server?
I thought maybe there is a way to catch all the http requests made in my app and modify them before they get sent but after googling for a while I've found it's hard to do.
So is it possible to do this with Android and iPhone apps? Or is there a better way to achieve it with a web app?
I also would like to know is it worth the effort to do this since the solution seems to be rather complex and using the Google Maps API is not a necessity because there are replacements to it in our country. I just prefer Google Maps API to them because of its neat API style and the prettier look of maps.
Your solution is a blatant violation of Google's terms and conditions.
10.1.1 (a) You must not access or use the Maps API(s) or any Content through any technology or means other than those provided in the Service, or through other explicitly authorized means Google may designate.
For example, you must not access map tiles or imagery through interfaces or channels (including undocumented Google interfaces) other than the Maps API(s). https://developers.google.com/maps/terms
Legal issues aside, I think you answered your own question. "Google Maps API is not a necessity because there are replacements to it in our country".
But if your hell-bent on using Google Maps you can use their tiles with a 3rd party library like leaflet for web content. Native mobile apps are an entirely different problem though...one which I suspect is either a: not possible or b: not feasible.
FWIW, this doc from Google states it is acceptable to cache map images.
https://developers.google.com/maps/premium/optimize-web-services#cache
Significant correction to the accepted answer:
The cited section 10.1.1 no longer exists. Moreover, searching for the terms "authorized" or "other than" in the Terms & Conditions (T&C) returns no hits for a similarly worded replacement.
In conclusion, upon reading the T&C it appears that Google no longer explicitly says You must not access or use the Maps API(s) or any Content through any technology or means other than those provided in the Service nor does Google appear to provide a replacement.
T&C here: https://cloud.google.com/maps-platform/terms/
There is a Google Lab to use the Google Places API: Google Maps Web Services Proxy for Mobile Applications
It seems that this is the repo: https://github.com/googlecodelabs/google-maps-web-services-proxy
I need to authenticate by OAuth to some sites (e. g. flickr) by Javascript and I want to make experience similar to what Facebook login-button does. When you click login-button a popup window is opened, you authenticate and then popup window is closed and onlogin event of login-button is raised.
Is there any Javascript library which implements this behavior for OAuth?
This is a feature of OAuth 2.0, which specifies a client-side flow which facilitates this.
The spec is here and Google's implementation of it is described here.
Support for this is included in the google-api-javascript-client (for Google APIs and login) and there is a general library that will work with supported providers called gwt-oauth2 -- it's written in GWT, but is also usable in a standard JavaScript environment.
edit: Microsoft's Live Connect library appears to support this flavor of OAuth 2.0 as well.
Unfortunately, Flickr does not appear to have support for this, as it only seems to support OAuth 1.0a.
But there some popular providers that do support the client-side OAuth 2.0 flow:
Google
Facebook
Foursquare
Instagram
DailyMotion
Windows Live
You could run your own server to make OAuth 1.0a requests to Flickr and send back OAuth 2.0 access tokens to the JavaScript client, I suppose.
I am certain janrain offers authentication to sevaral sites using node.js, I would give it a peek. Also try this example
On this page: http://code.google.com/apis/accounts/docs/OAuth2UserAgent.html Google gives instructions for doing oauth with client side applications that talk to their apis.
One step is to call their token validation api. But if I want to do this from javascript, it would require an ajax request which is cross domain.
It seems like with all the improvements to cross domain stuff recently this should be possible, but I'm not figuring it out. Any pointers would be helpful.
If you want a completely browser-based solution, you should consider using the Google APIs JavaScript client. Here is the documentation on how to do auth using that library: https://code.google.com/p/google-api-javascript-client/wiki/Authentication