实施 PKCE 以使用 OAuth 授权后端请求

Implementing PKCE for Authorizing Backend Requests with OAuth

哟呵呵呵!我正在构建一个应用程序,它利用 OAuth 从提供商 API 中提取用户数据,并且想知道我选择的流程是否符合 RFC。

目前,用户登录授权服务器,该服务器向我的前端客户端发送授权代码。然后前端将授权代码传递到我的后端,后端将其交换为授权令牌,然后调用提供程序以提取数据。

在这个best practices document中,它指出:

Note: although PKCE so far was recommended as a mechanism to protect native apps, this advice applies to all kinds of OAuth clients, including web applications.

据我了解,PKCE 旨在确保将令牌授予请求授权码的同一实体,以防止攻击者使用窃取的授权码执行未经授权的请求。

现在,我明白为什么这很重要,即使后端不暴露客户端秘密,因为攻击者可以使用截获的授权代码向后端发出请求以接收令牌。但是在我的流程中,由于我没有创建身份验证方案而是试图授权有预谋的请求,因此令牌保留在后端。

那么这里为什么推荐PKCE呢?在我看来,被盗的授权码最多只能从后端发起 API 请求,而不会向攻击者返回任何令牌或数据。假设 PKCE 实施是可行的方法,它究竟如何工作?前端请求auth code和后端换token不完全一样,那么是不是直接传code_verifier给后端调用就可以了?

如能提供一些说明,将不胜感激。

PKCE 确保开始登录的一方也在完成登录,我将在下面总结单页应用程序 (SPA) 方面的两个主要变体。

PUBLIC 客户

考虑一个运行仅在 Javascript 中实现的代码流的单页应用程序。这将在 OpenID Connect 重定向期间将代码验证程序存储在会话存储中。在登录后 return 到应用程序时,这将连同授权代码和状态一起发送到授权服务器。

这将 return 标记给浏览器。如果存在 Cross Site Scripting 漏洞,则该流程可能会被滥用。特别是恶意代码可以启动隐藏的 iframe 并使用 prompt=none 静默获取令牌。

机密客户

因此,当前单页应用程序的最佳做法是为前端使用后端 (BFF),并且从不向浏览器发送 return 令牌。在这个模型中,BFF 更自然地像传统的 OpenID Connect 网站一样运行,其中 statecode_verifier 都存储在 login cookie 中,持续 sign-in进程。

如果存在跨站脚本漏洞,那么session riding可能会被恶意代码发送授权码给BFF并完成登录。但是,这只会导致写入浏览器无法访问的安全 cookie。同样,隐藏的 iframe 黑客也只会重写 cookie。

code_verifier 也可以存储在会话存储中并从浏览器发送到 BFF,但恶意代码很容易获取它并将其发送到服务器。这并没有真正改变风险,关键是不应 return 向浏览器输入任何令牌。在浏览器中使用次级安全值是可以的,只要您可以证明它们是合理的,例如对于安全审查员。一般来说,如果安全值在安全 cookie 中并且对 Javascript.

不太可见,则更容易解释

更多信息

最佳实践通常因客户用例而异,在 Curity,我们为客户(和普通读者)提供资源来解释安全设计模式。这些基于 security standards and we translate them to customer use cases。你可以 发现我们最近的 SPA Security Whitepaper 有用。