Supabaseの認証をFirebaseのトークンでやってみようとして挫折した

## 挫折しました。。。
セキュアなアプリを目指して、Supabaseの RLS (Row Level Security) を活用し、ログイン状態に応じてデータベースの参照・操作を制限しようとしました。

Supabase RLSは、Supabase Auth を使えば簡単に設定できるようですが、今回のアプリではすでに Firebase Auth を導入済み。
そこで、Firebaseの認証を維持したまま、Supabase RLS を適用する方法を模索しました。

## 環境
- フレームワーク: Nuxt.js (Vue)
- 認証: Firebase Authentication
- データベース: Supabase

## 開発の流れ
まずはSupabase RLSを使用して一番簡単であろう"ログイン中のユーザーはSELECTでデータを参照できる"を目指します。
1. rls_testというテーブルにユーザーがログインしていたらSELECTできるというポリシーを作成
2. supabaseの認証にfirebaseを追加
3. firebaseに対してcloud functionでrole: "authenticated"を設定
4. SupabaseClient初期化時にfirebase tokenを設定する
5. テーブルをSELECTしてみる

## 結果、SupabaseClient初期化時にfirebase tokenを渡せず失敗
1,2,3はうまく設定できました。
[公式ドキュメント](https://supabase.com/docs/guides/auth/third-party/firebase-auth)を参考にしつつ、実装のイメージが全くついていなかったFirebaseのcloud functionでのroleの設定も確認できました。
4も実装し5で対象テーブルのデータを取ろうとしましたが、取れていない、、、。
RLSポリシーを無効化するとテーブルのデータが取得できるので問題は4にありそうです。

**残念ながら、今回達成できたのはここまででした。**
Firebaseのcloud functionでrole: "authenticated"を設定後、4のSupabaseClientをfirebase token付きで初期化しようとしましたが、ログで確認したところ、初期化したSupabaseClientの中にaccessTokenがありませんでした。

実際のコード
```ts
const supabase = createClient<Database>(
  runtimeConfig.public.supabaseUrl,
  runtimeConfig.public.supabaseKey,
  {
    accessToken: async () => {
      return await user.value?.getIdToken(true) ?? null
    },
  }
)

console.log(supabase)
```

console.logしている箇所の出力結果

```json
SupabaseClient {supabaseUrl: 'https://xxxx.supabase.co', supabaseKey: 'xxx', realtimeUrl: ...
accessToken: async () => {…}
    length: 0
    name: "accessToken"
    arguments: (...)
    caller: (...)
```
**accessTokenのlengthが０なので設定ができていないようです。**
argumentsとcallerにはこのようなエラー分が出力されていました。
```
arguments
: 
[Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at accessToken.invokeGetter (<anonymous>:3:28)]
```
上記のことから、accessTokenが設定できていなそうだと予想しております。


#### ちなみに今回設定したSupabase RLSのポリシーは以下です。
using trueとすることで、RLS を有効にしつつ、とりあえず「誰でも参照できる」状態にしてテストしています。

```sql
alter policy "Enable read access for all users"
on "public"."rls_test"
to public
using (
  true
);
```
(※RLSを無効にするとテーブルは参照できることを確認済み)

## エラー解決に向けて試したこと
1. Supabaseのバージョンを確認・更新
@supabase/supabase-js のバージョンが古い可能性があるため、最新版へ更新してみる
```npm update @supabase/supabase-js```
→ 変化なし。エラーは依然発生。

2. SupabaseClientのaccessToken オプションの指定方法を変更
createClientのaccessTokenオプションが非同期関数 (async () => {})のままで期待通りに動作していない可能性を考え、明示的にawaitで取得したトークンを渡すように変更しました。
```ts
const token = await user.value?.getIdToken(true);
const supabase = createClient<Database>(
  runtimeConfig.public.supabaseUrl,
  runtimeConfig.public.supabaseKey,
  { accessToken: token }
);
```
→ 依然として accessToken が設定されていない。

3. Supabase の auth.exchangeCodeForSession を試す
AIに相談すると違う方法でaccessTokenを付与する方法も提案されました。
auth.signInWithIdToken を使用することで、FirebaseのtokenをSupabaseに渡す方法もあるみたいです。
```ts
const token = await user.value?.getIdToken(true);
const { error } = await supabase.auth.signInWithIdToken(token);
if (error) console.error("Sign-in error:", error);
```

他にもsetTimeoutで数秒待ってみたり、エラーでググりまくりましたが有効な解決手段が見つからず断念。

## 今後どうしていくか
今回はNuxt.jsのアプリの中で全てのコードを書いていました。
Firebaseのcloud functionを使用し、完全に別サーバーで試してみようかとも思っています。


## 最後に
**今回の挑戦は、悔しい結果に終わりました。**
公式サイトもあり仕組み的にもアンチパターンでないため悔しいですね。
調査スキルを上げていきたい次第です。
公式ドキュメントの読み込みや、Cloud Function の設定方法を学べたことは大きな収穫でした。

**最後まで読んでいただきありがとうございました。**