You can secure you API Key (Google Cloud Console ->
Credentials)
- Create separate API keys for Web/Android/iOS/Backend.
- For web, you can secure it by
Application restrictions
usingHTTP referrers
, and fill inWebsite restrictions
on list of websites allowed. - You can further secure
API restrictions
by specifying which API this key could access.
The things is restriction via HTTP referrers
is not really secure, as people still could access it via empty or spoofed HTTP referrers
.
To secure Google Maps Static API (Web) from abuse, you need to use signed url.
First thing we want to do is disable access from unsigned url.
- Goto https://console.cloud.google.com/google/maps-apis/quotas, and select
Maps Static API
. - Expand
Unsigned requests (if URL signing secret is defined)
, and set the quota to ZEROUnsigned requests (if URL signing secret is defined) per day
: 0Unsigned requests (if URL signing secret is defined) per minute
: 0Unsigned requests (if URL signing secret is defined) per minute per user
: 0
If you try to load static maps without signature/signed (e.g. https://maps.googleapis.com/maps/api/staticmap?center=35.01856,135.68077&markers=35.01856,135.68077&zoom=16&size=370x300&key=YOUR_KEY&sensor=false
), it will show This site can't load Google Maps correctly
.
Now, you need to get URL Signing Secret
.
- Goto https://console.cloud.google.com/google/maps-apis/credentials, and select
Maps Static API
- Look under
URL Signing Secret
for the secret key.
Sign your URL (Python 2.7 example)
import hashlibimport hmacimport base64# import urllib.parse as urlparseimport urlparsedef sign_url(input_url, secret): if not input_url or not secret: raise Exception("Both input_url and secret are required") url = urlparse.urlparse(input_url) # We only need to sign the path+query part of the string url_to_sign = url.path + "?" + url.query # Decode the private key into its binary format # We need to decode the URL-encoded private key decoded_key = base64.urlsafe_b64decode(secret) # Create a signature using the private key and the URL-encoded # string using HMAC SHA1. This signature will be binary. signature = hmac.new(decoded_key, str.encode(url_to_sign), hashlib.sha1) # Encode the binary signature into base64 for use within a URL encoded_signature = base64.urlsafe_b64encode(signature.digest()) original_url = url.scheme + "://" + url.netloc + url.path + "?" + url.query # Return signed URL return original_url + "&signature=" + encoded_signature.decode()
GOOGLE_API_KEY = 'AIzaSyD1...'GOOGLE_MAPS_STATIC_URL_SIGNINING_SECRET = 'abc...'url = f"https://maps.googleapis.com/maps/api/staticmap?center=35.01856,135.68077&markers=35.01856,135.68077&zoom=16&size=370x300&key={GOOGLE_API_KEY}&sensor=false"# the final url will have a 'signature' parameterurl = signed_url(url, GOOGLE_MAPS_STATIC_URL_SIGNINING_SECRET)
References: