使用NodeJS服务器devise移动身份validation

我最近在为一个iOS应用程序的安全和用户身份validation问题挣扎,主要的问题是如何让用户注册任何第三方服务(或本地用户帐户),仍然保持安全和模块化的过程。

我提出的解决scheme是相当复杂的,我不是100%确定,如果所有这一切都是最佳实践,所以我想我会问,并得到什么build议和指针我可以修复,什么效果好,什么是坏等。

首先是authentication的问题。 我喜欢将authentication的想法与用户的想法分开。 对我来说,身份validation是由设备或客户端执行的,与特定用户无关,而用户帐户是由于身份validation而创build或检索的。 你可以做的是将客户端的身份validation视为一个进程,然后对用户进行身份validation(检查是否存在帐户等),以便有两层安全性。 假设客户端成功authentication,但用户密码错误,整体authentication失败,松散耦合这两个概念是有利的。

为了实现身份validation,我使用了JWT(JSON Web Tokens)通过cookie,原因很多。 1)它们在移动设备上工作得更好2)无会话,这使得服务器的实现变得更容易,并且据我所知,不受CORS攻击。 JWT似乎是使用移动设备时更好的解决scheme。 我使用了大量的npm库,最值得注意的是express-jwt和jsonwebtoken在服务器端进行身份validation。

正如我上面提到的,我不仅要执行身份validation,还希望允许用户注册任何他们想要的第三方服务,例如Facebook,Twitter,以减less注册期间的用户摩擦。 在思考这个问题之后,我花了很长时间search,提出了一个身份authentication系统的概念,authentication系统中的每个“账户types”被视为一个单独的身份提供者,并被推广为提供诸如access_token ,user_id,到期数据等。身份提供者很像在许多应用程序设置页面中看到的“已关联的帐户”。 在iOS的一面,我做了一个抽象类,为了支持每个服务,我创build了一个具体的子类, FacebookIdentityProviderLocalIdentityProvider (email / password)等等。

在服务器端,我使用Passport模块来备份每种身份提供者。 例如,他们有一个facebook令牌模块,一个用户的电子邮件和密码等。所以我做了一个API路由/authenticate ,我的客户向序列化的身份提供商请求,并基于标识符string, localfacebook-token ,护照会根据提供的信息调用相应的子模块来validation该提供者。

总的来说,安全stream程如下所示:

  1. 客户端检查磁盘是否存在以前的JWT令牌(使用encryption箱进行安全存储)。
  2. 如果find令牌,客户端向我的verify端点发出请求。 该端点将validation令牌是否仍然有效并且没有过期。
  3. 如果令牌没有过期,客户端将被发送一个200,并与世界一切好。 如果不是,那么客户端将向我的refresh_token端点发出一个请求,其中包含已过期的令牌,它将尝试重新发送令牌。 如果失败,则客户端向我的authenticate端点发出请求,该端点只能由用户操作调用。
  4. 如果在磁盘上最初没有发现令牌,则在3的末尾发生同样的事情,客户端必须等待用户进行authentication。

所有这些工作都已经完成并且实现了,但是我仍然对一些事情有些模糊。 首先,我在express-jwt页面上读取了关于撤销令牌的内容。 什么决定了什么时候我应该撤销令牌并重新login用户? 每当它无限期地到期时,保持刷新令牌是没有意义的。

其次,当我将序列化身份提供者发送到服务器时,我传递一个额外信息的字典,这个信息将被护照用来根据进程进行身份validation。 如果成功,则为该用户创build身份提供者并存储在数据库中。 这是足够的,还是应该做更多的access_token和其他领域,我从一个成功的电话回来? 特别是对于Facebook SDK,当客户端通过应用程序进行身份validation时,我获得访问令牌,然后在客户端再次与服务器进行身份validation时,获得另一个令牌。

我有一个额外的想法是有人集成了每个请求通过头或查询parameter passing一个API密钥。 API密钥将被保密,并在客户端得到保护。 我认为这会做的是添加另一层“身份validation”,甚至还没有通过身份validation过程的客户端。 只有拥有api-key的客户才能够首先达到我的api,而且只有这些客户才能够进行身份validation。

我的背景是正式的networking安全(我从来没有任何好处),现在是全栈式移动开发,所以我对这个东西有更好的把握,但是我觉得好像在缺乏一些潜在的危险漏洞。 我不幸的是不能发布代码,因为这是我的业务,​​但如果有什么我不明确,只是评论,我会很乐意详细说明。

另外我觉得我应该提到,所有这些都是通过使用Nginxconfiguration的SSL完成的,并且我所有的iOSnetworking请求都是使用Overcoat进行的 。 最终,我想使用Nginx作为负载平衡器,但这是另一天的职位。

我刚刚用过类似的东西。 撤销在JWT中被误解了,在客户端请求刷新令牌之前,您不能“撤销”它,您可以拒绝某个特定令牌的请求,但是只有使用restful服务器才能从客户端设备中删除它。 那么,在客户端应用程序中,如果您从服务器收到拒绝,您当然可以删除令牌。

移动应用程序的问题,你不想打扰用户不必要地询问authentication数据,而且如果用户丢失他的设备或更换他的设备,他/她想要撤销旧设备的访问,自然:

  • 你可以保持令牌(encryption)的散列密码,并在每个请求中,你可以检查令牌中保存的哈希密码是否与你的用户的数据库logging相同。

  • 你可以在db中保留userid,tokenid,设备信息,撤销字段(true / false)。 在这个表中,当设备请求使用被撤销的令牌进行刷新时,您只需简单地跟踪撤销的令牌,您只需返回错误,并且可以从表中删除此行,因为过期的令牌不再有问题。

希望这可以帮助。