Laravel と Firebase Authentication 連携で躓いた

## はじめに
Laravelを使った個人開発をしており、詳しくはこの記事でまとめています。

https://qiita.com/Sangwoo-Oh/items/3dcbb9658c9c5537bce9

今回の開発では認証機能にFirebase Authenticationを採用し、バックエンドアプリからFirebaseに接続する必要がありました。公式のFirebase Admin SDKはPHPをサポートしておらず、サードパーティSDKであるkreait/firebase-phpを利用しました。
FirebaseにこのSDKを通じて連携をする上で、躓いたポイントを忘れないように記録しておきたいと思います。

## 開発環境
- OS バージョン
    - Windows 11
- バックエンド
    - Laravel 11.41.3

## 手順と生じた問題
### 1. SDKとLaravel用のpackageをインストール
SDKのgithubページのREADMEを参考にインストールします。
https://github.com/kreait/firebase-php
https://github.com/kreait/laravel-firebase
```
composer require kreait/firebase-php 
composer require kreait/laravel-firebase
```

### 2. SDKの設定ファイルを公開
以下のコマンドでconfig配下にfirebase.phpがコピーされます。カスタム設定ができますが、この記事では特に編集しません。
```
php artisan vendor:publish --provider="Kreait\Laravel\Firebase\ServiceProvider" --tag=config
```

### 3. サービスアカウントの秘密鍵をダウンロード
Jsonフォーマットの秘密鍵をプロジェクトコンソールのサービスアカウントタブからダウンロードできます。サービスアカウントを作成していない場合は、まず作成する必要があります。

ダウンロードできたら、ファイル名をfirebase-auth.jsonに変更し、storage/app/配下に設置します。セキュリティセーフのため、gitignoreに追加します。

### 4. 環境変数を設定
.envファイルに3で設置したJsonファイルの絶対パスの環境変数を設定します。
```plaintext:.env
FIREBASE_CREDENTIALS=storage/app/firebase-auth.json
```

### 5. Firebase認証用のコントローラーを用意
```php:FirebaseUserController.php
<?php

namespace App\Http\Controllers;

use Kreait\Laravel\Firebase\Facades\Firebase;

class FirebaseUserController extends Controller
{
    protected $auth;

    public function __construct()
    {
        // authコンポーネントのインスタンスを格納
        $this->auth = Firebase::auth();
    }

    public function getAllUsers()
    {
        // Firebaseプロジェクトに登録されている全ユーザーを取得
        $users = $this->auth->listUsers();
        return response()->json($users);
    }
}

```
api.phpにルーティングを追記します。
```php:api.php
...
use App\Http\Controllers\FirebaseUserController;
...
Route::get('/users',[FirebaseUserController::class, 'getAllUsers']);
```
### 6. 動作確認
Firebaseコンソールから[Authentication]->[ユーザーの追加]でテストユーザーを作成します。
ローカルサーバーを起動し、ブラウザやPostmanで先ほどのAPIエンドポイントにアクセスしてみます。これで作成したテストユーザーが返ってきたら連携成功です。

http://127.0.0.1:8000/api/users にGETリクエスト

すると、空のJsonが返ってきます。
```
{}
```
エラーも出ていないし、レスポンスが返ってきてるので、Firebaseとの連携はできているはずです。ここで原因がわからずドキュメントとにらめっこしていると、listUsers()は配列ではなく、Generatorを返すと書いてありました。
そのため、foreachなどでデータを生成し、新たな配列を返す必要がありました。
> To enhance performance and prevent memory issues when retrieving a huge amount of users, this methods returns a `Generator`.

https://firebase-php.readthedocs.io/en/7.16.1/user-management.html#list-users
```php:FirebaseUserController.php
public function getAllUsers()
{
    $users = $this->auth->listUsers();
    // foreachで各ユーザーデータをGenerate
    $array_users = [];
    foreach ($users as $user) {
        $array_users[] = $user;
    }
    return response()->json($array_users);
}
```
これでユーザーデータを取得することができました！


### 7. 他の取得メソッド（queryUsers()）
ドキュメントに記載のqueryUsers()でも取得できるか試してみます。UserQueryの値で取得条件を設定できます。
https://firebase-php.readthedocs.io/en/7.16.1/user-management.html#query-users

```php:FirebaseUserController.php
...
use Kreait\Firebase\Auth\UserQuery;
...
public function getAllUsers()
{

# Building a user query object
$userQuery = UserQuery::all()
    ->sortedBy(UserQuery::FIELD_USER_EMAIL)
    ->inDescendingOrder()
    ->withLimit(499); # The maximum supported limit is 500
}
$users = $auth->queryUsers($userQuery);
```
同じく、http://127.0.0.1:8000/api/users にGETリクエスト

すると、別のエラーが出ました。
> Kreait\Firebase\Exception\Auth\AuthError
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)

原因としては、リクエストの際に、FirebaseからSSL証明書を受け取り、その証明書が認証局によって発行されたかどうかものかどうかをCA証明書バンドルというものを使って確認します。しかし、Windows環境ではその証明書バンドルを手動で設定する必要があるため、それが見つからないというエラーです。

下記サイトから最新のcacert.pemをダウンロードし、

https://curl.se/docs/caextract.html

下記フォルダに保存します。

```
{phpのインストール先パス}/php-8.3.13-Win32-vs16-x64/extras/ssl/
```

またphp.iniのcurl.cainfoをコメントアウトし、cacert.pemまでの絶対パスを設定します。
```php.ini
curl.cainfo="{phpのインストール先パス}\php-8.3.13-Win32-vs16-x64\extras\ssl\cacert.pem"
```

ローカルサーバーを再度立ち上げます。

すると、今度はユーザーが取得できているはずです。

## 参考記事

https://github.com/kreait/laravel-firebase

https://github.com/kreait/firebase-php

https://firebase-php.readthedocs.io/en/7.16.1/index.html

https://qiita.com/maguro_tuna/items/4b3ecd7502e218f103ca