fluttergoogle-mapsgoogle-places-api

Flutter Google Places API Authorization Error


I have a Flutter application that utilizes Google Maps for displaying maps and making calls to the Places API to retrieve nearby stores based on the user's location. During development I did not restrict the API keys but now that I want to move to production I restricted both the Android and iOS keys

Here's how I make the call to the Places API:

final String apiUrl =
    "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${cords.latitude}%2C${cords.longitude}&radius=$radius&type=$type&key=$apiKey";
final response = await http.get(Uri.parse(apiUrl));

I tried to restrict the API keys for iOS and android (1 key for each app). The map is shown properly but the calls to the places API return the following error:

{
   "error_message" : "This IP, site or mobile application is not authorized to use this API key. Request received from IP address x.x.x.x, with empty referer",
   "html_attributions" : [],
   "results" : [],
   "status" : "REQUEST_DENIED"
}

After searching for quite some time, I found a Stack Overflow post suggesting that some google maps APIs are designed to be called from a backend system rather than directly from the frontend. Here's the link to the post for reference: Android Google Maps Direction Api - Api key restriction not working

It got me thinking maybe it would be the case for me as well. Based on the provided link by the user it turns out it actually is... (Please let me know if I am mistaken)

Picture from maps FAQ showing the way to restrict Places API

Which keys or credentials should I use for different Maps products?

I'm considering modifying the way I call the Places API. Since I already use Firebase, I'm thinking of triggering a Cloud Function to make the Places API call and then forwarding the JSON response to the client phone. However, I'm unsure whether I should restrict the API key for the Cloud Function.

My questions are:

If you believe I could tackle this issue in another way please let me know, I also noticed on the table that there are entries for Places SDK for android and iOS that can be restricted to application but I don't know if it suits my case because I am using flutter.

Things to clarify:

Any suggestions or insights would be greatly appreciated. Thank you in advance.


Solution

  • What I ended up doing was actually using a callable cloud function since I was already using firebase and I implemented App Check to make sure only my apps can trigger that function and also to keep the api key secure, I used the google cloud secret manager.

    It also a good practice and suggested to restrict it to the specific API's you want to use

    For anyone interested on how to secure sensitive information, Cloud Functions for Firebase integrates with Google Cloud Secret Manager.

    https://firebase.google.com/docs/functions/config-env?gen=2nd#create-secret

    export const fetchFromGoogleMaps = functions.onCall({
      secrets: ["secret_name"],
      enforceAppCheck: true,
    }, async (request) => {
      const apiKey = process.env.secret_name;
    
      const apiUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&type=${type}&key=${apiKey}`;
    
      return await axios.default.get(apiUrl).then((apiResponse) => {
        // ...
      }).catch((error) => {
        // handle the error
      });