简体中文
  • OAuth
  • client
  • public
  • confidential
  • PKCE

公共客户端与机密客户端之间的区别是什么?

本文揭示了 OAuth 中公共客户端与机密客户端之间的区别,以 Logto 应用为例。

Darcy Ye
Darcy Ye
Developer

使用 Logto 创建应用时,你会注意到有几种不同的应用类型可供选择,包括单页面应用程序(SPA)、本机应用程序和传统 Web 应用程序。从名称上来看,可以直观地知道本机应用程序是运行在常见设备操作系统上的应用程序,比如手机。那么,究竟什么是 SPA 和传统 Web 应用呢?为什么我们需要区分这些不同类型的应用程序?本文将揭示这些问题的答案。

在开始之前,我们需要简要介绍一些概念。

什么是 OAuth?

OAuth 是一种开放的访问授权标准,通常被用于互联网用户授权网站或应用程序访问他们在其他网站上的信息,而无需提供其密码。

在最近的十年间,它逐渐成为了标准的授权流程,并被谷歌、Meta、微软等大多数公司广泛接受。目前使用的版本是 OAuth 2.0

在 OAuth 的背景下,我们之前提到的应用被称为客户端。只要它们获得了资源拥有者(通常为最终用户)的授权,它们就可以请求受保护的资源。

公共客户端和机密客户端

OAuth 根据客户端维护其凭证机密性的能力,定义了两种客户端类型。

机密客户端

能够维护其凭证机密性的客户端(例如,实施在安全服务器上、对客户端凭证有访问限制的客户端),或者可以通过其他方式进行安全客户端认证的客户端。

公共客户端

无法维护其凭证机密性的客户端(例如,运行在资源拥有者设备上的客户端,如本机应用程序或基于 Web 的应用程序),而且无法通过任何其他方式进行安全的客户端认证。

SPA、本机应用程序和传统 Web 应用程序

有了上述背景知识,让我们看看在 Logto 的上下文中,SPA、本机应用程序和传统 Web 应用程序意味着什么,以及它们是否被视为公共客户端或机密客户端。

SPA

SPA 的客户端代码从 Web 服务器下载,并在资源拥有者设备上的用户代理(如 Web 浏览器)中执行。协议数据和凭证对资源拥有者来说易于访问(而且通常是可见的)。

本机应用程序

本机应用程序安装并在资源拥有者的设备上运行。协议数据和凭证对资源拥有者是可访问的。通常假设包含于应用程序中的任何客户端认证凭证都是可以被提取的。

传统 Web 应用程序

传统 Web 应用程序是运行在 Web 服务器上的客户端。资源拥有者通过其设备上的用户代理呈现的 HTML 用户界面访问客户端。客户端凭证以及颁发给客户端的任何访问令牌都存储在 Web 服务器上,不会暴露或对资源拥有者可访问。

因此,我们可以明确地看到,SPA 和本机应用程序是公共客户端,而传统 Web 应用程序是机密客户端。

你可能会发现,在 Logto 中创建 SPA 或本机应用程序时,没有应用程序密钥,而传统 Web 应用程序既有应用程序 ID 又有应用程序密钥。这是因为公共客户端的密钥无法保证是安全的。

客户端在 OAuth 授权流程中的工作原理是什么?

在开发 OAuth 应用程序时,第一步是向 OAuth 服务提供商注册客户端。客户端注册涉及提供应用程序的详细信息,例如其名称和重定向 URI。然后,OAuth 服务提供商生成客户端 ID 和客户端密钥,它们被视为应用程序的凭证。

客户端 ID 被视为公共信息,并在 OAuth 过程中与用户共享。它通常包含在授权 URL 中,并对最终用户可见。

另一方面,客户端密钥作为应用程序的密码,必须保密。在 OAuth 过程中,它被用来交换授权码(假设它是授权码流)以获取访问令牌。客户端密钥的存在确保只有注册的应用程序才能完成访问令牌的交换。

介绍代码交换证明密钥(PKCE)

如前所述,公共客户端的客户端密钥无法保证安全,攻击者可能会获取客户端凭证并伪装为客户端访问受保护的资源,这在任何情况下都是不可接受的。

PKCE(代码交换证明密钥)通过在每个授权流程开始时临时生成一个代码验证器,在本地存储并散列以生成一个代码挑战发送到授权服务器,解决了这个问题。在交换访问令牌时,再次将代码验证器发送到授权服务器。授权服务器验证代码验证器和代码挑战是否匹配,这确保了公共客户端未被冒充。

PKCE 中的代码验证器实际上等同于动态客户端密钥。其安全性由散列算法的不可逆性保证。

回顾

在本文中,我们讨论了 OAuth 中机密客户端和公共客户端的概念。我们了解到机密客户端具有保密和安全存储敏感信息的能力,而公共客户端缺乏这种能力。在 Logto 的产品实践中,我们研究了这两种客户端类型的示例,包括传统 Web 应用程序、SPA 和本机应用程序。

我们还讨论了 OAuth 中的客户端注册过程,以及客户端 ID 和客户端密钥的角色。

此外,我们发现公共客户端在安全存储客户端密钥方面面临限制。为了克服这一限制,我们介绍了 PKCE(代码交换证明密钥),这是一种 OAuth 扩展,允许公共客户端在不需要客户端密钥的情况下安全地交换授权码。

我们的产品 Logto 是一个综合性 CIAM 解决方案,遵循 OAuth 和 OIDC 协议的最佳实践,以确保每个阶段的安全,包括使用 PKCE 保护公共客户端的安全。