🐕

Firebase authのログイン情報はindexedDBの保存されている

2021/08/17に公開

Firebase authenticationを最近触っている。

create-react-appでローカルで動くアプリでfirebase packageを導入してみると、ログイン状態が保持されるので、ブラウザのどこかで保存されているのはわかった。

ブラウザのログイン情報がどこに保存されているのか気になって調べた。

indexedDB

https://github.com/firebase/firebase-js-sdk/issues/2903#issuecomment-613577822

Local persistence is the default for a worker environment. In a worker environment, indexedDB is used. You don't even need to specify it. Can you try again without specifying it? If that works, we can fix this so it works when it is explicitly specified in that environment.

https://groups.google.com/g/firebase-talk/c/wgSvjniKPQI?pli=1

Firebase Auth migrated from localStorage to indexedDB (for LOCAL persistence) starting from version 4.12.0.
The reason for doing so are many. Among them:

  1. Supporting indexedDB will make Firebase Auth usable in service workers and web workers.
  2. indexedDB is better supported and more reliable in many environments such as Cordova/Ionic, chrome apps, etc.

local persistenceというのがあって、永続性が保たれるようになってるらしい。
なんか色々あって、indexedDBへうつったようだ。そして、

indexedDBとはこちらに詳しい。

https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API

IndexedDB は、ファイルや blob を含む構造化された多くのデータを保存する、クライアントサイドのローレベル API です。この API は高パフォーマンスなデータの検索を行うために、インデックスを使用します。Web Storage は比較的少量のデータを保存するのに有用ではありますが、構造化された非常に多くのデータを扱うには不十分です。IndexedDB が解決策を提供します。

IndexedDB は SQL ベースの RDBMS に似たトランザクショナルデータベースシステムですが、SQL ベース の RDBMS が固定された列を持つテーブルを使用するのに対して、IndexedDB は JavaScript ベースのオブジェクト指向データベースです。IndexedDB では、キーでインデックス付けされたオブジェクトを保存および取り出すことができます。Structured Clone アルゴリズム (en-US)がサポートする、任意のオブジェクトを保存できます。データベースのスキーマを定義する、データベースへの接続を確立する、そして一連のトランザクションでデータの取り出しや更新を行うことが必要です。

「オブジェクト指向データベース」というものらしい。

indexedDBのチュートリアル

こちらでチュートリアルができる

indexedDBを使ってどういう動作をするか

https://firebase.google.com/docs/auth/web/auth-state-persistence?hl=ja

公式サイトに詳しい。

IDTokenとして取得可能

ログイン後の画面で以下のボタンをおいてみると値を取得可能

        <a href="#show" onClick={this.showIDToken}>
  showIDToken = (event) => {
    // IDトークンを試しにとる
    console.log("IDtoken取得");
    firebase
      .auth()
      .currentUser.getIdToken(/* forceRefresh */ true)
      .then(function (idToken) {
        // Send token to your backend via HTTPS
        // ...
        console.log("idToken");
        console.log(idToken);
      })
      .catch(function (error) {
        // Handle error
      });
  };

整理

https://firebase.google.com/docs/auth/admin/verify-id-tokens

Firebase クライアント アプリがカスタム バックエンド サーバーと通信する場合、そのサーバーに現在ログインしているユーザーを特定する必要が生じる場合があります。これを安全に行うために、正常なログイン後、ユーザーの ID トークンを HTTPS を使ってサーバーに送信します。次に、サーバー上で ID トークンの完全性と信頼度を確認し、ID トークンの uid を取得します。サーバーで現在ログインしているユーザーを安全に特定するために、この方法で送信された uid を使用できます。

Firebaseで認証するとIndexedDBにログインしたユーザー情報が保存される。stsTokenManager.accessTokenのようにAccessTokenも入っている。 firebase.auth().currentUserからID Tokenとして取得もできる。このID トークンは、バックエンドシステムが、Firebase Adminを介してuidを取得するのに利用される。

関係ありそうなリンク

localStorageはjsで読み込めるので、攻撃者がスクリプトにより任意のJSコードを実行して攻撃を目論むXSSによって、トークン格納していると盗まれる。

https://www.youtube.com/watch?v=PKPj_MmLq5E

上の動画、OAuthについて学べる。
アクセストークンがリソースサーバーがクライアントアプリの権限を確認する仕組み。

参考

https://rara-world.com/firebase-onauthstatechanged/

ブラウザのインスペクタ画面から、indexedDBの該当箇所を削除するとログアウト状態にできます!

Discussion