【Laravel/PHP】JWT認証でFirestoreをREST API操作する

スポンサーリンク

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上にも情報が少なく、ドキュメントも見つけにくいので苦労しました…。

主な手順については下記公式ページに書かれています。

Cloud Firestore REST API の使用  |  Firebase

実際のコード例(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の作り方↓

サーバー間アプリケーションに OAuth 2.0 を使用する  |  Authorization  |  Google for Developers

REST APIリファレンス(テスト実行も可能)↓

Google APIs Explorer  |  Google for Developers
Google API Explorer は、さまざまな Google API をインタラクティブに操作できるツールです。

Firestoreのトークンを使ったルール記載方法について↓

Security Rules | Full-Stack Firebase

未経験、異業種からIT業界に転身。フロントエンジニア。主にJavascript(React.js)をつかったWEBアプリ開発にたずさわる。
お問い合わせ、ご相談など → genpsp10@gmail.com

psp7をフォロー
プログラミング
スポンサーリンク
psp7をフォロー
ハトらぼ

コメント