OAuth 详解<4> 什么是 OAuth 2.0 隐式授权类型?

demo007x/oauth2-client: Oauth2 Client package for Golang (github.com) 欢迎star

隐式授权类型是单页 JavaScript 应用程序无需中间代码交换步骤即可获取访问令牌的一种方式。它最初是为 JavaScript 应用程序(无法安全存储机密)而创建的,但仅在特定情况下才推荐使用。

这篇文章是我们探索常用的 OAuth 2.0 授权类型系列的第二篇文章。之前我们介绍了授权码授权类型。如果您想在我们开始之前稍微回顾一下并了解有关 OAuth 2.0 的更多信息,请查看OAuth 到底是什么?

什么是 OAuth 2.0 授权类型?

在 OAuth 2.0 中,术语“授权类型”是指应用程序获取访问令牌的方式。OAuth 2.0 定义了几种授权类型,包括授权代码流。OAuth 2.0 扩展还可以定义新的授权类型。

每种授权类型都针对特定用例进行了优化,无论是网络应用程序、本机应用程序、无法启动网络浏览器的设备,还是服务器到服务器的应用程序。

隐性授予

Authorization Code Grant Type 一样,Implicit Grant 首先构建一个链接并将用户的浏览器定向到该 URL。在高层次上,该流程具有以下步骤:

  • 应用程序打开浏览器将用户发送到 OAuth 服务器
  • 用户看到授权提示并批准应用程序的请求
  • 使用 URL 片段中的访问令牌将用户重定向回应用程序

获得用户的许可

OAuth 就是让用户能够授予对应用程序的有限访问权限。应用程序首先需要决定它请求的权限,然后将用户发送到浏览器以获得他们的权限。为开始隐式流程,应用程序构建如下所示的 URL 并将浏览器定向到该 URL。

https://authorization-server.com/auth
 ?response_type=token
 &client_id=29352910282374239857
 &redirect_uri=https%3A%2F%2Fexample-app.com%2Fcallback
 &scope=create+delete
 &state=xcoiv98y3md22vwsuye3kch

以下是对每个查询参数的解释:

  • response_type=token- 这告诉授权服务器应用程序正在启动隐式流。请注意与此值设置为 的授权代码流的区别code
  • client_id- 应用程序的公共标识符,在开发人员首次注册应用程序时获得。
  • redirect_uri- 告诉授权服务器在用户批准请求后将用户发送回何处。
  • scope- 一个或多个空格分隔的字符串,指示应用程序请求的权限。您使用的特定 OAuth API 将定义它支持的范围。
  • state- 应用程序生成一个随机字符串并将其包含在请求中。然后它应该检查在用户授权应用程序后是否返回相同的值。这用于防止 CSRF 攻击。

当用户访问此 URL 时,授权服务器将向他们显示一个提示,询问他们是否愿意授权此应用程序的请求。

OAuth 提示

重定向回应用程序

如果用户批准请求,授权服务器会将浏览器重定向回redirect_uri应用程序指定的位置,并在 URL 的片段部分添加一个tokenand state

例如,用户将被重定向回一个 URL,例如

https://example-app.com/redirect
  #access_token=g0ZGZmNj4mOWIjNTk2Pw1Tk4ZTYyZGI3
  &token_type=Bearer
  &expires_in=600
  &state=xcoVv98y2kd44vuqwye3kcq

请注意这与授权代码流程之间的两个主要区别:返回访问令牌而不是临时代码,并且两个值都在 URL 片段(在 之后)而不是在查询#字符串中返回。通过这样做,服务器确保应用程序能够从 URL 访问该值,但浏览器不会将 HTTP 请求中的访问令牌发送回服务器。

状态值将与应用程序最初在请求中设置的值相同。应用程序应检查重定向中的状态是否与它最初设置的状态相匹配。这可以防止 CSRF 和其他相关攻击。

服务器还将在访问令牌过期之前指示访问令牌的生命周期。这通常是很短的时间,大约 5 到 10 分钟,因为在 URL 本身中返回令牌会带来额外的风险。

此令牌已准备就绪!在应用程序可以开始使用它之前没有额外的步骤!

何时使用隐式授权类型

通常,在极其有限的情况下使用隐式授权类型是有意义的。隐式授权类型是为 JavaScript 应用程序创建的,同时试图比授权代码授权更易于使用。实际上,从最初的简单性中获得的任何好处都会在确保此流程安全所需的其他因素中丢失。如果可能,JavaScript 应用程序应使用不带客户端密码的授权码授权。但是,Okta 授权代码授予需要客户端密码,因此我们采用了下面提到的不同方法。

隐式授权类型的主要缺点是访问令牌直接在 URL 中返回,而不是像授权代码中那样通过受信任的反向通道返回流动。访问令牌本身将记录在浏览器的历史记录中,因此大多数服务器都会发布短期访问令牌以降低访问令牌泄露的风险。因为没有反向通道,隐式流也不返回刷新令牌。为了让应用程序在短期访问令牌过期时获得新的访问令牌,应用程序必须再次通过 OAuth 流程将用户送回,或者使用隐藏的 iframe 等技巧,增加流程最初的复杂性创建以避免。积极的一面是,Okta JavaScript SDK 通过本质上提供“心跳”来让您的访问令牌保持活动状态,从而无缝地处理这个问题。

隐式流使用 URL 片段的历史原因之一是浏览器可以在不触发页面重新加载的情况下操纵 URL 的片段部分。但是,History API现在意味着浏览器可以在不重新加载页面的情况下更新 URL 的完整路径和查询字符串,因此这不再是隐式流程的优势。

使用隐式流的另一个原因是授权服务器不支持或不能支持跨源请求 (CORS)。授权代码授予要求 JavaScript 应用程序向授权服务器发出 POST 请求,因此授权服务器需要支持适当的 CORS 标头才能允许浏览器发出该请求。如果您正在构建自己的授权服务器,这是一个相对容易进行的更改,但如果您使用的是现有服务器,那么您可能无法使用隐式授权来绕过 CORS 限制。

有关这些限制的更多详细信息和其他研究和文档的链接,请查看oauth.net 上的隐式授权类型。

隐式授权类型和 OpenID Connect

在 OpenID Connect 中,服务器id_token除了access_token在 URL 片段中返回一个。这被认为是传输此数据的不安全通道,因为它很容易被篡改。由于 OpenID Connect ID 令牌包含用户身份等声明,因此必须先验证此令牌的签名,然后才能信任它。否则,用户可能会更改令牌中的数据并可能冒充 JavaScript 应用程序中的其他用户。相比之下,当应用程序使用授权代码授权来获取 时id_token,令牌将通过安全的 HTTPS 连接发送,即使令牌签名未经过验证,该连接也能提供基准级别的安全性。

类似的帖子