Product for Google IoT Solutions - 5分でFirebaseのセキュリティとルールがわかる

# 背景

* 過去数回にわたってFirebaseについて記事を書いてきました。今回は認証編です。
 * [Product for Google IoT Solutions - Firebaseを触ってみた](http://qiita.com/alingogo/items/ee3daebc6078dc6d8956)
 * [Product for Google IoT Solutions - Firebaseとraspberry piをリアルタイムで通信してみる](http://qiita.com/alingogo/items/545e5244323afb4469ae) 
 * [Product for Google IoT Solutions - 5分でFirebaseの認証がわかる](http://qiita.com/alingogo/items/a24bea82cc15602a74ed)


# 問題

* 以前の説明の例に、以下の記述があります。

```
 var ref = new Firebase("https://{app_name}.firebaseio.com");
```

* app_nameがそのままに公開されたとなると、誰でもapp_nameを使って、firebaseへアクセスできてしまいます。


## 説明

![無題の図形描画 (1).png](https://qiita-image-store.s3.amazonaws.com/0/13451/65267d35-138c-78a7-6057-3ab7ae70fd0f.png)

* 例えば、siteAのapp_nameで、siteAのFirebaseへアクセスして、userAのageを30に設定しました。
* 悪い人は、siteAのapp_nameを、siteBに使って、userAのageを20に改ざんできます。
* 結果、Firebaseが危険に晒されます。

## siteA

### コード

```
<!DOCTYPE HTML>
<html lang="en-US">
<head>
  <title>firebase test</title>
  <script src="https://cdn.firebase.com/js/client/2.4.1/firebase.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
  <script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
</head>
<body>
<button id="login"  class="btn btn-primary">Firebase Twitter</button>
  <p id="result"></p>
  <script>
  var ref = new Firebase("https://{app_name}.firebaseio.com");

  $("#login").click(function () {
      ref.authWithOAuthPopup("twitter", function (error, authData) {
      if (error) {
        $("#result").text("Login Failed!");
      } else {
        $("#result").text("Authenticated successfully with payload");
        ref.set({age: 30});
        $("#result").text("ageを30に設定しました");
      }
    });
  })
</script>
</body>
</html>
```

### 実行と結果

![firebase-security2.png](https://qiita-image-store.s3.amazonaws.com/0/13451/40807e6b-76cf-97ac-2208-be4df367e5dd.png)

![firebase-security1.png](https://qiita-image-store.s3.amazonaws.com/0/13451/6a2a0e87-4dde-14f4-51ce-10dacdb4680a.png)



## siteB（悪い人）

### コード

```
<!DOCTYPE HTML>
<html lang="en-US">
<head>
  <title>firebase test</title>
  <script src="https://cdn.firebase.com/js/client/2.4.1/firebase.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
  <script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
</head>
<body>
<button id="login"  class="btn btn-primary">ageを変更</button>
  <p id="result"></p>
  <script>
  var ref = new Firebase("https://{app_name}.firebaseio.com");
        ref.set({age: 20});
        $("#result").text("ageを20に設定しました");
</script>
</body>
</html>
```

### 実行と結果

![firebase-security3.png](https://qiita-image-store.s3.amazonaws.com/0/13451/451ad71b-e0cd-682c-de54-79be69de71b4.png)

![firebase-security4.png](https://qiita-image-store.s3.amazonaws.com/0/13451/3f5e58e5-21b8-bd06-1610-54ca5436dca3.png)





# 対策 - Firebaseのセキュリティとルールを利用

## Firebaseのセキュリティとルールを設定します

![firebase-security5.png](https://qiita-image-store.s3.amazonaws.com/0/13451/ec748c2c-3614-5e67-2906-9296b7b295f2.png)

### 説明
* Firebaseのconsoleに、「Security & Rules」をクリックして、セキュリティとルール操作画面が出てます。
* 上記の図の内容より、設定します。
    * 全てのユーザに関する内容を、usersの下に追加します。uidの値より、ユーザを区別することができます。
    * uid下に、uidを持っているユーザのみは、読み書き権限を設定します。
* 右上のsaveボタンをクリックして、Firebaseに保存できます。

## siteAのコード

```
......
ref.authWithOAuthPopup("twitter", function (error, authData) {
      if (error) {
        $("#result").text("Login Failed!");
      } else {
        $("#result").text("Authenticated successfully with payload");
        //ref.set({age: 30});
        ref.child('users').child(authData.uid).set({age:30});
        $("#result").text("ageを30に設定しました");
      }
......
```

## 結果

![firebase-security6.png](https://qiita-image-store.s3.amazonaws.com/0/13451/bde7dadd-c667-f664-b935-ff87915f0428.png)

* このようにすると、ユーザが認証していない場合は誰も対象ユーザに関する情報を改ざんできなくなります。

# 感想

* Firebaseのセキュリティとルールを利用して、安全を保証できます。
* Firebaseのセキュリティ対応は、その他のサービスと違うことがあります。
    * Firebaseには、セキュリティルールを設定することができます。
    * その他のサービスには、認証や、サーバー側の権限確認等で安全を保証します。