Google API Key for browser. Issue when referrers set - javascript

I generated Browser API Key in Google Console and set referrers:
Then I go to http://afriflirt.com, open JS console in browser and run this code ("Google Maps Geocoding API" enabled for this api key in settings):
var apiKey = 'AIzaSyAGpR-mG46fDbmWjJwkZZHft_xvZ_dM3cA';
$.getJSON(
'https://maps.googleapis.com/maps/api/geocode/json?address=12345&key=' + apiKey,
function(resp) {alert(JSON.stringify(resp));}
);
in response I see this message:
This IP, site or mobile application is not authorized to use this API
key. Request received from IP address 113.180.75.109, with referer:
http://afriflirt.com/
If I remove referrers - API key start working, but this is not safe.
So it's a problem only when I set referrers. Tried different formats of referrers patterns, but nothing worked. Also tried to wait some time (as I saw "it may take up to 5 minutes for settings to take effect"), but it doesn't help too.
Please let me know if you have any ideas how to fix this.

According to the documentation, you need a server key for the geocoding web service.
Create a server key, enable it for IP address: 113.180.75.109, that should work in your example (but it isn't recommended to use a server key from javascript like that, use a browser key and the Google Maps Javascript API v3 Geocoding Service).

Related

How to restrict my google API key and use it with Google Geocoding API in Javascript?

I have a WordPress site and I am using a NPM package to call the Google Geocoding API from google and get the latitude and longitude from an address, it includes the API key and the address to look for. I had to un restrict my API key on my google console because I was getting an error when I was trying to do the call.
The package is here: https://www.npmjs.com/package/#google/maps
What I am trying to achieve is to restrict my API key to be used only on the site. Right now it is only restricted with Geocoding API, Javascript Maps API and Places API filters so it won't be used with any other kind of library.
I am only using the geocoding functionality on the site and nothing else so it doesn't make sense to have a Map, but I have the places and maps libraries active because on the WordPress admin I use them.
I tried the HTTP referrer restriction with the website domain name and IP address restriction with the server IP where the site is being hosted but none of these worked.
I have a googleClient object which handles the Geocoding API
let requested_address
googleClient.geocode({address: requested_address})
.asPromise()
.then((response) => {
// Call to another function passing the location object from response
showLocations(response.json.results[0].geometry.location)
})
.catch((err) => {
// print error message in screen
$('.results-message').show().html(err.json.error_message)
});
I get an error with this message:
API keys with referer restrictions cannot be used with this API.
I am trying to get a way to use this same package with the API Key restrictions so it is not used on other sites/apps or other way to get the location latitude and longitude, even if you just put a zip code or a non complete address as Google Geocoding does.

What are end points in an API

I have the following description of an API. How do I call this API in my react app or through postman? I don't understand the endpoints in it.
Deployed a CORS-enabled API for IP geolocation and weather lookup at
https://weathersync.herokuapp.com.
There are two endpoints:
/ip
Get the geographic location of the requestor’s IP
/weather/$lat,$lng
Get weather for a given latitude & longitude
I tried https://weathersync.herokuapp.com/weather/28.704059,77.102490 in postman but it doesn't work. Also, https://weathersync.herokuapp.com/?ip=192.168.0.106 doesn't work. Any help is appreciated aI i am new to APIs
Through simple trial and error I managed to determine that this API expects you to call it like this for the /ip route:
https://weathersync.herokuapp.com/ip?73.119.54.218
Note that this is pretty unusual and would be considered incorrect by most API designers. I would expect it to be /ip/73.119.54.218 instead, but the server is not set up correctly to handle that.
Also, as TKoL mentioned in the comments, an IP like 192... will never work, because it is a local IP address that is not visible to the outside world beyond your network. If the server attempts to lookup anything based on that IP address, it will likely not find anything, or even worse it might find something about a computer inside of its datacenter, in which case it could return data that is subtly incorrect from your point of view. You can find your external IP with services like iplocation.net.
Your weather example works fine for me as-is (try clicking below in a browser):
https://weathersync.herokuapp.com/weather/28.704059,77.102490
I did not try Postman, but it may not be working for you because it does not send the same HTTP headers as a browser does. Some servers expect certain headers to be sent. You can manually configure the headers in Postman to mimic a browser, which should work if that is the case.

Do I need to hide API key when using google maps js API? If so, how? [duplicate]

This question already has answers here:
How do I securely use Google API Keys
(2 answers)
Closed last month.
According to https://developers.google.com/maps/documentation/javascript/tutorial#HTML5 ,
it seems I can add the following tag to my html and start using maps js API.
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
But this will reveal my API key.
After searching on google and browsing answers on stackoverflow, I feel that maybe there is no need to hide this API key. I just need to set the referer when I create the API key on google, as explained in
https://stackoverflow.com/a/2256312/1316649
So, even others know my API key, they cannot use it from another domain. Am I right?
But google says you shouldn't embed API key in code:
https://support.google.com/cloud/answer/6310037
So, do I need to hide API key when using google maps js API? If so, how?
Update: By 'API key', I meant browser API key.
You can create multiple API keys with different restrictions to use them safely. For embedding a map, the Google Maps documentation has instructions for creating a correctly restricted API key so that it cannot be abused for other purposes at Get an API Key - Restricting API keys. It's OK to include a restricted API key in your source code, because you cannot embed a map properly without doing that anyway.
If you need server-side API access, you can create a second API key with less restrictions. That one should be kept secret.
While the above answers are helpful, none of them addresses the following vulnerability:
Once a user has access to your API key, even if they are restricted to using it only from your domain, they can still use it as much as they want. In the crudest sense, this could mean a million page refreshes (and map loads) in a very small amount of time, consequently putting you over your usage quota.
I haven't come across any solutions that address this issue. Unless I'm missing something...?
Relevant usage limits for google maps javascript api here.
The link that you posted that says you shouldn't embed API keys in code is related to Google's Cloud Platform. You are fine to leave your API key for Google Maps in your code.
To hide an API key for any service:
Design a web server that will accept requests for the third party service and proxy requests to them.
Design your interface to make requests to the web server that you designed in step 1.
Store the key on the web server you built in step 1, and apply authentication, authorization and rate limiting to the 3rd party proxied requests.
The 3rd party libraries that you use might to build and interface in step 2 might force you to use certain hosts or might force you to include an API key. For the first problem, you'll have to either edit their library code, or provide the 3rd party client library with a different http request library, like redefining the fetch() function in javascript for example. For the second problem, just add a garbage key and your proxy server can ignore it and re-write it with the real key.
Benefits:
Hide your keys.
Track who, what, and when for requests and responses. You could do this other ways though.
Could add a layer of caching to the service to speed up requests that other users have made before, provided that their terms of service allows it.
Caveats:
Because users will be making requests pretending to be your server, you are accepting a security risk. If the user intentionally makes maliciously formatted requests, they are doing so while appearing to be your server. You can however log all requests if you want to audit them later.
It takes more than a couple seconds to build and configure the proxy server with all the security you require.
You now need to handle all of these web requests which may be a lot of traffic.
You may want to intercept the responses the server returns in case it returns the key in the response body during in an error or otherwise.
You are adding another link in the chain and it will make the service slightly less reliable.
Mentions
I wanted to mention that this is essentially what "#OLTO and SUGI-cube Project" was trying to demonstrate in their answer and what #Brandon Miller was suggesting as a solution in a comment.
No need to hide API key, you just have to make it useless,
You can simply use key restrictions on the google API console.
from google API console choose:-
credentials
choose your API key or create a new one
Application restrictions
HTTP referrers (websites)
and then add your Website restrictions
I would recomend restricting your API keys to only be used by the IP addresses & referrer URLs that need them: By restricting the IP addresses, referrer URLs, you can reduce the impact of a compromised API key.
You can specify the hosts and apps that can use each key from the console by opening the Credentials page and then either creating a new API key with the settings you want, or editing the settings of an API key.
This should help you to secure your API keys.
Jeff
The two most accepted ways I have seen are to either use the [#googlemaps/js-api-loader]1 Or to - and this is important - restrict your keys the way google tells you to.
Hello there,
Even if it's too late to post an answer I believe this would help the community, so i have worked out a solution that will hide the script tag from the DOM, I managed to do it by deleting the script tag after loading the script OR if it were an error while loading it,
So here is the proposed solution and I'm happy to hear from you if it doesn't fit:
<script>
const deleteMapScriptTag = () => {
document.body.removeChild(
Array.from(document.body.getElementsByTagName('script')).find(
(item) =>
item.src.includes('https://maps.googleapis.com/maps/api/js?key=')
)
)
}
</script>
So that part will search for the google maps script tag and remove it from the document, and we will call it after the
onload, onerror
events provided by the script tag as demonstrated below :
<script onload="deleteMapScriptTag()" onerror="deleteMapScriptTag()"
src="https://maps.googleapis.com/maps/api/js?key={YOUR_API_KEY}&libraries=places"></script>
this will remove the script tag from the DOM as soon as it loads or fails loading, preventing users from inspecting the file and acquiring your key.
Although removed from the DOM, the original script tag (and therefore the key) will still be visible when viewing the page source.
Additionally, the full URL of the script can also be inspected via the Network requests panel in developer tools which also exposes the API key.
You need to hide API key
You need to hide API key when using google maps js API. It is not enough for you to set the referer.
I have local web server on my PC and can change my hosts file, So that I can spoof domain name of my HTML as your domain.
If you reveal your API key in your HTML, someone might access Google map with that key. This could mean a million page refreshes (and map loads)!
This is bad example from Google.
<script defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
How to hide API key from HTML
I use Environment Variables and CGI to hide my API key from HTML as follows.
1. set Environment Variables
I set Google Maps API key in Environment Variables and passing it to my CGI scripts.
nginx + fcgiwrap are running on my server, so I set API key in my fcgiwrap.conf like this.
fcgiwrap.conf
location /cgi-bin/ {
........
fastcgi_param GOOGLE_MAPS_API_KEY  YOUR_API_KEY; <= SET YOUR API KEY HERE
}
2. make CGI script
I made python CGI like this. This is same as src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY in SAMPLE of Google.
getapijs.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
import os
url = 'https://maps.googleapis.com/maps/api/js'
key = os.environ['GOOGLE_MAPS_API_KEY'] # get Environment Variables
mysrc = url + "?key=" + key
response = requests.get(mysrc) # get src from Google Maps url
print("'Content-Type': 'text/javascript; charset=UTF-8'") # header for HTML
print("")
print(response.text)
3. call CGI from javascript
call your CGI from window.onload. This is same as <script defer ... &callback=initMap> in SAMPLE from Google.
main.js
function initMap() {
var uluru = {lat: -25.344, lng: 131.036};
var map = new google.maps.Map(document.getElementById('map'), {zoom: 4, center: uluru});
var marker = new google.maps.Marker({position: uluru, map: map});
}
window.onload = function() {
fetch("/cgi-bin/getapijs.py").then(res=>{
return res.text();
}).then(mytext => {
eval(mytext);
}).then(() => {
initMap();
}).catch(() =>{
// error handling
});
}
4.read main.js in your HTML
set <script src="main.js"></script> in your header section.
index.html
<!DOCTYPE html>
<html>
<head>
<style>
/* Set the size of the div element that contains the map */
#map {
height: 400px; /* The height is 400 pixels */
width: 100%; /* The width is the width of the web page */
}
</style>
<title>Hello World</title>
<script src="main.js"></script>
</head>
<body>
<h3>My Google Maps Demo</h3>
<!--The div element for the map -->
<div id="map"></div>
</body>
</html>

Cant find the Gmaps API in CodeIgniter Environment

Good Day to you,
I have a difficulty in finding the google maps api key. I had to change the base_url in the config file and since then it gives me this error:
Google Maps API error: MissingKeyMapError https://developers.google.com/maps/documentation/javascript/error-messages#missing-key-map-error_.ab # js?v=3.exp&signed_in=false&sensor=false&libraries=places&language=en-USA:32
util.js:211
Google Maps API warning: NoApiKeys https://developers.google.com/maps/documentation/javascript/error-messages#no-api-keys
util.js:211
Google Maps API warning: SensorNotRequired https://developers.google.com/maps/documentation/javascript/error-messages#sensor-not-required
if i add this tag with my api key into the <head> of the page: <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY" type="text/javascript"></script>
i get this error:
unfortunately i only have an img of the error right now.
first it was missing then it was duplicated. and why would it be missing if i change the config?i know that you have to get a new api key with the new domain and i did that but there is a conflict with the old api key which i cant find anywhere. where then would i find the original key? i tried searching in all the files couldnt find any key. does somebody have a hint for me? i tried searching all files for "googleapis.com". Maybe the there is an otherway to link to the google api of which i dont know. im really looking forward to get this fixed.
thank you for your time to read this and i hope someone can help me
regards
theweeezel
As the error stated :
The script element that loads the API is missing the required authentication parameter. If you are using the standard Maps JavaScript API, you must use a key parameter with a valid API key. If you are a Premium Plan customer, you must use either a client parameter with your client ID or a key parameter with a valid API key.
If you will check the guide to API keys and client IDs. Kindly double check the API Key created and follow the script tag below.
If you're using the API under the standard plan, you must use a browser key (a type of API key) set up in a project of your choice.
Specify a key when loading the API
To specify a key, include it as the value of a key parameter when loading the API.
For example:
NOTE:
Google Maps APIs are available for Android or iOS apps, Web browsers, and via HTTP web services. APIs in each platform require a specific type of key. The Google Maps JavaScript API will only work with a Browser key. APIs of the same platform can use the same key.
Hope this helps.

Google Plus API - Keyinvalid

I am trying to use the javascript sdk to do an oauth login and access the google plus api. Basically the same code here: https://developers.google.com/api-client-library/javascript/features/authentication
In my firebug console, this is the url that is sending the api request to:
https://content.googleapis.com/discovery/v1/apis/plus/v1/rest?fields=servicePath%2Cresources%2Cparameters%2Cmethods&pp=0&key={key}
This is the error that comes back:
{"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}
I have:
1. Added Google Plus Api to my project
2. Created oauth credentials
3. Setup my consent screen
However, I am still getting the error.
The reason is that you have the key defined in the request. As specified in the discovery API docs (https://developers.google.com/discovery/v1/getting_started#before_starting):
"The APIs Discovery Service provides only public methods that do not
require authentication. In addition, unlike the requests you make to
many other Google APIs, the requests you make to the Discovery Service
API should not include an API key. If you do provide a key, the
requests will fail. This behavior helps ensure that you don't
accidentally disclose your API key when distributing tools that are
based on the Google APIs Discovery Service."
So you can solve the problem by removing the key from your request entirely.
If you are using Google's javascript client to do this and the error occurs when loading further APIs, you have to unset the key first:
gapi.client.setApiKey( null );
gapi.client.load( "plus", "v1", function( apiresponse ) { ... } );
If another function requires the key later, you have to set it again.
To avoid setting and unsetting the key constantly, I load all the needed APIs before authentication, then set the API key and thus will no longer have the issue.

Categories

Resources