使用firebaseSimpleLogin的Firebase用户帐户安全性

时间:2014-07-12 01:25:37

标签: ios firebase firebase-security firebasesimplelogin

我正在尝试为使用firebase的应用程序设计安全性的最佳方法

基本问题

我们希望用户的数据安全。我们不希望恶意代理能够访问Firebase数据库上的其他用户的私有数据。似乎应该通过firebaseSimpleLogin解决这个问题,但是尽管我们没有看到文档,但我们还没有看到它。

问题细节

  • 我们提供包含用户帐户的应用,这些用户拥有私人数据
  • 用户应该只能阅读:
    • 他们自己的数据
    • 与所有用户相关的应用范围内的数据,例如所有用户都获得的副本的模板 当他们最初创建他们的帐户时,其原始副本 是在fb db
    • 另一个用户的一部分数据,如果是那样的话 其他用户明确决定与他们分享,例如 他们制作的游戏是他们希望其他用户拥有副本 的
  • 现在,用户登录 FirebaseSimpleLogin。这是有问题,因为任何恶意用户 可以合法地创建自己的帐户,并使用他们的帐户 使用恶意脚本登录的电子邮件和密码,并访问 分贝

我们考虑的解决方案

1。存储user_secret以确保用户具有合法访问权限

  • 受到How to setup Firebase security rules to accept connections only from an iOS App回答的第二种方法的启发
    • 结构看起来像security-> user_secret-> associated_user OR security-> user-> {all_valid_user_secrets}
    • 安全规则:“。read”:“root.child('user_secrets /'+ auth.uid).exists()”
  • 我们可以为每个用户存储多个用户密钥,允许从多个经过验证的来源(iOS应用,网络应用等)进行访问

#1的问题

  • 我们如何限制对安全子的写/读访问?
    • 服务器不存在SimpleLogin
    • 我们不希望这些信息可见,因为恶意用户可以在技术上阅读它以查找有关他/她自己帐户的信息,然后使用它来仔细阅读其余的数据库
  • 与问题陈述中的问题相同:用户可以合法生成帐户,然后使用这些凭据获取对db的恶意访问

2。暂时存储用户密码

  • 用户启动登录
  • 节点服务器生成密码,将其存储在Firebase中受限制的安全子级中(服务器可以执行此操作,因为Firebase机密允许完全访问)
  • 我们使用Firebase SimpleLogin授权firebase客户端,因为我们已经
  • 用户与应用互动。如果节点服务器写入的安全子项存在,则Firebase安全规则仅允许读/写访问
  • 用户启动注销/崩溃/关闭应用
  • 节点服务器从受限安全子项中删除密码
  • 取消对Firebase ref的授权,因为我们已经
  • 完成

#2 问题 - 此方法的问题是用户在登录时容易受到攻击,因为他们的安全信息会存在。

3。使用内置的Firebase安全规则

  • 我们希望有一个内置的firebase解决方案,但还没有找到解决上述问题的解决方案。如果你能指出一个非常棒的话。

我们希望有人可以帮助阐明这里的最佳方法,无论是使用我们的想法还是其他途径。非常感谢你的帮助。

2 个答案:

答案 0 :(得分:5)

您基本上要求某人为您的应用编写完整的安全架构。如果您在尝试将安全规则应用于这样的复杂结构之前彻底理解安全规则,那会更好。 A good study of the docs from start to end将为您提供一个功能齐全的解决方案。

让我们只关注似乎是核心问题,即您不确定如何使用仅限客户端的解决方案使邀请安全地工作。 (由于能够创建我们自己的令牌所提供的额外火力,node.js解决方案也应该明白这种理解)我会在这里做出很多假设;只需将这些想法应用到您当前的用例中即可。

数据结构:

/invites/$game_id/$uuid/true  (a place to store invited users)
/accepted_invites/$gameid/$userid/$uuid/true (a place to store accepted invites)
/games/$game_id (the place we want to invite users into)
/users/$user_id (a place where we put profiles for existing users)

1)当新用户在应用中创建帐户时,请将他们的个人资料写入/ users。安全用户/如下:

"users": {
   "$userid": {
      ".write": "auth.uid === $userid"
   }
}

2)要邀请用户,请创建一个uuid,表示一个不可提交的ID,并将其存储在邀请/ $ game_id中。请注意,没有人应该能够阅读此路径。

"invites": {
   "$game_id": {
     "$invite_id": {
        // I can only create an invite for groups I'm a member of
        ".write": "root.child('games/'+$game_id+'/members/'+auth.uid).exists()",
        ".validate": "newData.val() === true"
     }
   }
}

3)要加入游戏,用户必须首先接受访问令牌,证明他们 知道令牌(因为他们无法读取邀请路径)并将令牌链接到他们的 帐户ID。此条目的值是邀请的uuid。

"accepted_invites": {
   "$game_id": {
      "$user_id": {
         ".write": "auth.uid === $user_id",
         ".validate": "root.child('invites/'+$game_id+'/'+newData.val()).exists()"
      }
   }
} 

4)如果用户已经接受邀请或者最初创建并且还没有成员(!data.parent().exists()规则)

,用户可以将自己写入游戏
"game": {
   "$gid": {
      "members": {
        "$uid": {
           ".write": "auth.uid === $uid",
           // I can join a group if a) I'm creating it or b) I have accepted an invite
           ".validate": "!data.parent().exists() || root.child('accepted_invites/'+$gid+'/'+auth.uid).exists()"
        }
      }
   }
}

我们客户端解决方案的另一个增强功能是为邀请分配一个优先级,代表它们何时到期,然后在安全规则中引用该优先级来控制令牌有效的时间。

答案 1 :(得分:0)

由于@Kato的建议,我最终得到了#3的想法。到目前为止,使用内置规则和设计模式的解决方案允许我们避免需要第三方auth服务器。架构的一些示例如下:

 "game_detail" : {
      "$game_detail" : {
        ".read" : "data.child('owner').val() === auth.email || root.child('admins').val() === auth.email",
        ".write" : "newData.child('owner').val() === auth.email || root.child('admins').val() === auth.email"        
      }
    },

然后,使#3成为可能的附加密钥是,除了具有安全规则模式之外,我们还创建了一个通用管理员凭证,匿名用户在登录时可以使用这些凭据来访问数据库并执行必要的跨账户操作。

感谢大家的投入。