OAuth中的授权码目的是什么?

20
在OAuth中,你使用客户端ID/密钥发起请求以获取授权码。然后,你再发起第二个请求来交换授权码以获取访问令牌。我的问题是:
为什么需要这两步流程而不是一开始就获取访问令牌呢?这如何增加整个过程的安全性?还是有其他原因?
我在谈论服务器端应用程序(例如php)从远程服务器请求授权,而不是JavaScript。
3个回答

9
可以通过单个请求完成 - 这被称为隐式流。只有一个请求,response_type设置为tokenid_token token
使用访问代码(授权流)而不是直接返回令牌的一般想法是将它们隐藏在最终用户之外。通常由后端服务器而不是浏览器执行第二个请求。
您可以在此处找到更多详细信息:https://auth0.com/docs/api-auth/which-oauth-flow-to-use 注意:要获取完整答案,请阅读评论。

2
但是访问代码并不对用户(或用户机器上的软件)隐藏。如果像浏览器插件这样的恶意软件首先将访问代码替换为令牌,那该怎么办呢?授权服务器使用重定向URL作为着陆页,并通过直接的POST请求将代码发送给客户端应用程序,而完全不经过用户浏览器,这样岂不更安全? - NickSoft
2
访问代码是不可用的 - 但是要将访问代码交换为令牌,您需要提供用户未知的client_id和client_secret。 - Jakub Kubrynski
1
那么访问代码根本不需要。在服务器授权您的客户端ID/密钥访问后,您只需请求访问令牌即可。服务器知道您已经获得了访问权限,为什么还需要访问代码来证明它呢? - NickSoft
1
客户端ID和密钥是为应用程序准备的,而不是用户。访问代码是基于用户凭据授予的。因此,我(Jakub)登录到LinkedIn并获取访问代码。然后,您的应用程序使用我的访问代码和您的客户端ID/密钥从LinkedIn检索我的访问令牌。 - Jakub Kubrynski
1
隐式授权类型不再推荐使用。对于公共客户端,您应始终使用带有PKCE的授权代码授权类型。 - Spomky-Labs
第二个请求通常由后端服务器而不是浏览器完成。那么后端服务器无论如何都必须用访问令牌回应客户端,对吗?这一步骤如何确保进一步的安全性。我还是有些困惑。 - Sundar Rajan

4
在OAuth中,您使用客户端ID / 密钥发出请求以获取授权代码。
授权代码请求不包含客户端密钥。它只包含客户端ID和重定向URL,这使授权服务器能够验证请求是否来自已知客户端。
为什么需要这个两步骤的过程,而不是直接获取访问令牌?这样做如何使整个过程更加安全?或者还有其他原因。
如果我们忘记了隐式流,它涉及从第一个调用中检索访问令牌,那么我会说这是为了提高安全性。
当使用授权代码流时,您使用用户代理(浏览器)启动流程。这意味着,用户代理将重定向最终用户到授权服务器进行身份验证(获取用户名密码并验证最终用户)。如果最终用户验证成功,则授权服务器会发送授权代码。这是一个临时密码,与原始授权代码请求绑定。
现在,客户端使用授权代码直接联系授权服务器以获取访问(和其他)令牌。这第二步发生在用户代理之外。
如果客户端是机密客户端,即具有客户端ID和客户端密码的客户端,则这个第二个调用将需要提供此客户端密码。因此,它内部包含一个客户端验证过程。从授权服务器的角度来看,如果客户端身份验证失败,令牌请求将被拒绝。这为授权代码窃取提供了保护。
另外,在第二步中,我们避免了让第三方看到访问令牌。例如,在隐式流中,访问令牌作为URL片段通过用户代理发送。如果用户代理被攻击(例如:被某些恶意代码操纵),则可以提取此访问令牌。
那么公共客户端呢?这意味着由于其性质而无法获得客户端密码的客户端(例如:无法通过存储来保护密码的客户端)。
公共客户端使用PKCE。必须使用它来避免授权代码窃取。因此,在令牌请求(第二个调用)中,客户端将直接发送代码验证器。用户代理不能在第一次请求中获取代码验证器,因为它已经被哈希化(代码挑战)。因此,令牌请求现在包含一个只有客户端和授权服务器知道的密码。
如果您比较这两种情况(公共和机密客户端),您会发现第二个调用增加了一个额外的安全层。

0

更安全...还是不安全?这取决于它的应用方式。

请查看: https://auth0.com/docs/api-auth/which-oauth-flow-to-use

您会注意到,当在服务器端使用时,授权代码流程被使用。同时,请注意,当请求授权代码时,响应URL带有一个带问号的查询字符串:https://example-app.com/redirect?code=g0ZGZmNjVmOWI&state=dkZmYxMzE2

当使用单页应用程序时,您将使用隐式流程。请注意,访问令牌通过URL中的锚点(#)发送:https://example-app.com/redirect#access_token=MyMzFjNTk2NTk4ZTYyZGI3

锚点值永远不会被发送到服务器,它只能在spa中对客户端可用。服务器将永远无法看到访问令牌。

当服务器应用程序收到重定向时,必须能够读取它。这是可能的,因为url中有一个问号而不是#。如果直接发送令牌,客户端可以通过浏览器历史记录或fiddler查看访问令牌。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接