GAE/Go 2nd genでFirebase SDKを利用する際の注意点

timakin
4 min readDec 5, 2018

--

これは本当に軽微なメモなんですが、GAEでGo1.11を使うために移行をしたことで、認証が動かなくなっていることに気づくのが遅れてしまいました。他の人がそうならないように記録しておきます。

これまで

仮にGAE/GoでFirebaseの認証機構を使っていたとして、今までだとGAE/GoでのFirebaseクライアントの初期化はこのようにすればよかった。

もっと詳細に書くと、AppEngineのcontextを含んだ状態でurlfetchを呼び出してさえいれば、Firebaseのサービスアカウントの情報を明示的に指定しなくてもよかった。

opt := option.WithHTTPClient(urlfetch.Client(ctx))
app, err := firebase.NewApp(ctx, nil, opt)
if err != nil {
...
}

これから

GAE/Goが2nd genに移行することになって、コードの置き換え作業の中で urlfetch を消さなくちゃいけなくなる。ここで、ただのAPIクライアントだったらHttpClientのTransport設定からurlfetchを外すだけでよかった。

しかし、Firebaseに限ってはそうではなく、認証情報をurlfetch経由で渡せなくなるので、サービスアカウントの情報を何らかの手段でオプションとして渡してあげないといけない。

ただ、サービスアカウントのJSONファイルをそのままどっかに置いて、それを読み込ませるのもあれなので、なんとかシークレットな環境変数として渡せないか?と考えた結果以下のようにすれば動く。

まずapp.yamlで環境変数の設定をする。

service: api
runtime: go111

# 以下はsecrets.yamlか何かを作ってincludeする
env_variables:
FIREBASE_SERVICE_ACCOUNT_JSON: |
{
"type": "service_account",
"project_id": "xxxxxxx",
...
}

次にFirebase SDKの呼び出し箇所。

creds, err := google.CredentialsFromJSON(ctx, []byte(os.Getenv("FIREBASE_SERVICE_ACCOUNT_JSON")))
if err != nil {
...
}
opt := option.WithCredentials(creds)
app, err := firebase.NewApp(ctx, nil, opt)
if err != nil {
...
}

つまり、 golang.org/x/oauth2/google を使ってJSONのblobを元にクレデンシャルを読み取ってオプションとして渡してあげれば、Firebaseに対してリクエストを投げられる。もともとGAEじゃなかった人はこうやってるかもしれないけど、少なくともGAE/Goの2nd genに移行する際には遭遇する問題かと思われる。

まとめ

GAE/Go 2nd genの移行に伴い、Firebaseの移行方法は公式のドキュメントにあまり明確に書かれていなかった(気がする)ので、ちゃんと意識しつつ、出来るだけ取り回しがしやすいようにJSONを環境変数から読み取って渡すとかした方が便利。

追記

JSONをどっかに書いて読み込ませるとか書いてたけど、別にDefaultCredentialsを取得できるっぽいので、そっちを使った方が良さそう。皆々様ご知見感謝です…!(2nd genだとできないと思って慌ててた)

--

--