web-dev-qa-db-ja.com

Firebase:ユーザーの役割に応じてセキュリティルールを設定する

ユーザーの役割に応じて、Firebaseに「書き込み」セキュリティルールを実装したいと思います。
私のデータ構造は次のとおりです:

+ myapp
  + users
    + john
      + email: "[email protected]"
      + roles
        + administrator: true
    + mary
      + email: "[email protected]"
      + roles
        + moderator: true
    + ...
  + documents
    + -JVmo6wZM35ZQr0K9tJu
      + ...
    + -JVr56hVTZxlAI5AgUaS
      + ...
    + ...

たとえば、管理者ユーザーのみがドキュメントを書き込めるようにしたい。
これらは私が行ったルールです:

{
  "rules": {
    ".read": true,
    "$documents": {
      ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
    }
  }
}

しかし、それは機能しません:管理者ユーザーでさえドキュメントを書くことができません...
Firebaseのセキュリティルールに対する私の理解は完全に欠陥がありますか?

[〜#〜] update [〜#〜]:ジェニーの答えの直前(信じるかどうか:-)、私は彼が提供するものとまったく同じソリューションを実装しました(もちろん加藤のコメントに基づいています)。
ただし、いくつかのテストを行ったが、ルールを構造化できなかった

{
  "rules": {
    "documents" {
      "$document" {
        ".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
        ".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
      }
    }
  }
}

仕事...私はいつもこのような警告を受けました:

"FIREBASE WARNING: on() or once() for /documents failed: Error: permission_denied: Client doesn't have permission to access the desired data. "

だから私は代わりにこの構造を思いつきました:

{
  "rules": {
    "documents" {
      ".read": "root.child('users').child(auth.uid).child('roles').child('documents').child('read').val() === true",
      ".write": "root.child('users').child(auth.uid).child('roles').child('documents').child('write').val() === true"
    }
  }
}

私にとって実際に機能するのは、ユーザーの役割/顧客/読み取りノードをtrueに設定すると、ユーザーはすべてのドキュメントを読み取ることができますが、それ以外の場合は読み取ることができません(書き込みも同じです)。

私の疑問は今です:

  • なぜ私は(加藤が提案したように)最初のルールを機能させることができなかったのですか?
  • 私が思いついたようなセキュリティホールがルールにありますか?
  • キーに基づいて各単一ドキュメントの可読性/書き込み可能性を許可/拒否する必要はなくても、ノードの可読性/書き込み可能性を許可/拒否したい場合でも、「$」変数を使用するルールです。全体?
24
MarcoS

ユーザーレコードの名前に基づいて、それらはauth.uidと一致しません。これはおそらくTwitter:2544215などの Simple Login idです。

まず、Simple Login uidによって保存されるようにユーザーを調整します。

+ myapp
  + users
    + Twitter:2544215
      + email: "[email protected]"
      + roles
        + administrator: true
    + Twitter:2544216
      + email: "[email protected]"
      + roles
        + moderator: true
    + ...
  + documents
    + -JVmo6wZM35ZQr0K9tJu
      + ...
    + -JVr56hVTZxlAI5AgUaS
      + ...
    + ...

次に、セキュリティルールを追加して、管理者がdocumentsにアクセスできるようにします。特定のユースケースに応じて、ここにはいくつかのオプションがあります。

  1. 管理者に各ドキュメントのコンテンツへの書き込みアクセス権を付与するには:

    {
      "rules": {
        "documents": {
          "$documents": {
            ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
          }
        }
      }
    }
    
  2. または、代わりにコレクション全体へのアクセスを許可します。

    {
      "rules": {
        "documents": {
          ".write": "root.child('users').child(auth.uid).child('roles').child('administrator').val() === true"
        }
      }
    }
    

これらの2つの違いは、セキュリティルールを1つ上の階層に移動する$documents変数です。

(これは主に@Katoによるコメントの回答フォームへの集約でした)

27
mimming