Firebase【セキュリティールール編】


概要

Firestore/Storageでのセキュリティールーのメモ

セキュリティ ルール言語
カスタム トークンを作成
セキュリティ ルールと Firebase Authentication

セキュリティールール構文

service
Firebase プロダクト(サービス)を定義する。
macth
firestoreまたはstorageへのpathのパターンを宣言する。
allow
ルールのいずれかが一致すると、指定したメソッドを実行できる。

関数定義

処理をまとめて関数化することができる

// return boolean
fuction example() {
    return request.auth.uid != null
}

組み込み変数・関数

※ここではよく使いそうなものだけ抜粋。

request

request.autn 認証済みであればパラメーターが入ってくる。

exists()

引数にpathを渡すと存在するかどうかを返す。

get()

引数にpathを渡すとオブジェクト返す。

セキュリティ ルールのメソッド

メソッド 動作 備考
read 読み取り あらゆるタイプの読み取りリクエスト
write 書き込み あらゆるタイプの書き込みリクエスト
get 読み取り 単一のドキュメントやファイルを対象とした読み取りリクエスト
list 読み取り クエリとコレクションを対象とした読み取りリクエスト
create 書き込み 新しいドキュメントやファイルへの書き込み
update 書き込み 既存のドキュメントやファイルへの書き込み
delete 削除 データの削除

ルールサンプル

1、firestorageで認証しているとコレクション(users)に書き込みができる
2、コレクション(users)で認証IDと同じドキュメント名のデーターのみ読み取りができる。
3、firestorageで認証しているとコレクション(books)に書き込み、読み取りができる

service cloud.firestore {
    // ここはおまじない
    match /databases/{database}/documents {
        // 関数を定義
        function signedIn() {
            return request.auth != null
        }
        // 1
        match /users {
            allow write : if signedIn()
        }
        // 2
        match /users/{uid} {
            allow read : if request.auth.uid == uid
        }
        // 3
        match /books {
            allow read write : if signedIn()
        }
    }
}

macthはネストすることもできる

service cloud.firestore {
    match /databases/{database}/documents {
        function signedIn() {
            return request.auth != null
        }
        // 1
        match /users {
            allow write : if signedIn()
            // 2
            match /{uid} {
                allow read : if request.auth.uid == uid
            }
        }
        // 3
        match /books {
            allow read write : if signedIn()
        }
    }
}

備考

・アプリへの認証にFirebase Authenticationを使用せずにサーバー(PHPやNode.jsなど)でログインしている場合
→ サーバー側でトークンを発行、firebase-adminのcreateCustomTokenでトークンを生成しクライアント側に渡しsignInWithCustomTokenでログインする。

サンプル:

サーバー側
// ... //
const admin = require('firebase-admin');
admin.initializeApp({
    credential: XXXX,
    databaseURL: XXXX
});

// ... //
const token = "<トークン>";
admin.auth().createCustomToken(token)
    .then(customToken => {
    // 生成したカスタムトークンをクライアント側に送信する処理
    })
    .catch((error) => {
    // error
    })
クライアント側
import firebase from "firebase/app";
import 'firebase/auth'
// ... //
const customToken = "<サーバー側で生成したカスタムトークン>";
firebase.auth().signInWithCustomToken(customToken)
    .catch((error) => {
        // error
    })