sm7
sm7

Reputation: 669

How to restrict API Key when calling the Reverse Geocoding API from Browser?

I am using Google Reverse Geocoding API from Browser.

The API works fine when using API Key with no restriction. For example: https://maps.googleapis.com/maps/api/geocode/json?key=API_KEY_WITH_NO_RESTRICTION&latlng=41.8857156,-87.64823779999999 - OK

But as I am calling the API from the browser, I would like to restrict the API Key, preferably request originating from certain domains.

Now, as per the restriction guideline, HTTP Referer restrictions won't work for the Geocoding API (one of the Google Web Service API). It returns error "API keys with referer restrictions cannot be used with this API." in such case!

The other option is to use IP address restriction. But it seems to be more suited if the call was originating from the server. In that case server address could be added in the restriction.

How can I secure (restrict) the API Key if I want to continue to call the Geocoding API from the browser?

Upvotes: 4

Views: 3851

Answers (1)

sm7
sm7

Reputation: 669

I figured out that I have to use Maps Javascript API in order to be able to call the Reverse Geocoding (Address Lookup) from browser (client) with HTTP Referer restrictions in place for the API Key.

In my initial implementation I used fetch(requestUrl) from the browser as it seemed very convenient and ended up with the above problem.

Example (using TypeScript):

  1. Enable Maps Javascript API

  2. Install required packages

npm install @googlemaps/js-api-loader
npm i -D @types/google.maps
  1. reverseGeo.ts
import { Loader } from '@googlemaps/js-api-loader';

const loadScript = async (): Promise<void> => {
  const loader = new Loader({
    apiKey: API_KEY_WITH_REFERRER_RESTRICTION,
    version: 'weekly',
  });

  await loader.load();
};

export async function reverseGeo(
  lat: number, long: number
): Promise<string> {
  await loadScript();
  const geocoder = new google.maps.Geocoder();

  const latlng = {
    lat: lat,
    lng: long,
  };

  try {
    const { results } = await geocoder.geocode({ location: latlng });
    if (results && results[0]) {
      return results[0].formatted_address;
    }
  } catch (e) {
    // handle exception
  }

  throw new TypeError('Zero result or reverse geo Failed'); // or handle other way
}
  1. reverseGeo.spec.ts
import { reverseGeo} from './reverseGeo';

it('should test reverseGeo', async () => {
  console.log(reverseGeo(22.5726, 88.3639));
});

Upvotes: 5

Related Questions