我们可以谈谈客户端证书吗?

2020-06-13 07:22:55

我正在改进API用户使用SourceHut API进行身份验证的方法。今天,我为了这个目的阅读RFC6749(OAuth2),这让我想起了最初的OAuth规范。我隐约记得api客户端实际上签署了每个请求,而…。是的,确实是这样。这也让我思考:还有什么签署请求?TLS!

OAuth非常复杂。RFC有76页长,单独的持有者令牌RFC(6750)又是18页,而且从来没有人读过它们中的任何一个。还可以添加JSON WebToken(RFC7519,30页)。这个过程很复杂,每个人都会自己实现它--这肯定会在安全关键组件中出错。并不是所有的数据都经过身份验证,任何步骤都不涉及密码学,任何一方都很容易以意外状态结束。服务器必须自己处理撤销和生成安全令牌的问题。你见过对OAuth持肯定态度的人吗?

现在,请坐。喝杯咖啡吧。我想谈谈客户端认证。他们为什么不起飞?让我们草拟一个假设的基于TLS的协议作为OAuth的替代方案。想象一下下面的…。

您是API客户端开发人员,生成证书颁发机构和中间人,并将您的CA证书上载到服务提供商,作为您注册为用户代理的一部分。

当您希望用户授权您访问他们的帐户时,您可以为他们生成证书,然后将他们重定向到服务提供商的授权页面,并附带一个CSR。您的证书包括您希望被授予访问权限的授权作用域的列表等。它已经使用您的客户端CA密钥或其中间产品之一进行了签名。

客户端查看所需的访问权限,并同意。它们与签名证书一起被重定向回您的API客户端应用程序。

TLS基本上是互联网上单一的最坚固的、经过战斗考验的安全机制,每个平台都有成熟的实现,每个人都实现了OAuth,但往往很差。

客户端证书是无状态的。它们包含证明客户有权访问所需的所有信息。

如果您使用nginx、haproxy等处理SSL终止,您甚至可以在应用程序后端看到授权请求之前拒绝它们。

如果客户端的CA是恶意的或丢失了私钥,服务提供商可以在单个吊销中取消信任。

API客户端和服务提供商都始终确定该进程是由API客户端故意启动的。不需要像OAuth那样使用奇怪的状态令牌来完成此过程!

有很多免费的特性:任何您喜欢的元数据、内置的过期、API客户端可以根据自己的判断自组织成中间产品,等等。

有安全意识的最终用户可以在他们的帐户中切换一个标志,作为同意过程的一部分,在签名的证书返回给API客户端之前,要求他们自己签署API客户端的证书。因此,授权给该用户帐户的任何API请求都必须由API客户端、服务提供商和用户签名才能有效。

这里还有另一个示例:假设您的组织有几个服务,每个服务都代表其用户与Acme Co的API的子集交互。您的组织生成单个根CA,并使用它注册Acme Co的API,然后向您的每个服务颁发中间CA,这些服务只被允许为它们需要的范围子集颁发CSR。如果任何服务被破坏,它不能用于获得比它已经拥有的更多的访问权限,并且您可以只撤销一个中间服务,而不会影响其余的服务。

甚至一些著名的缺点,如CRLS和OCSP,也在这里得到缓解,因为系统更加集中。您可以控制所有要验证证书的端点,只要它们一进来,您就可以直接将撤销分发给它们。

好处显然不胜枚举。让我们把它包装成一个可爱的、支持Google的名称,为它编写一些不错的工具库和帮助库,然后发布它!

或者,也许不是。我有一种喋喋不休的感觉,觉得我漏掉了什么。几十年来,每个人都把这样一个显而易见的解决方案留在桌面上,这似乎是不对的。也许这只是整个证书签名舞蹈在每个人的嘴里留下了一个不好的味道-我们中的许多人都没有那么愉快的记忆,那就是使用可怕的OpenSSL CLI来生成ACSR。但是,如果我们有动力的话,我们没有理由不能做得更好,更精简。

还有更多客户端证书的用例,这些用例看起来并不那么引人注目,比如用户密码的替代方案。Web浏览器对强制端证书的支持非常糟糕,但这是一个可以解决的问题。

郑重声明,我无意对SourceHutAPI使用此方法。我只是突然想到了这个想法,我想听听你的想法。为什么我们不使用客户端证书?

对我的一篇帖子有什么评论吗?通过发送电子邮件至~sircmpwn/[email protected],在我的公共收件箱中开始讨论。

您是一名自由软件维护员吗?在您的工作过程中,您是否正在与压力、苛刻的用户、超负荷工作或任何其他社会问题作斗争?请给我发电子邮件-我知道你的感受,我可以倾听你的同情心,分享一些经验丰富的建议。