FirestoreをREST APIで操作
Firestoreをプロジェクトに導入するには、通常公式ページのスタートガイド記載のクライアントライブラリをインストールします。
ただ、PHPに関してはgRPC拡張機能を別で導入したり、他の言語よりも手間がかかります。しかも、CentOS系のLinuxではC言語で書かれたソースをgit cloneしてコンパイルしないといけないという、超絶めんどくさい仕様となっています。
このため、今回LaravelからFirestoreを操作する方法として、REST APIを使ったやり方を採用しました。
PHPで書いてるプログラム部分だけ見たい方は、最後の方に記載していますので目次から飛んでください。
REST APIでFirestoreを操作する手順
REST APIで操作できるなら簡単かと思いきや、結構なハマりポイントがあります。REST操作するまでに必要な工程を記載しておきます。
- Firebaseプロジェクトのサービスアカウントを作成
- 作成したサービスアカウントからP12形式の鍵ファイルをダウンロード
- 鍵ファイルをP12からpem形式に変換
- Firestoreのルールを記載する (一番下の方に書いてます)
ここまでがブラウザ上での作業です。以下はプログラム内での工程です。
- 鍵ファイルを使ってJWTを作成
- JWTでOAuth認証しトークンを取得
- トークンを使ってREST APIを呼ぶ
これでようやくREST APIが呼べるようになります。このやり方をやってる人が少ないのか、WEB上にも情報が少なく、ドキュメントも見つけにくいので苦労しました…。
主な手順については下記公式ページに書かれています。
実際のコード例(Laravel/PHP)
JWTを作ってOAuth認証し、トークンを取得してREST APIを呼ぶまでの具体的なコードは下記です。
雑で申し訳ないですが、PHPを使ったREST API呼び出しで悩んでいる方には参考になると思います。成功するとFirestoreのcitiesコレクションの中身が取得できます。
public function test() { $http_client = new \GuzzleHttp\Client(); $now = time(); $header = array( 'alg' => 'RS256', 'typ' => 'JWT' ); $claim = array( 'iss' => 'yourapp@appspot.gserviceaccount.com', //ご自分のFirebaseサービスアカウントアドレス 'scope' => 'https://www.googleapis.com/auth/datastore', 'aud' => 'https://www.googleapis.com/oauth2/v4/token', 'exp' => $now + 3600, 'iat' => $now, ); //pem-keyファイルの読み込み $private_key = openssl_get_privatekey('file://' . base_path() . '/key.pem', 'passphrase'); //base64エンコード $header_base64 = base64_encode(json_encode($header)); $claim_base64 = base64_encode(json_encode($claim)); //鍵で署名 openssl_sign($header_base64 . '.' . $claim_base64, $signature, $private_key, 'sha256WithRSAEncryption'); $signature_base64 = base64_encode($signature); //JWT作成 $jwt = $header_base64 . '.' . $claim_base64 . '.' . $signature_base64; //JWTでOAuth認証、トークン取得 $response_token = $http_client->request( 'POST', 'https://www.googleapis.com/oauth2/v4/token', [ 'Content-Type' => 'application/x-www-form-urlencoded', 'form_params' => [ 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt, ], ] ); $token = json_decode($response_token->getBody())->access_token; //トークンを使ってREST API呼び出し $response = $http_client->request( 'GET', //ご自分のFirebaseプロジェクトID(yourapp)を指定してください, citiesコレクションをあらかじめ作成しておいてください 'https://firestore.googleapis.com/v1/projects/yourapp/databases/(default)/documents/cities', [ 'Content-Type' => 'application/x-www-form-urlencoded', 'headers' => [ 'Authorization' => 'Bearer ' . $token, ] ] ); return $response->getBody(); }
ちなみにFirestoreのルールですが、下のように書けばトークンによる認証が有効になり、read/writeできるようになります。重要なポイントとして、トークンの有効期限は最大1時間です。
service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if requests.auth.token.admin == true; } } }
JWTの作成とか、REST APIの詳しいドキュメントが見たい方は、下記ページに書かれているので参考にしてください。(基本英語です)
JWTの作り方↓
REST APIリファレンス(テスト実行も可能)↓
Firestoreのトークンを使ったルール記載方法について↓
コメント