躲不开创建身份验证?开发者福音,更安全、更低成本的方案

全文共3310字,预计学习时长12分钟

 

图源:unsplash

 

大多数应用程序都需要某种身份验证。建立一个安全的认证系统是一个非常艰巨的任务,这要比想象中要困难的多,也更容易出错。

 

如果你是一家大公司的业务应用开发人员,你需要限制授权员工的访问并且检查他们的权限;如果你正在构建一款新的SaaS应用程序,那么就需要用户能够创建配置文件并自行维护。

 

除了这两种情形,构建应用程序时,第一步就要创建身份验证和用户管理工作流。即至少要创建一个注册表单和一个登陆页面。身份验证是web应用开发人员需要实现的最常见功能之一,但也是最容易被忽视的功能之一。但如果出现的错误会带来灾难性的后果。

 

系统的核心在于,用户管理和身份验证只需要几个web表单,似乎很简单,但细节很关键。安全地构建那些东西是一项壮举,并且大多数时候,需要以一种有隐私意识的方式构建。

 

 

身份云服务

 

好消息是,如今不再需要更新用户管理和身份验证逻辑,现在有大量有效的解决身份云服务的方案能轻而易举将身份信息安全地添加到应用程序中。

 

例如一些通用的身份验证平台:Auth0、Azure AD、Google Identity Platform以及Okta。还有一些社交网络身份提供商,如Apple’s、Facebook’s、GitHub’s、Twitter’s等。

 

图源:unsplash

 

消费者能够轻易地使用这些平台,并且为应用程序提供了大量潜在数据的即时访问权限,但有时也可能会对用户隐私造成负面影响。

 

开发人员没有理由不使用身份提供者服务。它们能够节省大量的开发时间,而这些时间可用于搭建实际的应用。最重要的是,它们的解决方案更安全。

 

 

大多数身份验证是安全的

 

大多数网络身份提供者提供高级安全功能,例如对多重认证(MFA)的支持、安全证书或者**(包括U2F、FIDO2、WebAuthn等)。不要低估其重要性,据微软的报告所述,启用MFA可以防御99.9%的账户攻击。

 

然而,还有另一个鲜为人知的方案能让使用网络身份提供者的服务相比使用自己的解决方案更安全:其拥有相当多的用户,从而可以更容易地分析出模式并防止攻击。

 

假设用户在加拿大的家中登录,两小时之后同一个账户在乌克兰登录。网络身份提供商就会将此标记为可疑,并且直接拒绝登录,或者至少要求其他形式的验证(如MFA令牌)。他们还可以通知受到影响的用户和/或管理员。

 

图源:unsplash

 

通过数百万用户执行的数百万的身份验证操作,这些大型网络身份提供商就获得了足够的数据以构建人工智能模型,用来更好识别可疑模式。

 

 

普遍异议

 

构建用户管理和身份验证逻辑并不难

 

注册和登陆表单只是问题的一方面。需要处理的不仅仅是构建一个表单,以允许用户创建一个帐户并键入其凭据。

 

首先,需要执行其他业务逻辑,例如强制执行密码安全规则(但请遵从NIST加密标准,不要强制使密码定期过期,并且不要强加创造性的规则,如要求大小写和符号等),验证电子邮件地址和/或电话号码,并为用户提供重置密码的方法。

 

设计这些系统时非常容易犯错误,有很多细节需要牢记:超大型的公司的数据库中没有散列密码(或者没有正确散列密码),不慎在日志文件中以明文方式转储密码,并且重置表单,很容易将其暴露,被社会工程等利用。

 

图源:unsplash

 

众所周知,正确管理密码并不容易。但管理用户名也很难吗?例如,看起来相同的两个用户名并不意味着两者是一样的。詹姆斯·班尼特在2018年的演讲《嗨!我的名字是……》中介绍了在用户名这样“简单”的东西上可能会出现什么问题。

 

最后,应用程序可以从许多提供商已经提供的高级安全功能中受益,其中包括对多重认证和安全令牌的支持。

 

这些服务的验证服务并不总是免费的,尤其是在应用程序库规模增大的情况下

 

还有什么不是免费的吗?遭到黑客攻击,必须支付损害赔偿,其中包括直接补救费用(如果有的话),紧急修复应用程序所花费的时间,特别是失去用户的信任。

 

甚至在此之前,完成一个安全的身份验证系统并对其进行维护、操作用户数据库等,都是以时间和资源为代价的。

 

笔者是非常资深的开发人员,知道如何建立一个安全的认证系统

 

在明白了安全构建这些东西并非想象的那么简单之后,如果你是个资深开发者,最好把时间花费在应用程序的其他部分,为用户提供更多价值。例如,如果真的想在认证系统方面任职,那么可以考虑加入Microsoft,Auth0,Facebook等公司,致力于改进他们的身份平台。

 

图源:unsplash

 

应该保持对用户的控制

 

首先,为什么?除非你在创建一个新的Facebook,那么数据的确是最大的财富,并且收集的越多越好,但通常这并不是刚需。

 

此外,收集更多关于用户的数据甚至可能会增加遵守GDPR等法规的成本。这将使违规行为潜在的危害性更大、代价更高。

 

上述大多数解决方案仍然有助于深入了解客户及其行为。

 

托管服务往往有些棘手,因此如果担心服务迁移的能力,可以考虑采用自托管的身份认证服务器。但请记住:这些系统的维护更加复杂,并且由于数目过大,往往缺乏先进的安全功能。

 

如何开始

 

好消息是,上述提供商(Auth0, Azure AD, Google Identity Platform, Okta)和更多的提供商都使用相同的协议:OpenID Connect 或 OAuth 2.0。两者都是现代化的行业标准协议,有着针对每种编程语言和框架的客户端库。

 

具体的步骤包括:

 

1. 向网络身份提供商注册应用。提供商会提供一个应用程序ID(或客户端ID)和一个**(或Client Secret)。

 

2. 定义应用程序所需的权限。除了返回用户的配置文件外,根据身份服务,还可以访问更多的数据,包括用户的电子邮箱,云存储等(例如通过Office 365或G Suite)。

 

3. 在应用程序中包含客户端库

 

笔者不会详细解释OpenID Connect是如何工作的,但是总体的流程包括应用程序将用户重定向到身份提供程序服务器上的页面。用户将在那里完成身份验证流程,然后和JWT令牌一起重定向到应用程序。

 

图源:unsplash

 

这种JWT令牌是加密签名的,其有效期受限,可用于为用户维护会话。换句话说,只要令牌有效,当应用程序识别到令牌的时候,就可以将请求视为来自于令牌所属的用户。

 

同样的JWT令牌还包括关于用户的声明。这取决于服务,但通常包括用户名、电子邮件地址和/或其ID。

 

应用程序可以利用这些声明来识别用户,并可以使用相同的用户ID来引用存储于应用程序内的数据。JWT令牌是加密签名的,因此在验证令牌的签名时,可以保证没有人篡改声明。

 

在静态web应用或本机应用中使用OpenID Connect

 

静态web应用程序(也称为JAMstack应用程序)和本地应用程序(例如桌面或移动应用程序)能以稍不同的方式使用OpenID Connect。在OAuth 2.0规范中,这被称为隐式流。

 

隐式流不需要使用Client Secret:因为应用程序在客户端上运行,所以没有安全的方式进行分发。

 

1. 应用程序将用户重定向到身份验证终点,确保查询字符串包含scope=id_token。

2. 用户利用身份提供程序完成身份验证流。

3. 用户被重定向到应用程序,JWT会话令牌作为一个片段附加到页面的URL(该片段是#符号后面的内容)。它在 id_token字段中。

4. 应用程序从URL片段获取JWT,进行验证。如果有效,那么用户通过身份验证,并且可以使用JWT中的声明来获取有关用户信息。

 

要在静态web应用程序中验证JWT,可以使用idtoken-verifier程序模块。桌面和移动应用程序可以使用类似的库来开发它们。

 

图源:unsplash

 

在客户机服务器应用程序中使用OpenID Connect

 

这些指令在很大程度上取决于用于构建应用程序的语言或框架。jwt.io website有一个完整的库列表来验证JWT令牌。对于某些栈,还可以利用更高级别的解决方案,如针对Node.js/Express的express-jwt或passport。

 

在构建客户端应用程序时,重要的是,一定要确保使用RSA-SHA256 (在JWT 的情况下, alg 必须是 RS256)来对令牌进行签名,因为这是非对称的:令牌使用身份提供程序中的**进行签名,但是应用程序可以使用公钥对其进行验证。

 

另一种常见的算法HMAC-SHA256(或HS256)使用对称**对令牌进行签名和验证,但是令牌无法安全地分发至客户端应用程序。

 

图源:unsplash

 

然后,客户端应用程序可以在向后端API服务器发出的每个请求中使用此JWT,这通常在Authorization中或者在cookie中传递。本例中,JWT的行为与任何其他会话令牌一样,但具有独立声明。

 

API服务器将检查JWT的存在并再次验证它;如果验证成功(且令牌尚未过期),可以将用户视为已验证,并从JWT内部声明中读取其用户ID。

 

这种简洁高效安全的身份验证方案,你get了吗?

 

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)