【Android×Google Calendar API】APIキーにアプリ制限をかける方法とヘッダー設定まとめ
はじめに
前回の記事では、APIキーだけで日本の祝日を取得する方法を紹介しました。
今回は、さらに安全に運用するため、GCP側でAPIキーにアプリ制限をかける方法と、
Android側で正しくヘッダーを設定する方法についてまとめます。
やりたいこと
特定のAndroidアプリからのみ Google Calendar API を呼び出せるように制限をかける
ハマりポイント
- 通信時にパッケージ名とフィンガープリントをヘッダーに載せる方法が分かりづらい
- APIキー、パッケージ名、フィンガープリントをソースコードにハードコーディングしない設計に悩む
- ヘッダーでのフィンガープリントは「:」不要
やったこと
-
GCPコンソール上でアプリケーションの制限を実施
- APIキーの設定画面で、アプリケーション制限を以下に設定
「アプリケーションの制限」 → Androidアプリ
「パッケージ名」(例: com.example.XX)
「フィンガープリント」(例: XX:XX:XX:XX:...)
- APIキーの設定画面で、アプリケーション制限を以下に設定
-
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がバレる可能性はあり。)