OAuth授权代码和隐式工作流程有什么区别?什么时候使用每个?


165

OAuth 2.0具有多个工作流程。关于这两个,我有几个问题。

  1. 授权码流程 -用户从客户端应用登录,授权服务器向应用返回授权码。然后,该应用将授权代码交换为访问令牌。
  2. 隐式授予流程 -用户从客户端应用程序登录,授权服务器直接向客户端应用程序颁发访问令牌。

两种方法在安全性方面有什么区别?哪一个更安全,为什么?

当服务器可以直接发出访问令牌时,我看不出在一个工作流程中添加额外步骤(令牌的交换授权代码)的原因。

不同的网站说,当客户端应用程序可以确保凭据安全时,将使用授权代码流。为什么?


Answers:


204

access_token就是调用受保护资源(API)所需要的。在“授权码”流程中,有两个步骤可以获取它:

  1. 用户必须进行身份验证并向codeAPI使用方(称为“客户端”)返回。
  2. API的“客户端”(通常是您的Web服务器)将code在#1中获得的交换为access_token,并使用client_id和进行身份验证client_secret
  3. 然后,它可以使用调用API access_token

因此,有一个双重检查:拥有通过API浮出水面的资源的用户和使用该API的客户端(例如,Web应用程序)。两者都经过验证才能获得访问权限。请注意此处的OAuth的“授权”性质:用户将对他的资源的访问权限(通过code身份验证后返回的内容)授予应用程序,该应用程序的get为access_token,并代表用户进行调用。

在隐式流程中,省略了步骤2。因此,在用户验证之后,将access_token直接返回an ,您可以使用它来访问资源。API不知道谁在调用该API。任何人都access_token可以使用,而在前面的示例中,只有Web应用程序可以(任何人通常都无法访问其内部)。

隐式流通常是在其中存储的情况下使用client idclient secret不推荐(例如,设备,尽管许多也无妨)。这就是免责声明的意思。人们可以访问客户端代码,因此可以获取凭据并假装成为资源客户端。在隐式流中,所有数据都是易失性的,应用程序中没有存储任何数据。


感谢您的解释,但我不明白为什么我们需要另一个授权码流程。我们可以通过隐式流(access_token)和刷新令牌在服务器上达到相同的结果。看起来隐式流的唯一安全考虑是access_code的寿命应该很短,因此不能在服务器之间使用。可以,但是刷新令牌可以解决此问题。为什么我们应该使用auth_code流并请求服务器上的auth_token获得access_code?
Mohammad Nikravan '16

好吧...这就是协议的工作方式。您可能需要阅读规范威胁分析,以获取有关两者的安全性优点的更详细参考。
Eugenio Pace

我知道原始答案已有5年以上的历史,但这是我读过的最简单,最清晰的解释。谢谢@EugenioPace
塔哈·艾哈迈德

1
@ Madnik7G原因与该答案所解释的(美丽的)正交:可能涉及第三方。整个流程由用户代理(例如,浏览器)编排,但最终,授权服务器(例如:“使用Facebook登录”)将直接与客户端(例如,您的服务器端BFF)对话。最终访问资源,以便用户代理永远无法直接访问。
丹尼尔·兰登

谢谢!是的,正在进行3种通讯:浏览器和AS 9e.g. Facebook)。那是/authorize要求。浏览器和网站尝试调用API(也称为客户端)。成功认证后,AS返回的是redirect_uri+ code。最后,客户在幕后呼叫AS,将交换codeaccess_token。这是token endpoint文献中的。通常,AS不会呼叫任何人。它总是答复。
Eugenio Pace

52

我将在此处添加一些我认为以上答案未明确的内容:

  • Authorization-Code-Flow允许最终访问令牌永远不会到达,也永远不会与浏览器/ app一起存储在计算机上。使用浏览器/应用程序将临时授权码提供给计算机,然后将其发送到服务器。然后,服务器可以将其与完全访问令牌交换,并且可以访问API等。使用浏览器的用户只能通过带有令牌的服务器来访问API。
  • 隐式流程只能涉及两方,最终访问令牌与浏览器/应用程序一起存储在客户端上。如果该浏览器/应用受到威胁,则其身份验证令牌也将受到威胁,这很危险。

tl; dr如果您不信任用户的机器来保存令牌,但您确实信任自己的服务器,则不要使用隐式流。


12
回复:使用浏览器的用户只能通过带有令牌的服务器访问API。 但是,服务器需要送东西给浏览器,以便将入站请求可以关联到令牌被保持的服务器端。如果愿意,可以使用cookie。如果服务器未将令牌传输给在浏览器中运行的JS,则它必须传输其他内容,(浏览器)客户端需要传递给服务器,以允许服务器代表特定客户端执行操作。
Cheeso

是的,一个cookie。因此,您应该设置服务器和浏览器客户端,以防止跨站点请求伪造。
Marcel

@Marcel我想知道,一旦我们获得了代码,在access_token的帮助下进行交换的方式和地点将获得实际的信息authorization code
chirag soni

14

两者之间的区别在于:

  1. 在隐式流中,令牌直接通过带有“#”号的重定向URL返回,该令牌主要用于没有服务器端的javascript客户端或移动应用程序中,并且在某些实现中客户端无需提供其秘密。

  2. 在授权代码流中,代码以“?”返回 要被服务器端读取,则服务器端这次必须向令牌URL提供客户端机密,以从授权服务器获取令牌作为json对象。如果您拥有可以处理此问题并将应用程序令牌及其个人资料存储在其自己的系统上的应用程序服务器,则该服务器通常用于常见的移动应用程序。

因此,这取决于客户端应用程序的性质,这是一个更安全的“授权代码”,因为它要求客户端上的机密,并且可以在非常安全的连接上在授权服务器和客户端应用程序之间发送令牌。限制某些客户端仅使用“授权码”,并禁止隐式


对于Facebook,授权代码在服务器端存储10分钟。该版本在其2012年12月5日的更改中发布。我的问题主要是,两者在安全性/性能方面有什么区别。我知道这两种流程的作用-但是使用授权代码的优点是-向工作流程增加了一步。
divyanshm

它没有向用户应用程序发送令牌,因此直接隐藏了客户端应用程序和授权服务器之间的连接,正如我提到的那样,这可能是非常安全的通道,与从用户到客户端应用程序的通道不同。
巴瑟姆·雷达·佐迪

在授权代码中的性能,您两次击中auth服务器,因此花费更多时间,而且客户端服务器将存储用户令牌,这也将增加更多时间。
巴瑟姆·雷达·佐迪

2
可以的!我可能忽略了这一点。因此,基本上,授权代码流将由整个服务器作为客户端的系统使用-浏览器发出请求并获取代码。代码被发送到安全连接到资源服务器的客户端服务器。我理解正确吗?访问令牌永远不会到达最终用户的计算机?
divyanshm

1
访问令牌永远不会到达最终用户的计算机?是的,它与客户端应用程序服务器链接到您的配置文件。
巴瑟姆·雷达·佐迪

4

隐式授予类似于授权码授予,但有两个明显的区别。

它旨在用于无法保留客户端秘密的基于用户代理的客户端(例如,单页Web应用程序),因为所有应用程序代码和存储均易于访问。

其次,代替授权服务器返回被交换访问令牌的授权代码,授权服务器返回访问令牌。

请在此处找到详细信息 http://oauth2.thephpleague.com/authorization-server/which-grant/


1
感谢该链接,它帮助我了解了每种资助类型和何时选择每种资助类型之间的区别。
弗朗索瓦POYER


2

让我总结一下我从以上答案中学到的要点,并加深自己的理解。

授权码流程!!!

  • 如果您有充当OAuth客户端的Web应用程序服务器
  • 如果您想长期使用
  • 如果您想离线访问数据
  • 当您负责应用程序进行的api调用时
  • 如果您不想泄漏您的OAuth令牌
  • 如果您不希望应用程序每次需要访问数据时都通过授权流运行。注意:隐式授予流不会接受刷新令牌,因此,如果授权服务器定期使访问令牌到期,则您的应用程序需要访问时,就需要在授权流中运行。

隐式拨款流!!!

  • 当您没有Web应用程序服务器充当OAuth客户端时
  • 如果您不需要长期访问,即仅需要临时访问数据。
  • 如果您信任应用程序运行所在的浏览器,并且访问令牌将泄漏给不受信任的用户,则有一定的顾虑。

2

哪一个更安全,为什么?

两者都是安全的,这取决于您使用它的环境。

当服务器可以直接发出访问令牌时,我看不出在一个工作流程中添加额外步骤(令牌的交换授权代码)的原因。

很简单。您的客户不安全。让我们详细看看。

考虑到您正在针对开发应用程序Instagram API,因此您要向其注册APP Instagram并定义API's所需的应用程序。Instagram将为您提供client_idclient_secrect

在您的网站上,您设置了一个链接,上面写着。“来并使用我的应用程序”。点击该Web应用程序应该2所调用Instagram API

FirstInstagram Authentication Server使用以下参数向发送请求。

1. `response_type` with the value `code`
2. `client_id` you have get from `Instagram`
3. `redirect_uri` this is a url on your server which do the second call
4. `scope` a space delimited list of scopes
5. `state` with a CSRF token. 

您不发送client_secret,您不能信任客户端(尝试使用您的应用程序的用户和/或他的浏览器)。客户端可以看到url或Java脚本并client_secrect轻松找到您。这就是为什么您需要进一步的步骤。

您会收到codestate。在code这里temporary并没有任何地方保存。

然后,您从服务器second拨打电话Instagram API

 1. `grant_type` with the value of `authorization_code`
 2. `client_id` with the client identifier
 3. `client_secret` with the client secret
 4. `redirect_uri` with the same redirect URI the user was redirect back to
 5. `code` which we have already received.

当从我们的服务器发出呼叫时,我们可以安全地使用client_secret(显示我们的状态),code并显示用户已被授予client_id使用该资源的权限。

作为回应,我们将有 access_token


1

从实际角度(我的理解)来看,拥有Authz代码流的主要原因是:

  1. 支持刷新令牌(应用程序代表用户进行长期访问),不支持隐式:请参阅:https : //tools.ietf.org/html/rfc6749#section-4.2
  2. 支持同意页面,该页面是资源所有者可以控制提供什么访问权限的地方(您在google中看到的各种权限/授权页面)。隐式中不存在相同的内容。参见章节:https : //tools.ietf.org/html/rfc6749#section-4.1,点(B)

“授权服务器(通过用户代理)对资源所有者进行身份验证,并确定资源所有者是授予还是拒绝客户端的访问请求”

除此之外,使用刷新令牌,Apps可以长期访问用户数据。


0

到目前为止,似乎没有讨论两个关键点,这解释了为什么授权码授予类型中的弯路会增加安全性。

简短的故事:授权代码授予类型保留浏览器历史记录中的敏感信息,并且令牌的传输仅取决于授权服务器的HTTPS保护。

较长版本:

在下文中,我将坚持使用RFC中定义的OAuth 2术语(这是快速阅读):资源服务器客户端授权服务器资源所有者

假设您希望某些第三方应用程序(=客户端)访问您的Google帐户(=资源服务器)的某些数据。假设Google使用OAuth2。您是Google帐户的资源所有者,但是现在您正在操作第三方应用程序。

首先,客户端打开浏览器以将您发送到Google授权服务器的安全URL。然后,您批准访问请求,授权服务器将您发送回客户端先前提供的重定向URL,并在查询字符串中添加授权代码。现在针对两个关键点:

  1. 此重定向的URL最终出现在浏览器历史记录中。因此,我们在这里不希望使用可直接使用的令牌。短暂的授权码在历史上危险性较小。请注意,隐交付式把令牌的历史。
  2. 此重定向的安全性取决于客户端的HTTPS证书,而不取决于Google的证书。因此,我们获得了客户端的传输安全作为额外的攻击媒介(为避免这种情况的发生,不可避免的是,客户端必须是非JavaScript的。否则,我们可以通过片段URL传输授权代码,而该代码不会通过网络。这可能就是为什么确实使用片段URL的隐式授予类型曾经被推荐用于JavaScript客户端的原因,即使现在不再如此。)

使用授权码授予类型,最终可以通过从客户端到授权服务器的调用获得令牌,其中传输安全性仅取决于授权服务器,而不取决于客户端。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.