oAuth2.0:为啥需要“授权码”,然后才需要令牌?

Posted

技术标签:

【中文标题】oAuth2.0:为啥需要“授权码”,然后才需要令牌?【英文标题】:oAuth2.0: Why need "authorization-code" and only then the token?oAuth2.0:为什么需要“授权码”,然后才需要令牌? 【发布时间】:2013-02-19 13:42:18 【问题描述】:

使用 oAuth 2.0,在“authorization-code”授权授予中,我首先调用“/authorize”,获取代码,然后在调用“/token”中使用此代码获取访问令牌。

我的问题:为什么这是流程?我想这是出于安全原因,但我无法弄清楚。为什么是这样实现的,而不是在第一次调用(“/authorize”)后立即获取访问令牌?

我们为什么需要这个代码?

【问题讨论】:

***.com/questions/13387698/… Why is there an "Authorization Code" flow in OAuth2 when "Implicit" flow works so well?的可能重复 这个 Q/A 是关于 SO 上臭名昭著的 X/Y 问题的教科书示例......仔细阅读问题并回答该问题而不是其他更方便的问题有什么困难?! 【参考方案1】:

是否也可以通过此中间步骤阻止客户端查看访问令牌?

来自 O'Reilly 的书:

授权码 此授权类型最适合服务器端 Web 应用程序。在资源所有者拥有之后 授权访问他们的数据,他们被重定向回网络 使用授权码作为查询参数的应用程序 网址。客户端必须将此代码交换为访问令牌 应用。这种交换是服务器到服务器完成的,需要 client_id 和 client_secret,甚至阻止资源 所有者获取访问令牌。这种授权类型还允许 使用刷新令牌对 API 进行长期访问。

基于浏览器的客户端应用程序的隐式授权 隐式授权是所有流程中最简单的,并且经过优化 用于在浏览器中运行的客户端 Web 应用程序。资源 所有者授予对应用程序的访问权限,并且新的访问令牌是 立即使用#hash 生成并传递回应用程序 URL 中的片段。该应用程序可以立即提取 从哈希片段访问令牌(使用 javascript)并制作 API 要求。这种授权类型不需要中介 “授权码”,但它也不能刷新 用于长期访问的令牌。

更新 - 确实是的:

什么时候应该使用授权码流?授权 应该使用代码流

需要长期访问。

OAuth 客户端是一个 Web 应用程序服务器。

API 调用的问责制非常重要,OAuth 令牌不应泄露给用户可能访问的浏览器 它。

更多:

也许最重要的是——因为永远不会发送访问令牌 通过浏览器 - 访问令牌的风险较小 通过浏览器历史记录、引用标头泄露给恶意代码, JavaScript 等。

【讨论】:

所以重点是回调 URL 中没有给出访问令牌是为了不让它以任何形式暴露在客户端。为什么?这是 SSL。我能想到的唯一原因是防止某些恶意软件访问 url,然后在应用用户授权的情况下终身访问用户数据。 但是为什么不让 api 与 server_secret_key + authorization_code 一起工作。而不仅仅是 access_token。这样就不会有授权码被盗的风险,因为服务器仍然有恶意软件没有的密钥 @MuhammadUmer 你对此有什么满意的解释吗?我也在寻找相同的信息。 不,我没有,现在我什至不记得我在想什么 @MuhammadUmer 如果我理解正确,您建议的 server_secret_key + authorization_code 方式与授权代码授予工作流程的访问令牌请求步骤相同:您在服务器上的应用程序交换其 client_secret + authorization_code (收到后第一步)用于令牌。然后它使用这个令牌来访问 API。【参考方案2】:

授权码流程适用于涉及 3 方的场景。

这些各方是:

客户

用户使用他的网络浏览器。他想使用你的应用程序。

提供者

有关于用户的信息。如果有人想访问这些数据,用户必须先同意。

您的(网络)应用程序

想要从提供者那里访问有关用户的信息。

现在你的应用告诉用户(将他的浏览器重定向到/authorize端点):

嘿用户,这是我的客户 ID。请与提供者交谈并允许他直接与我交谈。

因此,用户提供者对话(请求授权码并通过在他的浏览器中打开您的回调URL将其返回给您的应用程序):

您好提供商,我想使用这个应用程序,所以他们需要访问我的数据。给我一些代码,我将此代码提供给应用程序。

现在您的应用拥有授权码客户端提供者已经知道了。通过将其交给provider,您的应用现在可以证明client允许它访问他的数据。 provider 现在会向您的(网络)应用发出一个访问令牌,因此您的(网络)应用不必每次都重做这些步骤(至少在一段时间内) .

如果您的应用程序直接在客户端运行的其他应用程序类型(例如 iPhone/android 应用程序或 Javascript 客户端),则中间步骤是多余的。

【讨论】:

为什么不立即给用户访问/刷新令牌?为什么代码中有中间步骤? 同意,这不能回答问题。问题是为什么 @stickfigure 你能检查我的答案,看看它是否能解决你的疑问。如果没有,请告诉我。 嘿 Jan,在 Oauth 中,客户端是 Web 应用程序,资源所有者是“用户”,提供者可以是联合提供者或身份提供者。喜欢您的描述,但发现“派对”名称有点混乱。 是的。此处的术语适用于来自传统 client/user <-> server/web app 背景且希望将其应用与数据提供商(例如 Google)连接起来的人。【参考方案3】:

客户端的数据通常被认为是不安全的。在初始步骤本身授予令牌的隐式调用的情况下,任何拥有 access_token 的人都可以请求数据,API 不知道谁在调用该 API。

但是,对于应用程序想要标识自己的 Web 服务器应用程序,带有 client_secret 的 client_id 与 authentication_code 一起发送以获取 access_token,以后可以单独发送。

假设,如果 access_token 最初被授予本身,那么作为 client_id 和 access_token 仍将被视为已公开,因此应用程序必须每次发送 client_secret 和 access_token 以确保请求确实来自它。

而在当前场景下,获取access_token后,可以独立进行进一步的请求,不需要client_secret。

【讨论】:

【参考方案4】:

我觉得是这样的;

当我们使用授权码时,我们有2个验证部分;

1;验证用户的所有权,因为他登录了 2;我们知道客户确实是他所说的那样,因为客户正在发送他的 client_secret。

因此,如果我们在用户进行身份验证时返回访问令牌而不是授权码,我们知道是用户请求它,但我们不知道它将用于注册的客户端。比如你的 webapp。

当我们使用“隐式授权”时;(或返回访问令牌而不是授权码)

1;我们知道接收访问令牌的是用户,但不需要获取授权码,因为基于“用户代理”的应用程序是不可检查的。如果您考虑一下,它是可检查的,但它对每个人都可用。 client_secret 在基于“用户代理”的应用程序的源代码中是公开可见的,因此每个人都可以“查看源代码”并复制 client_secret 并使用此方法来验证客户端的所有权。

【讨论】:

【参考方案5】:

很重要的一点是

也许最重要的是——因为访问令牌永远不会通过浏览器发送——访问令牌通过浏览器历史记录、引用标头、JavaScript 等泄露给恶意代码的风险较小。

【讨论】:

但在 facebook Oauth 中,访问令牌被传递给浏览器 link【参考方案6】:

@ksht 的回答基本上是正确的。对于那些寻求简单、简短答案的人来说,它是这样的:

因为客户端应用程序(浏览器或本机应用程序)可以拦截传递的令牌。 oauth implicit 流程确实 允许这样做,但仅在非常特定的情况下。在所有其他情况下,浏览器可能会泄漏信息(操作系统中的黑客攻击、浏览器错误、插件),或者对于本机应用程序,您可以拦截将重定向 url 映射到应用程序的自定义 url 方案。所以解决方法是发回代码而不是令牌(通过 tls)并使用 PKCE 确保代码可以安全地交换为令牌。

【讨论】:

以上是关于oAuth2.0:为啥需要“授权码”,然后才需要令牌?的主要内容,如果未能解决你的问题,请参考以下文章

oauth2.0授权码模式详解

oauth2.0授权码模式详解

OAuth2.0 - 使用数据库存储客户端信息 及 授权码

OAuth2.0系列之授权码模式实践教程

#yyds干货盘点# OAuth2.0授权码模式实战

OAuth2.0的其余两种授权方式