生成OAuth令牌的最佳实践?

105

我知道OAuth规范没有具体说明ConsumerKey、ConsumerSecret、AccessToken、RequestToken、TokenSecret或Verifier代码的来源,但我想知道创建显著安全令牌(特别是Token / Secret组合)的最佳实践是否存在。

在我看来,创建令牌有几种方法:

  1. 只使用随机字节,在数据库中存储并与消费者/用户相关联
  2. 散列一些用户/消费者特定数据,并将其与消费者/用户相关联后存储在数据库中
  3. 加密用户/消费者特定数据

使用随机字节的优点(1)是数据库是信息的唯一来源,这似乎是最安全的。比(2)或(3)更难受到攻击。

对真实数据进行哈希(2)可以重新生成令牌,前提是已经知道了该数据。可能不会真正为(1)提供任何优势,因为需要存储/查找。比(1)更耗费CPU资源。

加密真实数据(3)将允许解密以获取信息。这将比(1)和(2)具有更少的存储量和潜在的较少查找次数,但可能不够安全。

还有其他的方法/优点/缺点应该考虑吗?

编辑:另一个考虑因素是令牌中一定要有某种随机值,因为必须存在过期并重新发放新令牌的能力,因此它不能仅由真实数据组成。

后续问题:

是否有最小的令牌长度可以显著加密?据我所知,较长的令牌秘钥将创建更安全的签名。这个理解正确吗?

从散列的角度来看,使用特定编码是否比其他编码更有优势?例如,我看到很多API使用十六进制编码(例如GUID字符串)。在OAuth签名算法中,Token被用作字符串。使用十六进制字符串,可用字符集将比Base64编码小得多(更可预测)。对于长度相等的两个字符串,具有较大字符集的字符串会有更好/更广泛的哈希分布。这似乎会提高安全性。这个假设正确吗?

OAuth规范在11.10 Entropy of Secrets中提出了这个问题。


为什么要加密?哈希不够好吗?如果只是用哈希来保护密码足够了,那么对于更长的访问令牌来说,难道不应该更好吗? - AlikElzin-kilaka
自从我提出这个问题已经过去了7.5年,老实说我已经记不清了。 - mckamey
1
再次阅读后,哈希和加密是两种不同的建议方法。加密可以让服务器在没有数据库查找的情况下获取一些信息。这是众多权衡之一。 - mckamey
1个回答

95

OAuth在令牌方面没有明确说明,除了它与一个密钥相关联。因此,您提到的所有方案都可以起作用。随着站点规模越来越大,我们的令牌也在不断发展演变。以下是我们以前使用过的版本:

  1. 我们的第一个令牌是一个加密的BLOB,其中包含用户名、令牌密钥和过期时间等信息。问题是,如果没有主机记录,我们无法撤销令牌。

  2. 所以我们将其更改为将所有内容存储在数据库中,并且令牌只是作为数据库键使用的随机数。它具有用户名索引,因此可以轻松列出用户的所有令牌并撤销它。

  3. 我们遇到了很多黑客活动。使用随机数,我们必须访问数据库才能知道令牌是否有效。因此,我们又回到了加密的BLOB。这次,令牌仅包含密钥和过期时间的加密值。因此,我们可以在不访问数据库的情况下检测到无效或过期的令牌。

以下是一些可能对您有帮助的实施细节:

  1. 在令牌中添加一个版本,以便您可以更改令牌格式而不破坏现有的令牌。我们所有的令牌都有第一个字节作为版本。
  2. 使用URL安全版本的Base64对BLOB进行编码,这样您就不必处理URL编码问题,这使得在OAuth签名中进行调试更加困难,因为您可能会看到三重编码的basestring。

3
非常感谢。版本控制的想法很好。我已经使用了适用���URL的Base64,但是我希望有一种严格的字母数字编码,以便更容易阅读。 - mckamey
以前没有想过,非常有趣!在阅读这篇文章之前,我计划使用APC键缓存来减轻数据库的不必要负载。但我仍然不确定这是否比共享内存查找慢(至少在合理时间范围内的第二、第三等请求)。 - Philzen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接