I don't know if I just have some kind of blind spot or what, but I've read the OAuth 2 spec many times over and perused the mailing list archives, and I have yet to find a good explanation of why the Implicit Grant flow for obtaining access tokens has been developed. Compared to the Authorization Code Grant, it seems to just give up on client authentication for no very compelling reason. How is this "optimized for clients implemented in a browser using a scripting language" (to quote the specification)?

这两个流程的起点是相同的(来源:https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-22):

客户端通过将资源所有者的用户代理定向到授权端点来启动流。 授权服务器对资源所有者进行身份验证(通过用户代理),并确定资源所有者是否授予或拒绝客户端的访问请求。 假设资源所有者授予访问权限,授权服务器使用前面提供的重定向URI(在请求中或在客户端注册期间)将用户代理重定向回客户端。

重定向URI包括一个授权代码(授权代码流) 重定向URI在URI片段中包含访问令牌(隐式流)

这里是流分裂的地方。在这两种情况下,此时重定向URI指向客户端托管的某个端点:

In the Authorization code flow, when the user agent hits that endpoint with the Authorization code in the URI, code at that endpoint exchanges the authorization code along with its client credentials for an access token which it can then use as needed. It could, for example, write it into a web page that a script on the page could access. The Implicit flow skips this client authentication step altogether and just loads up a web page with client script. There's a cute trick here with the URL fragment that keeps the access token from being passed around too much, but the end result is essentially the same: the client-hosted site serves up a page with some script in it that can grab the access token.

因此我的问题是:跳过客户端身份验证步骤可以获得什么?


当前回答

它可以归结为:如果用户正在运行一个基于浏览器或“公共”(JavaScript)的web应用程序,没有服务器端组件,那么用户隐含地信任该应用程序(以及它运行的浏览器,可能与其他基于浏览器的应用程序……)

没有第三方远程服务器,只有资源服务器。授权代码没有任何好处,因为除了浏览器之外,没有其他代理代表用户。出于同样的原因,客户端凭证没有任何好处。(任何客户端都可以尝试使用此流。)

然而,这对安全的影响是重大的。从https://www.rfc-editor.org/rfc/rfc6749 #节- 10.3:

当使用隐式授权类型时,访问令牌将在中传输 URI片段,这可能会将其暴露给未经授权的一方。

从https://www.rfc-editor.org/rfc/rfc6749 #节- 10.16:

资源所有者可以自愿将对资源的访问委托给 向攻击者的恶意客户端授予访问令牌。这可能 可能是因为网络钓鱼或其他借口…

其他回答

在隐式流程中,如果用户的浏览器被损坏(邪恶的扩展/病毒),那么损坏就可以访问用户的资源,并可以做坏事。

在认证流中,腐败不能,因为它不知道客户端的秘密。

https://www.rfc-editor.org/rfc/rfc6749#page-8

Implicit The implicit grant is a simplified authorization code flow optimized for clients implemented in a browser using a scripting language such as JavaScript. In the implicit flow, instead of issuing the client an authorization code, the client is issued an access token directly (as the result of the resource owner authorization). The grant type is implicit, as no intermediate credentials (such as an authorization code) are issued (and later used to obtain an access token). When issuing an access token during the implicit grant flow, the authorization server does not authenticate the client. In some cases, the client identity can be verified via the redirection URI used to deliver the access token to the client. The access token may be exposed to the resource owner or other applications with access to the resource owner's user-agent. Implicit grants improve the responsiveness and efficiency of some clients (such as a client implemented as an in-browser application), since it reduces the number of round trips required to obtain an access token.

隐式授权允许使用GET从授权端点获取令牌。这意味着授权服务器不必支持CORS。

如果这不是一个问题,并且没有其他与授权服务器不灵活相关的问题(例如,出于某种原因,刷新令牌不是可选的),那么授权代码流是首选的,即使是对于公共客户端,根据最近的行业趋势和至少这个(当前)官方草案实例。

从历史上看,实现隐式流还有其他原因,但目前似乎它们被授权代码授予提供的安全优势所超越,包括:

为机密客户端通过反向通道交付和使用令牌的选项 没有在公共客户端的浏览器历史中公开令牌 在发布令牌之前中断未经授权的流-使用PKCE,用于“各种OAuth客户端”

我不确定我是否正确理解了答案和丹的评论。在我看来,这个答案已经陈述了一些正确的事实,但它确实指出了OP所问的问题。如果我理解正确的话,隐式授权流的主要优势是像JS应用程序这样的客户端(例如Chrome扩展)不需要暴露客户端秘密。

丹·塔夫林说:

...在授权代码流中,资源所有者永远不需要看到访问令牌,而在javascript客户端中,这是不可避免的。客户端秘密仍然可以从javascript客户端使用授权代码流,然而..

也许我误解了您的意思,但是客户端(在本例中是JS应用程序)必须在授权代码流中将客户端凭证(客户端密钥和秘密)传递给资源服务器,对吗?客户端机密不能“对JS保密”。

以下是我的想法:

授权代码流中的认证代码+令牌的目的是令牌和客户端秘密永远不会暴露给资源所有者,因为它们在服务器到服务器之间传播。

另一方面,隐式授权流适用于完全使用javascript实现并在资源所有者的浏览器中运行的客户端。使用此流不需要任何服务器端代码。然后,如果所有事情都发生在资源所有者的浏览器中,那么发布认证代码和客户端秘密就没有意义了,因为令牌和客户端秘密仍然会与资源所有者共享。包含认证代码和客户端机密只会使流程更加复杂,而不会增加任何真正的安全性。

因此,关于“我们获得了什么?”的答案是“简单”。