注册应用程序
当开发人员访问您的网站时,他们将需要一种方法来创建新的应用程序并获取凭据。通常,在他们可以创建应用程序之前,您会让他们创建一个开发者帐户,或代表他们的组织创建一个帐户。
虽然 OAuth 2.0 规范不要求您在授予凭据之前收集任何应用程序信息,但大多数服务会在发布client_id和client_secret. 但是,出于安全目的,您需要开发人员为应用程序注册一个或多个重定向 URL,这一点很重要。这在重定向 URL中有更详细的解释。
通常,服务会收集有关应用程序的信息,例如:
- 应用名称
- 应用程序的图标
- 应用程序主页的 URL
- 应用程序的简短描述
- 指向应用程序隐私政策的链接
- 重定向 URL 列表
下面是 GitHub 注册应用的界面。在其中,他们收集了应用程序名称、主页 URL、回调 URL 和可选描述。
最好向您的开发人员说明您从他们那里收集的信息是显示给最终用户,还是仅供内部使用。
Foursquare 的应用程序注册页面要求提供类似的信息,但他们还要求提供简短的标语和隐私政策 URL。这些在授权提示中显示给用户。
您的服务还可以让开发人员选择他们正在创建的应用程序类型(公共或机密),或者选择可能与开发人员更相关的应用程序平台描述(网络应用程序、移动应用程序、SPA 等)。您的服务应该只向机密应用程序发布客户端机密,并且也不允许对这些应用程序使用隐式授权。
如上面的屏幕截图所示,Okta 让开发人员在收集有关应用程序的信息之前选择应用程序的平台(本机、单页应用程序、Web 或服务)。根据开发人员在此处选择的值,这将决定诸如为应用程序启用哪些授权类型以及是否向应用程序颁发客户端机密等事项。
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 的网站上很常见。
此外,在应用程序详细信息页面上隐藏秘密,直到开发人员单击“显示”,这是防止秘密意外泄露的好方法。