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

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

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

这两种方法在安全性方面有何不同?哪一个更安全,为什么?

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

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

65117 次浏览

两者的区别在于:

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

  2. 在授权代码流中,返回的代码带有“?”,以便服务器端可以读取,然后服务器端必须提供客户端密码,这一次是令牌URL,以便从授权服务器获取作为JSON对象的令牌。如果您的应用程序服务器可以处理此问题,并将用户令牌与他/她的配置文件存储在他自己的系统上,则可以使用它,并且它主要用于常见的移动应用程序。

因此,这取决于您的客户端应用程序的性质,哪一个更安全的“授权码”可以在客户端上请求秘密,并且令牌可以在非常安全的连接上在授权服务器和客户端应用程序之间发送,并且授权提供程序可以限制某些客户端仅使用“授权码”并且不允许隐式

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

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

因此,需要仔细检查:拥有通过API显示的资源的用户和使用该API的客户端(例如,Web应用程序)。两者都要经过验证才能授予访问权限。注意这里OAuth的“授权”性质:用户将其资源的访问权限(通过身份验证后返回的code)授予应用程序,应用程序获取access_token,并代表用户进行调用。

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

隐式流通常用于不建议存储client idclient secret的情况(例如,设备,尽管许多设备无论如何都会这样做)。这就是免责声明的意思。人们可以访问客户端代码,因此可以获得凭据并假装成为资源客户端。在隐式流中,所有数据都是易变的,应用程序中没有存储任何内容。

我将在这里补充一些我认为在上面的回答中没有说清楚的东西:

  • 授权代码流允许最终的访问令牌永远不会到达,也永远不会存储在具有浏览器/应用程序的计算机上。将临时授权代码提供给具有浏览器/应用程序的机器,然后将其发送到服务器。然后,服务器可以将其与完全访问令牌进行交换,并访问API等。使用浏览器的用户只能通过使用令牌的服务器访问API.
  • 隐式流只能涉及两方,并且最终访问令牌与浏览器/应用程序一起存储在客户端上。。如果此浏览器/应用程序受到危害,则其授权令牌也会受到危害,这可能是危险的。

热释光;博士如果您不信任用户计算机持有令牌,但信任您自己的服务器,则不要使用隐式流。

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

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

其次,不是授权服务器返回与访问令牌交换的授权码,而是授权服务器返回访问令牌。

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

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

  1. 支持刷新令牌(代表用户的应用程序的长期访问),不隐式支持:请参阅:https://www.rfc-editor.org/rfc/rfc6749#section-4.2
  2. 支持同意页面,这是一个资源所有者可以控制提供哪些访问权限的地方(您在Google中看到的权限/授权页面)。同样不存在于含蓄之中。请参阅“https://www.rfc-editor.org/rfc/rfc6749#section-4.1 ”部分的第(B)点。

";授权服务器(通过用户代理)对资源所有者进行认证,并确定资源所有者是否同意或拒绝客户机的访问请求

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

让我总结一下我从上面的答案中学到的要点,并补充一些我自己的理解。

授权码流!

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

隐式授予流!

  • 当您没有Web应用程序服务器充当OAuth客户端时
  • 如果您不需要长期访问,即只需要临时访问数据。
  • 如果您信任应用程序运行的浏览器,并且不太担心访问令牌会泄露给不受信任的用户。

哪一个更安全,为什么?

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

我不明白为什么额外的步骤(交换授权码 FOR TOKEN)添加到一个工作流中时,服务器可以直接 颁发访问令牌。

这很简单。你的客户并不安全。让我们来看看它的细节。

假设您正在针对Instagram API开发应用程序,因此您向Instagram注册了您的应用程序,并定义了您需要的API'sInstagram将为您提供client_idclient_secrect

在你的网站上,你设置了一个链接,上面写着来使用我的应用";。单击此按钮,您的Web应用程序将使调用Instagram API

First使用以下参数向Instagram 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是ABC_3的_,不会保存在任何位置。

然后,从服务器向Instagram API发出second调用。

 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

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

短篇小说:授权码授予类型保留浏览器历史记录中的敏感信息,令牌的传输仅依赖于授权服务器的HTTPS保护。

较长版本:

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

假设您想要一些第三方应用程序(=客户端)来访问您的Google帐户(=资源服务器)的某些数据。让我们假设Google使用OAuth 2。您是Google帐户的资源所有者,但现在您操作第三方应用程序。

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

  1. 此重定向的URL最终出现在浏览器历史记录中。因此,我们不希望在这里使用寿命长、直接可用的访问令牌。在历史上,短期授权码的危险性较小。注意,隐式授权类型确实将令牌置于历史中。
  2. 这种重定向的安全性取决于客户端的HTTPS证书,而不是Google的证书。因此,我们将客户端的传输安全性作为额外的攻击向量。(为了避免这种情况,客户端必须是非JavaScript的。否则,我们可以通过片段URL传输授权码,而代码不会通过网络。(这可能是隐式授权类型(确实使用片段URL)过去被推荐给JavaScript客户机的原因,即使现在已经不是这样了。)

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

不应再使用隐式授权,有关详细信息,请参阅IETF当前最佳实践。https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-18#section-2.1.2

作为替代,使用具有响应类型代码流;对于无法安全存储客户端凭据的客户端,您应该选择使用PKCE流的授权码。