firestoreにはセキュリティルールというものがあります。このセキュリティルールについての理解を深めるために、セキュリティルールがどんなものなのか、代表的なルールのかけ方について紹介したいと思います。

セキュリティルールについて

firestoreのセキュリティルールは、ホワイトリスト方式です。このセキュリティルールは、従来のREST API等でおこなっていた認証・許可の部分、データのバリデーションの部分をルールとして定義できるものです。このセキュリティルールを組み合わせて用いることで従来のREST API形式でサーバサイドで書いていたユーザ認証・許可、バリデーション、データの加工、データベースへの格納・参照等の機能をクライント側で完結させることができます。また、このセキュリティルールは、クライントから利用するケースに適用され、firebase admin SDKを利用するサーバサイドのロジックには適用されません。

セキュリティルールの適用方法について

REST API形式のときのユーザ認証・許可について考えてみると、ユースケースごとに行っていると思います。REST API形式な形でユースケースという言葉を置き換えると対象となるリソース、リソースに対する操作(=create, read, write, delete)ということになります。この考え方をそのままfirestoreのセキュリティルールにも適用していきます。

実際の適用方法は、データ構造などにも深く関連するので詳細に踏み込むのはやめますが、ここでは代表的な例をいくつか紹介しておこうと思います。

代表的なセキュリティルールのパターンについて

firebaseには、ユーザ認証基盤であるfirebase authenticationという機能があります。この認証基盤と組み合わせてルールを適用するパターンはよくあるので、ここではその例を3つほど紹介したいと思います。

認証済みユーザのみ許可する

こちらの認証基盤と合わせて使う簡単な例です。下記例は、認証しているユーザに対してのみデータベースを公開するというルールです。開発段階によく使われるものですね。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

認証済みユーザのユーザIDを利用する

firebase authenticationで認証したユーザは、request.authに認証したユーザの情報がぶら下がっています。また、クライントのみでfirestoreを使ってユーザごとに必要な情報を保持する仕組みは、ユーザIDをドキュメントIDにドキュメントに保存されることがよくあります。そのドキュメントへのアクセスのチェックを行うのが下記例です。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{path=**}/users/{uid} {
      allow read, write: if request.auth != null && request.auth.uid = uid;
    }
  }
}

カスタムトークンを利用する

firebase authenticationでは、カスタムトークンという形にユーザ情報をぶら下げることができます。そのぶら下げた情報を使って、アクセスを制御する方法です。カスタムトークンを設定することは、firebase admin SDKを利用しておこなわないと出来ないので、クライント側だけは処理が完結できないのですが、簡単なcloud functionsを生成し、firebase admin SDKを通して、例えばamind権限があるかなどの属性をもたせることも出来ます。ロールというカスタムトークンを保持して、amin権限をもつか持たないかで情報の更新をできるかどうかを制御しています。

service cloud.firestore {
  match /databases/{database}/documents {
    match /{path=**}/rooms/{room} {
      allow read:  if request.auth != null && request.auth.token.role in ["member", "admin"];
      allow write: if request.auth != null && request.auth.token.role == 'admin';
    }
  }
}

おわりに

今回は、firestoreのセキュリティルールでよく利用されるfirebase authenticationと合わせて利用される代表的なルールについて紹介しました。最初は戸惑うかもしれないですが、従来のREST APIの機能をクライント、firestoreのセキュリティルールに分けて実現していると考えるとスッキリします。