06. 千呼万唤始出来:最重要的授权方式——授权码模式

正如前文所说,授权码模式是四种授权模式中最为复杂,但也是最为安全和推荐的授权模式。简化模式与授权码模式如出一辙,理解了授权码模式也就理解了简化模式。下面的时序图说明了授权码模式工作的流程。
[图片]

  1. 终端用户通过浏览器访问第三方应用。
  2. 第三方应用程序初始化授权请求将用户浏览器重定向到授权服务器的授权端点。
  3. 如果用户没有在授权服务器的域下登录,则授权服务器将引导用户进行登录。否则直接向用户展示授权页面。
  4. 用户登录并且同意授权。
  5. 授权服务器将用户浏览器重定向回第(2)步授权请求中的授权回调URI,并且附带了一个临时的授权码,该授权码经过终端用户的浏览器,它对终端用户是可见的。
  6. 第三方应用程序初始化令牌请求,向授权服务器的令牌端点发送令牌请求,目的是使用上一步获得的授权码换取代表终端用户访问资源的“钥匙”——访问令牌。
  7. 授权服务器向第三方应用程序颁发访问令牌和可选的刷新令牌,这一步是通过HTTPS直接发生在第三方应用程序和授权服务器之间通信过程。客户端收到的访问令牌对终端用户是不可见的,相对于授权码,这一步第三方应用程序收到的访问令牌对终端用户是不可见的。终端用户安全地收到了访问令牌,并且安全地将其保存在了服务器端。
  8. 第三方应用程序使用上面收到的访问令牌向资源服务器的资源端点发起资源调用请求,换取终端用户的资源。
  9. 资源服务器向第三方应用程序返回资源调用结果。
  10. 第三方应用程序处理用户资源,并将结果通过浏览器返回给终端用户。

在授权码模式中客户端为了从授权服务器处获取到访问令牌必须向授权服务器发送两个请求。第一个请求被称作是授权请求(Authorization Request) ,如上图中的第(2)步所示。客户端首先将用户的浏览器重定向到授权服务器的授权端点,在重定向请求中携带了客户端想请求的权限列表以及其他一些必要的参数,授权服务器校验授权请求的合法性(客户端ID是否存在、scope参数是否越权等)后,向用户展示授权页面。用户同意授权后,授权服务器将用户浏览器重定向回客户端,并追加一个授权码。客户端在获得授权码后使用授权代码向授权服务器的令牌端点发送第二个请求以获取访问令牌,第二个请求被称作是访问令牌请求(Access Token Request) ,如上图中的第(6)步所示。该请求直接发生在客户端应用程序后端和授权服务器之间,对终端用户不可见。授权服务器在校验访问令牌请求的合法性后向客户端颁发访问令牌,该访问令牌可用于调用API。我将在下一小节详细向你介绍这两个请求的具体内容。

换个视角看授权码模式

因为授权码模式是重要和最为推荐的模式,为了更清楚地理清授权码模式的工作流程,我们换个视角看授权码模式。下图展示了客户端如何与授权服务器交互,以获得用户同意,并最终代表用户执行API请求的过程。
在这里插入图片描述

  1. 当客户端首次需要访问当前用户“托管”在资源服务器上的资源或者首次需要访问它还没有访问权限的其他资源时,客户端将初始化授权请求,并将当前资源拥有者(Resource Owner)重定向 到授权服务器的授权端点。如上图第(1)和第(2)步所示。
  2. 权服务器必须知道是哪个客户端代表哪个资源拥有者来获取授权,因此授权服务器的授权端点(Authorization Endpoint)一定是一个需要用户认证通过才能访问的端点。如果用户没有登录,则授权服务器将用户重定向到授权服务器的登录页面提示终端用户进行登录,否则直接展示授权页面,向资源拥有者问询授权许可。这是上图第(3)步到第(6)步发生的情况。
  3. 用户确认授权信息并同意授权(用户可能缩小客户端申请的授权范围,例如客户端向用户申请read、write的权限,终端用户认为write权限不应当授予当前客户端,所以用户在这个阶段缩小了授权范围)。如上图第(7)步所示。
  4. 用户同意授权后,授权服务器将生成一个较短生命周期的授权码(Authorization Code),并将该授权码重定向回客户端在第一步授权请求携带的授权回调URI。如上图第(8)步所示。
  5. 授权服务器解析收到的授权码,并组装第二个请求——令牌请求(Access Token Request)。第二个请求是一个后端信道的通信,客户端 server 端直接向授权服务器令牌端点发起一个Web API调用。这个请求的关键参数是客户端携带了自己“藏在”服务器端的客户端密钥 。如上图第(9)步所示。
  6. 授权服务器校验授权码和客户端密钥、客户端ID等信息正确后,响应访问令牌(如果授权服务器支持刷新令牌,还会向客户端响应一个Refresh Token。该令牌是否颁发取决于授权服务器的具体实现,例如Google OAuth 平台向客户端提供了一个额外的参数——access_type,由客户端来决定是否需要这个Refresh Token。我将在后面向你展示这些技术的细节)。这是第(10)步发生的情况。
  7. 在收到访问令牌后,客户端将携带该访问令牌扮演用户的角色去访问用户托管在授权服务器上的资源或服务。这同样是一个后端信道的通信,此时需要客户端初始化第三个请求——资源访问请求。这是发生在上图A到D的情况。

授权码存在的必要性

我们知道,访问令牌是高度敏感和重要的信息,你可以把它想象成你家里的钥匙,任何持有钥匙的人都可以随意进出你的家门,一旦钥匙遗失或被窃取,将会造成恶劣的影响。一个原则是访问令牌不应该通过前端浏览器传递,而是应该通过安全的后端通道获取和传递。
注意我在上图中第(2)步和第(8)步的重定向请求,在第(2)步中客户端将用户浏览器重定至授权服务器的授权端点,让资源拥有者和授权服务器发生关系。在第(7)步中,资源拥有者点击“允许”同意了来自客户端的授权请求,授权服务器的授权端点(Authorization Endpoint)在收到终端用户的确认信息后,有两种处理方式:

  1. 直接重定向到客户端回调地址并附带访问令牌。
  2. 重定向返回一个临时的授权码,由客户端后端组装令牌请求(包含授权码和客户端密钥等信息),与授权服务器交互请求访问令牌。
    第一种方式 OAuth 2 四种授权模式里的简化模式 ,它不安全的首要原因显而易见,浏览器的历史记录或者 HTTP 的 Referer 头都有可能导致访问令牌泄露。在 OAuth 2.1 中这种方式已经被彻底废弃了。第二种方式将一个临时的授权码传递给客户端后端,由后端发起 Web API 调用来交换安全性极高的访问令牌,令牌的获取和使用发生在安全的后端信道,作为终端用户(资源拥有者)始终不会看到该访问令牌!

为什么必须使用重定向技术

可能有同学想为什么必须通过重定向的方式,授权服务器的授权端点(Authorization Endpoint)在收到资源拥有者的确认信息后直接通过后端Web API的调用方式向客户端后端响应一个访问令牌,这样做不是更简单么!
重定向技术是保证终端用户、客户端和授权服务器之间连贯沟通的核心!
我在上图中少画了一个重要的角色——操作代理即浏览器。下图我将第(1)步、第(2)步和第(8)步替换成了操作代理对象。在第(1)步中资源所有者一定是通过操作代理即浏览器访问客户端程序,从A到D步骤在客户端获得访问令牌然后获取资源后必须要将资源的处理结果返回给终端用户。使用重定向技术相当于“浏览器代替用户发起了一次请求”,两次关键的重定向都是一样的作用。在第(8)步中授权端点重定向后浏览器这个代理将授权码传递给了客户端后端,客户端使用授权码后将资源处理结果响应给了终端用户。如果直接通过Web API的调用响应访问令牌,那么终端用户和客户端之间也就断了联系,客户端无法再将资源处理的结果响应给客户端。
[图片]

总结

在今天的小节中我向你介绍了最重要的授权模式——授权码模式。这个过程虽然复杂,但是从OAuth四个角色各自的视角来看,却格外简单和清晰。例如从终端用户的视角看,他在整个流程中只做了两件事,登录授权服务器和做授权决策,终端用户不用关心背后复杂的流转过程。从客户端的视角看它做了三件事——发送授权请求、发送访问令牌请求、携带访问令牌访问资源请求。授权服务器的实现就略显复杂,对应客户端发送的授权请求和访问令牌请求,它需要分别暴露两个端点——授权端点(Authorization Endpoint)和令牌端点(Token Endpoint),对应客户端的资源请求,授权服务器则需要暴露一个令牌自省端点(Token Introspection Endpoint)。现在这一切是不是很清晰了呢!
[图片]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值