从0开始构建一个Oauth2Server服务 9 #
ClientID 与 Secret #
ClientID #
此时,您已经构建了应用程序注册屏幕,您已准备好让开发人员注册应用程序。当开发人员注册应用程序时,您需要生成一个客户端 ID 和一个可选的密钥。生成这些字符串时,在安全性和美观性方面需要考虑一些重要事项。
是client_id
应用程序的公共标识符。尽管它是公开的,但最好不要让第三方猜到它,因此许多实现都使用类似于 32 个字符的十六进制字符串之类的东西。如果客户端 ID 是可猜测的,那么针对任意应用程序进行网络钓鱼攻击会稍微容易一些。它在授权服务器处理的所有客户端中也必须是唯一的。
以下是来自支持 OAuth 2.0 的服务的客户端 ID 的一些示例:
- Foursquare:
ZYDPLLBWSK3MVQJSIYHB1OR2JXCY0X2C5UJ2QAR2MAAIT5Q
- Github:
6779ef20e75817b79602
- Google:
292085223830.apps.googleusercontent.com
- Instagram:
f2a1ed52710d4533bde25be6da03b6e3
- SoundCloud:
269d98e4922fb3895e9ae2108cbb5064
- Windows Live:
00000000400ECB04
- Okta:
0oa2hl2inow5Uqc6c357
如果开发人员正在创建“公共”应用程序(移动或单页应用程序),那么您client_secret
根本不应该向该应用程序发出 。这是确保开发人员不会意外地将其包含在他们的应用程序中的唯一方法。不存在,就不能泄露!
因此,通常最好在开发人员开始时询问他们正在创建什么类型的应用程序。您可以向他们提供以下选项,并且只为“网络服务器”或“服务”应用程序发布一个秘密。
- 网络服务器应用程序
- 单页应用
- 移动或本机应用程序
- 服务应用
当然,没有什么可以阻止开发人员选择错误的选项,但是通过主动询问开发人员将使用哪种类型的凭据,您可以帮助减少泄露秘密的可能性。
Secret #
这client_secret
是一个只有应用程序和授权服务器知道的秘密。应用程序自己的密码是必不可少的。它必须足够随机以至于不可猜测,这意味着您应该避免使用常见的 UUID 库,这些库通常会考虑生成它的服务器的时间戳或 MAC 地址。生成安全机密的一种好方法是使用加密安全库生成 256 位值,然后将其转换为十六进制表示形式。
在 Ruby 中,您可以使用 SecureRandom 库生成十六进制字符串:
require 'securerandom'
SecureRandom.hex(32)
至关重要的是,开发人员永远不要将他们的client_secret
公共(移动或基于浏览器的)客户端包括在内。为帮助开发人员避免意外执行此操作,最好使客户端密码在视觉上与 ID 不同。这样当开发人员复制粘贴 ID 和密码时,很容易辨认出哪个是哪个。通常使用更长的秘密字符串是表明这一点的好方法,或者在秘密前加上“秘密”或“私有”前缀。
存储和显示Client_ID 和Secret #
对于每个注册的应用程序,您需要存储 public client_id
和 private client_secret
。因为这些本质上等同于用户名和密码,所以您不应以纯文本形式存储秘密,而应仅存储加密或散列版本,以帮助降低秘密泄露的可能性。
当您发布客户端 ID 和密码时,您需要将它们显示给开发人员。大多数服务为开发人员提供了一种检索现有应用程序秘密的方法,尽管有些服务只会显示一次秘密并要求开发人员自己立即存储它。如果您只显示一次秘密,则可以存储它的散列版本以避免存储明文秘密。
如果您以以后可以向开发人员显示的方式存储秘密,则在泄露秘密时应采取额外的预防措施。保护秘密的一种常见方法是在开发人员可以查看秘密之前插入“重新授权”提示。
该服务要求开发人员在泄露秘密之前确认他们的密码。当您尝试查看或更新敏感信息时,这在 Amazon 或 GitHub 的网站上很常见。
此外,在应用程序详细信息页面上隐藏秘密,直到开发人员单击“显示”,这是防止秘密意外泄露的好方法。