I've created a Google API key and using it to show maps in my Android application. For security reasons it is recommended that we should apply restrictions to the API so attackers cannot use it easily.
So I applied restrictions like below image:
And my app works perfectly with current restrictions. Now when I'm trying to access maps with this request (via browser):
https://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=600x300&maptype=roadmap&key=AIxxxxxxxxxxxxxxxxxxxxxxxx&signature=6d2cd94cb942dcc8da184cb28cf0e1a0f53e5837
Where key is my real API key but the signature is a totally random SHA1 it gives me this error:
The Google Maps Platform server rejected your request. Unable to authenticate the request. Provided 'signature' is not valid for the provided API key, or the provided 'key' is not valid.
Which makes sense, since it's not my application SHA1 and also Im accessing GoogleMap API with web browser not with an Android app.
However if I remove the signature query parameter from request It works. Now if someone decompile my app and grab the API key from app's AndroidManifest file, he can easily use this key to make a lot of API requests and abuse my key. It appears that this restrictions doesn't work or am I misunderstood something? How can I restrict this key to be only usable with my Android app?
I can't seem to find documentation to confirm, but based on my experience, Google's key restrictions (by IP address, referrer, Android app, etc.) don't work for Google Static Maps. As you have noted, even though you have restrictions set up, you can still access static maps via a browser when you omit the signature.
That means the only way to secure Static Maps is with a signature. Google Static Maps allows you to access with or without a signature.
With signature: if you include a signature parameter, then it must be correct. A correct signature is unique for each static map URL you're trying to access, and how to generate this signature is documented here: https://developers.google.com/maps/documentation/maps-static/digital-signature#sample-code-for-url-signing
Note that the signature is generated by hashing the URL with a secret key which is generated in your Google Cloud console: https://developers.google.com/maps/documentation/maps-static/digital-signature#get-secret
You should generate the entire URL, including the signature, on your server (not in your app code) where the secret key can be kept... secret.
Without signature: if you omit the signature parameter, signature validation is bypassed, and as you rightly pointed out, anyone who can see your unsigned static map URL can steal the key to generate other static maps (or use the key for other services, unless you've enabled restrictions).
To limit damage potential, there is a default 25,000 per day limit on unsigned access. This limit can be changed (including to 0, which is effectively making signatures mandatory for your key) as described here: https://developers.google.com/maps/documentation/maps-static/digital-signature#limit-unsigned-requests