I'm building an Electron application that uses Google's YouTube Data API v3.
For accessing the API, I decided to use the standard API key (instead of OAuth, since I am not going to be accessing any personal data).
But the problem is, I cannot hide the API key in my app, and I also cannot use referrer restrictions (referrer restrictions allow you to filter which web sites can use your API key (by HTTP address)), since this is an Electron app. So basically, if someone looks at the source code (or even just at the developer tools), they can see the key, and use it freely.
Any advice on what to do? Thanks.
The only way to secure your API key for an application that does not require users to register or log in, is to place it behind a server proxy. So, when they start the app, the app reaches out to your server, the server then returns the API key so it only resides in the app in dynamic form, it is never visible to users.
However, this is still insecure if they use a packet sniffer or local proxy they can grab your token.
The most secure way to do this is to make all your API requests from a private server that your app has access to. So, the app makes no requests to Youtube, it only gets the data from your server.
Then, you can secure your app by signing API requests to your private server with a private key. For example, you could have a config file in the app with a private key that is sent in the header of every API request. Then, they only way to get your key would be to decompile your app, and then access that config file, then make API requests to your private server using the same private information. Then, to prevent malicious users, you can monitor traffic and set up request limits, like 1 request per second per app. Any app exceeding that limit could be black-listed as a DDOS attack or a malicious user.
The data flow would look something like this.
App -> Server (with Api Key) -> youtube (data) -> Server (data) -> App
Related
I have looked into the first 15 "similar questions" to my question and none resolved my issue. Sometimes, the error I am getting for the same API request is "This IP, site or mobile application is not authorized to use this API key. Request received from IP address {*ip_address*}, with empty referer". I also searched for that and none of the solutions suggested helped in my case.
My current situation
I am calling https://maps.googleapis.com/maps/api/directions/json?key=MYKEY&some_other_params in an iOS project
I am using an API key that is restricted to a Bundle ID
I have a list of items (let's refer to it as location items) that when clicked I call the Direction API to get route info
I am getting the two errors I mentioned above interchangeably. That means sometimes I get the expired error and sometimes I get the IP error. I get the errors for the same location item.
APIs enabled:
Directions API
Geolocation API
Maps SDK for iOS
Geocoding API
Places API
The Bundle ID is not the problem
I know that my Bundle ID is correct as I am using it with another service, which is Firebase. To eliminate the silly mistake of mistyping, I copied the same Bundle ID from my Firebase API credential. My API key for Firebase is restricted to the same Bundle ID and to the Firebase service. It is working without any issues.
API restrictions only
To eliminate the Bundle ID issue, I also tried None for the Application restrictions and chose to restrict APIs. I added the APIs I listed above one at a time and called the Directions API. Nothing worked, neither having a single API (Directions API) or having all of them.
The weird thing about Places API
A weird behavior I am getting is that I created a new API key and it worked without any restrictions. What is more weird is that I disabled Places API temporarily. I did this as I wanted to "refresh" my APIs. I read in another thread that the IP issue was resolved by disabling and re-enabling the Places API.So I turned it off but did not turn it on immediately. I used a new API key and clicking my location items yields to route info (I got the desired result).
Other restrictions (usage limit and billing)
I know that it is also not about the restriction of too many attempts on the Directions API. The documentation states that the limit is 50 requests per second. Besides, I did the "fast clicking of items" using the unrestricted API key and I always get a route info. Billing is also enabled on our project so that's not the issue either.
Stuck with an unrestricted key
Right now we are using an unrestricted key that is unacceptable. I wonder, why using an unrestricted key works perfectly and restricting it does not. I am sure I am missing a configuration but I have tried every possible combination that I can think of.
API keys restricted to your application's bundle ID won't work for backend web service requests such as Directions API. These API keys would only work for request made from Places SDK and Maps SDK for iOS. This is the reason why you are getting the error "This IP, site or mobile application is not authorized to use this API key. Request received from IP address {ip_address}, with empty referer".
According to Google Maps API key best practices, for API keys used for Web services sent directly from a mobile applications, you can do one or more of the following techniques to secure your API keys:
Use a proxy server. The proxy server provides a solid source for interacting with the appropriate Google Maps Platform API. Then restrict your API key with IP restrictions.
Obfuscate or encrypt the API key or signing secret. This complicates scraping of API keys and other private data directly from the application.
Use CA pinning or certificate pinning to verify the server resources are valid. CA pinning checks that a server's certificate was issued by a trusted certificate authority, and prevents Man-In-The-Middle attacks that could lead to a third party discovering your API key.
i want to use google map api for route between two location. in my IOS application. i try create public key for project and enable uses API in developer console. but i got this error: this ip site or mobile application is not authorized to use this api key IOS. after this error i try create API key for Key restriction for (IP addresses (web servers, cron jobs, etc.)) and set my ip address and then routing is work fine. but when i try this from other device again and again i get this error.
i should use this URL for routing :
let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving&key=APIKEY"
how can solve this problem for working my code in all devices.
The API key that you use with Google Maps web service (Directions API) supports an IP restriction as mentioned in the following document:
https://developers.google.com/maps/faq#using-google-maps-apis
The issue is that you cannot know the IP addresses of all devices where your application is installed.
You have the following options:
Use unrestricted API key. Note that API key requires HTTPS connection, so the API key won't be intercepted from the request itself, because the request is encrypted. So, in this case you should procure that the API key is not put directly in your source code. If you can read it from config or the environment, it might be feasible.
Create an intermediate server. Your iOS application should send requests to the intermediate server, intermediate server should send requests to Google and pass responses back to your app. In this case you can restrict an API key by IP address of your intermediate server.
I hope this helps!
I have an iPhone app that uses a Rails server HTTP API. The API is public at this point - no authorisation is required to get the data.
Currently anyone can go to API's URL and download the data.
http://server.com/mydata
The data is not very sensitive. But I still want to prevent people from easily getting it. What are the ways of doing that? I do not want iOS app users to log in either.
Current solution I have
iPhone app adds a secret token to the HTTP header or query of the request. The data goes over HTTPS.
https://server.com/mydata?secret=my_secret
Is there a better approach?
You could try an approach where the client is only allowed X number of requests per time period (based on IP address or username)
HTTPS is extremely easy to man in the middle on a device you control. You can do SSL cert validation, but there is always someone out there with more time, so best off to handle it server side.
Distribute and use your own SSL certificate.
Apps that transfer sensitive customer data, like credit card and payment information, must be protected from man-in-the middle attacks. The best protection is a mutual authentication scheme, where certificates are exchanged to make sure the app is connected to a trusted server and to make sure the server is connected to a trusted app.
Then only individuals (who have presumably installed your application) have access. If someone digs through the code and gets the public certificate then they can impersonate the client; but at that point they win anyway and two-factor authentication should be explored.
I want to create a iOS app, and I am starting to design a api using node.js+mongodb+express. I know people can use charles to set up a proxy and when user open the app in the iphone device, they can see the api requests in charles app. So people can use this api to do some harm to the app services or what. I want to secure my api. I won't open my api to others. So, I don't need oauth. What else I can do to secure my api? And if any tutorial is provided, that will be good.
Do it with https, just make sure your app stops working if the certificate is invalid.
Alternative:
Crypt/decrypt your http(s)-body before sending/after receiving with a global password (not recommended) or a public key on your phone and a private key on your application.
If someone gets that pw or public key, they can still manipulate the API.
What you want to do is use https with additional security.
First: In the app "pin" the server certificate, that is validate the server certificate in the app, this is quite common these days. AFNetworking supports this.
Second: Add a certificate to the app and verify it on the server. Now the server knows it is communication with your app.
Now both the server and app have assurance they are communication with authenticated end points.
That is, want a Rails application that lets me see a customized view of the user's Gmail calendar. But it'll be on shared hosting so don't want to store credentials, or have them in the clear.
Question: Can I securely access Gmail for a Rails app on shared hosting non-SSL without putting credentials at risk? How would I do this? (e.g. does OAuth or OpenID solve this)
Requirements would be:
Rails application will call Google Calendar via API
No credentials stored on shared hosting site (e.g. in database or whatever) - MANDATORY
Rails site is non-SSL - MANDATORY (for the purpose of this question)
Ability to stay logged in whilst browser still open - DESIREABLE (assume using session id...assuming this is secure)
For example exiting approach I've used which wouldn't satisfy my requirements on my non-SSL rails site (on a shared host) would be:
# Get Google Calendar
service = GCal4Ruby::Service.new
service.authenticate("<google account name>", "<password>") # <== requires password
cal = GCal4Ruby::Calendar.find(service, "myCalendar")[0]
# Get Google Events
search_str = "<search str>"
#events = GCal4Ruby::Event.find(cal, search_str, params)
You will get mixed content if you try to include in an http page an https Google calendar view loaded as an iframe.
If you're just doing API calls, as long as the API calls are from your server to an encrypted endpoint, https://calendar.google.com or something similar, then there are no problems.
If you're doing API calls from a non-http page in the browser, then a determined attacker will be able to eavesdrop on any data you serve, including credentials sent to the browser for forwarding to the calendar service.
If you're sending credentials to the browser you should also worry about exfiltration via XSS.