0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Android×Google Calendar API】APIキーにアプリ制限をかける方法とヘッダー設定まとめ

はじめに

前回の記事では、APIキーだけで日本の祝日を取得する方法を紹介しました。
今回は、さらに安全に運用するため、GCP側でAPIキーにアプリ制限をかける方法と、
Android側で正しくヘッダーを設定する方法についてまとめます。

やりたいこと

特定のAndroidアプリからのみ Google Calendar API を呼び出せるように制限をかける

ハマりポイント

  1. 通信時にパッケージ名とフィンガープリントをヘッダーに載せる方法が分かりづらい
  2. APIキー、パッケージ名、フィンガープリントをソースコードにハードコーディングしない設計に悩む
  3. ヘッダーでのフィンガープリントは「:」不要

やったこと

  1. GCPコンソール上でアプリケーションの制限を実施

    • APIキーの設定画面で、アプリケーション制限を以下に設定
      「アプリケーションの制限」 → Androidアプリ
      「パッケージ名」(例: com.example.XX)
      「フィンガープリント」(例: XX:XX:XX:XX:...)
  2. Androidアプリ側でのAPIリクエスト実装

    • 通信時に、X-Android-Package と X-Android-Cert ヘッダーを付与するように実装
    • APIキーやフィンガープリントはハードコーディングせず、環境変数で管理

実装

APIリクエスト

    private val transport = NetHttpTransport()
    private val jsonFactory = GsonFactory.getDefaultInstance()
    private val androidKeyInitializer = HttpRequestInitializer{
        //TODO: APPLICATION_IDはContextからの取得が望ましい?
        request ->
        // X-Android-Package ヘッダ
        request.headers.set("X-Android-Package", BuildConfig.APPLICATION_ID)
        // X-Android-Cert ヘッダ
        request.headers.set("X-Android-Cert", BuildConfig.SHA1_FINGERPRINT.replace(":", "")) //":"を除去する必要がある。
    }

    private val calendar = Calendar.Builder(transport, jsonFactory, androidKeyInitializer)
        .setApplicationName(BuildConfig.APPLICATION_ID) //TODO: APPLICATION_IDはContextからの取得が望ましい?
        .build()

APIキー、パッケージ名、フィンガープリントの管理方法

  • APIキー管理(local.properties → BuildConfig)
    local.properties
GOOGLE_API_KEY = XXXXXXX

build.gradle.kts(Module :app)

val localProperties = Properties()
val localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()){
    localProperties.load(FileInputStream(localPropertiesFile))
}

android {
     buildFeatures{
        buildConfig = true
    }
    defaultConfig {
        buildConfigField("String", "GOOGLE_API_KEY",
            "\"${localProperties.getProperty("GOOGLE_API_KEY", "")}\"")
    }
}

→ こうすることで、ソースコードにAPIキーを直接書かずに管理できます。

  • フィンガープリント(SHA-1)の管理(BuildConfig)
    build.gradle.kts(Module :app)
android {
    buildFeatures {
        buildConfig = true
    }

    buildTypes {
        debug {
            buildConfigField(
                "String", 
                "SHA1_FINGERPRINT", 
                "\"XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX\""
            )
        }
        release {
            buildConfigField(
                "String", 
                "SHA1_FINGERPRINT", 
                "\"YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY\""
            )
        }
    }
}

→ Debug・Releaseそれぞれ別の証明書を使う場合にも対応できます!

注意点

  • BuildConfigへのキー定義はAPKに埋め込まれるので、APIキーにはIP制限やアプリ制限が必要。
  • セキュリティをさらに高めたい場合、Android Keystore、API Gatewayの導入や、サーバー経由でAPIを叩く方法があるらしい。

まとめ

  • GCP側でAPIキーに「パッケージ名+フィンガープリント」の制限をかける
  • Android側ではHTTPリクエストヘッダーに正しく情報を載せる
  • APIキーやフィンガープリントはコードに直書きしない方法。(APKの逆コンパイルによってKeyがバレる可能性はあり。)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?