🗺️

Google Maps PlatformのClient ID廃止に備えよう〜APIキーへの移行〜

に公開

はじめに

以前からアナウンスされていましたが、Google は今後、すべての Google Maps Platform サービスで Client ID を廃止し、API キーの使用を必須とする方針を発表しています。

本記事では、Client ID から API キーへの移行について、実際に私たちが検討した内容や実装方法を共有したいと思います。同じような移行作業に直面している方の参考になれば幸いです。

Client ID と API キーについて

2018年以降にGoogle Maps Platform を契約している場合、APIキーしか発行できなくなっています。Client ID は、それ以前にGoogle Maps APIを利用していた場合に発行されているレガシーな認証方法です。

Client ID

https://developers.google.com/maps/premium/authentication/client-id/url-authorization?hl=ja

Client ID(gme-* 形式)は、以下のような特徴を持っています。

  • ホワイトリスト方式:利用できるウェブサイトやドメインを事前に登録
  • 規則性のある文字列gme-companyname のような予測しやすい形式
  • 基本的に脆弱:文字列自体にセキュリティ機能がなく、利用箇所に応じた細かいアクセス制御もできない

API キー

API キーは MFA や OAuth2、パスキーのようなユーザー認証とは異なり、アプリケーション認証 のための仕組みになります。API キーは以下の役割を持っています:

  • アプリケーションの識別:「誰が」ではなく「どのアプリケーションが」リクエストしているかを識別
  • 1つのプロジェクトから複数発行可能:用途や制限に応じて異なるキーを発行・割り当てして運用
  • 予測しにくい文字列 : AIza から始まるという規則はありますが、それ以外には予測しにくいランダムな文字列
  • アクセス制御:HTTP リファラーや IP アドレスだけでなく、利用可能なAPIの種類による制限も可能

Client ID から API キーへの移行

冒頭で紹介した通り、Client ID のサポートは終了予定となっています。具体的には、すでに非推奨となっており(2025年5月26日)、2026年5月31日以降は使用できなくなるようです。

そのため、上記のタイムリミットまでに Client ID から API キーへの移行が必要になります。

さて、Google Maps Platform の利用は、ざっくり分けると次の2つです:

  1. 地図の読み込み・表示:地図を表示し、マーカーやポリラインを描画
  2. APIを呼び出す:ジオコーディングやルート検索などの API を利用

それぞれのパターンで、移行時の考慮事項が異なります。順番に見ていきましょう。

地図表示(Maps JavaScript API)の移行

地図を表示するには「Maps JavaScript API」を使います。基本的な使い方としては、通常は以下のような script タグを宣言します。

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>

ただ HTML に直接埋め込むと、誰でも API キーを見ることができてしまいますし、Git でコード管理する上でも、API キーをそのままコミットするのは少し抵抗があります。

そこで、私たちのチームでは React/Vue3 と Vite を使って地図アプリケーションを開発しているので、Vite で標準提供されている dotenv で環境変数から読み込まれるようにしました。

https://ja.vite.dev/guide/env-and-mode

各自のローカル環境でビルドやデプロイする場合は、開発用と本番用の .env ファイルを用意してもらいます。これらのファイルは間違ってコミットされないよう、.gitignore に追加しましょう。

.env.development
VITE_GOOGLE_MAPS_API_KEY=AIza.........
VITE_ENV=development
.env.production
VITE_GOOGLE_MAPS_API_KEY=AIza.........
VITE_ENV=production

GitHub ActionsのようなCI/CD環境からビルドやデプロイする場合は、Secrets and variablesに値を登録しておき、ワークフローファイルで取得するようにしておきます。

.github/workflows/deploy.yaml
// 略
env:
  VITE_GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
// 略

続いて地図の読み込み、つまり上記の環境変数の参照側も対応します。
ここはアプリケーションの技術スタックにあわせて提供されているライブラリを利用するのがよいと思います。
本家のページではJavaScript APIで汎用的に使えるローダーとして js-api-loaderが紹介されていますが、例えばVue3の場合、vue3-google-mapを利用するとより簡単に利用できるので、今回はこちらを使います。

Map.vue
<template>
  <div style="height: 100%">
    <GoogleMap
      :api-key="googleMapsApiKey"
      style="width: 100%; height: 100%"
      :center="mapCenter"
      :zoom="mapZoom"
    >
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { GoogleMap } from 'vue3-google-map';

const googleMapsApiKey = import.meta.env.VITE_GOOGLE_MAPS_API_KEY || 'your-google-maps-api-key';
const mapCenter = ref({ lat: 35.670651, lng: 139.771861 }); // Tokyo
const mapZoom = ref(10);
</script>

Vite では環境変数を import.meta.env で使用する仕様となっているので、環境変数から値を取得します。

また開発時と本番ビルド時で使用するAPIキーを使い分けるために、 package.json では以下のようにしています。

package.json
{
  // 略
  "scripts": {
    "dev": "vite --mode development",
    "build": "NODE_ENV=production vite build"
  }
  // 略
}

それ以外のAPI呼び出しの移行

ジオコーディングやルートなどのAPI呼び出しに関しては、特に事情や制約がなければ、各言語ごとに提供されているクライアントライブラリを利用するのがよいでしょう。

認証方式として Client ID を API キーに切り替えればOKです。
Javaの場合は以下のように変更します(ジオコーディングAPIの場合)

GeoApiContext context = new GeoApiContext.Builder()
-         .enterpriseCredentials("gme-xxxxxx", "secret")
+         .apiKey("AIza.......")
          .build();

移行時の注意点とTips

移行にあたって調査・検討・確認したことを紹介します。
対応する場合、本記事の一番下の参考リンクにある移行ガイドやベストプラクティスには必ず目を通し、対応方法を考えましょう。

APIキーはどの単位で発行・管理するか?

使用しているコンポーネント/サービス/テナントなどによってAPIキーを分けたほうが、問題があった場合の影響範囲を局所化できて都合がよさそうです。そこでAPIキーはどれくらいの単位で分けて運用するのがよいかを考えました。

前提としてAPI キーには プロジェクトあたり300個 という上限があります。
それ以上必要な場合は、複数のプロジェクトに分けることもできるようなため(未確認)、理論上はかなり細かな割り当てをする運用もできるみたいです。

私たちのチームでは、運用・管理の容易性とのトレードオフを考慮し、以下のような括りでAPIキーを発行することにしました。

  • ローカル開発用
  • バックエンド(開発環境)
  • バックエンド(本番環境)
  • 地図画面用(開発環境) Aサイト
  • 地図画面用(本番環境) Aサイト
  • 地図画面用(開発環境) Bサイト
  • 地図画面用(本番環境) Bサイト

Maps JavaScript APIでAPIキーがユーザーから見えてしまう?

APIキーはその名からわかるとおり秘密にしたい文字列ですが、Maps JavaScript APIを使っている場合、マップを読み込む時にネットワーク通信が発生するので、ブラウザの開発者ツールからその通信内容を見ることで key の値も確認できてしまいそうです。

これはついては、ユーザーに対しAPIキーの秘匿性を完全に保つことは難しく、仕方ないと割り切ることにしました。
対策として HTTPリファラーを公開サイトのものだけに制限するのを徹底 することにより、他のサイトでの API キーの流用ができないようにしました。

万が一キーが漏れたり悪用されたらどう対処するか?

Google Maps Platformコンソールでは、APIキーごとに利用状況をモニタリングすることが可能なため、適切にAPIキーを分けておくことで、不正利用されているキーの検知の足がかりにできます。

キーの悪用に対し、私たちも今のところ、APIキーの利用状況をモニタリングし、悪用されたキーについては無効化やローテーションを行い、新しいAPIキーで再デプロイする、という方法で備えることにしています。
より柔軟かつ堅牢にやる方法として、APIキー自体を定期的にローテーションすると共に、APIキーを安全なサーバーから動的に取得する方法も検討中です。

APIキーのHTTPリファラーの設定

APIキーのリファラーではワイルドカードを使うことはできますが、ワイルドカードは複数階層には使えません。
例えば https://*.example.com/* のように指定すると、 https://foo.example.com/123 には適用されますが https://foo.bar.example.com/456 には適用されません。サブドメインごとに個別に登録する必要があります。

HTTPリファラーは複数登録することが可能なので、過不足なく登録しておくようにしましょう(なお、登録数の上限についてはっきり明言された資料は見つけられませんでした…)

ベストプラクティスに沿ったHTTPヘッダーの利用

APIキーに移行した場合でもURLにAPIキーをクエリパラメータとして渡す方法だと、URL スキャンによってキーが盗難に遭う可能性があります。
そこで Google は x-goog-api-key ヘッダーの使用を推奨しています。

https://cloud.google.com/docs/authentication/api-keys-use?hl=ja

残念ながら私たちが使っている google-maps-services-java ではこのヘッダに対応していないようでした。

おわりに

Client ID を使っている場合、APIキーへの移行は必須です。
Google Maps Platform の API キーは、MFA や OAuth2、パスキーが提供するようなユーザー認証レベルのセキュリティとは性質が異なりますが、Google が提供する「API キーの制限」などのベストプラクティスを遵守し、適切に管理することで、実用上十分なセキュリティを確保できるように設計されています。
セキュリティ対策を適切に講じる観点でも、早めに備えておきましょう。

参考リンク

株式会社キャリオット

Discussion