第 2 章 OAuth之舞

第 2 章 OAuth之舞

本章内容

  • OAuth 2.0协议概述
  • OAuth 2.0系统中的不同组件
  • 不同组件如何相互通信
  • 不同组件交互的内容是什么

现在你已经对OAuth 2.0协议及其重要性有了大致的了解,可能也知道了如何以及何时使用该协议。但发起一个OAuth事务需要哪些步骤?OAuth事务完成的结果是什么?这个设计是如何保证安全的?

2.1 OAuth 2.0协议概览:获取和使用令牌

OAuth是一个复杂的安全协议,它需要不同的组件相互通信,其精准平衡犹如一支技术之舞。但是从根本上说,OAuth事务中的两个重要步骤是颁发令牌和使用令牌。令牌表示授予客户端的访问权,它在OAuth 2.0的各个部分都起到核心作用。尽管每个步骤的细节会因多种因素而异,但是一个规范的OAuth事务包含以下事件。

(1) 资源拥有者向客户端表示他希望客户端代表他执行一些任务(例如“从该服务下载我的照片,我想把它们打印出来”)。

(2) 客户端在授权服务器上向资源拥有者请求授权。

(3) 资源拥有者许可客户端的授权请求。

(4) 客户端接收到来自授权服务器的令牌。

(5) 客户端向受保护资源出示令牌。

OAuth流程的不同部署可以以略微不同的方式处理每一步,通常将多个步骤合并为一个动作以优化流程,但核心流程基本相同。接下来看看最典型的OAuth 2.0示例。

2.2 OAuth 2.0授权许可的完整过程

接下来将详细介绍OAuth授权许可的过程。我们将研究不同参与方的所有不同步骤,追踪每一步的HTTP请求和响应。我们将展示一个基于Web的客户端应用的授权码许可流程。该客户端将以交互方式得到资源拥有者的直接授权。

注意 本章的示例抽取自本书后面会用到的练习代码。虽然在此处你还不需要理解这些练习,但是如果研究一下附录A并试着运行其中一些复杂的示例,可能会对你有所帮助。另外请注意,在这些示例中使用localhost完全不是有意为之,因为OAuth能够也确实会跨多个独立主机工作。

授权码许可中用到了一个临时凭据——授权码——来表示资源拥有者同意向客户端授权,如图2-1所示。

图 2-1 授权码许可的详细过程

我们具体介绍一下这些步骤。首先,资源拥有者访问客户端应用,并表明他希望客户端代表自己去使用某一受保护资源。例如,用户会在这一步示意打印服务去使用某个照片存储服务。该服务是个API,客户端知道如何调用它,并且还知道需要通过OAuth来调用。

如何发现服务器?

为了最大限度地保持灵活性,OAuth协议去除了真实API系统的很多细节。具体来说,OAuth没有规定客户端如何知悉与受保护资源交互的方式,或者客户端如何发现受保护资源对应的授权服务器。这些问题一般都由建立在OAuth之上的其他协议以标准方式解决,例如OpenID Connect和User Managed Access(UMA),第13章和第14章将详细讨论。为了阐述OAuth本身,我们假设客户端已有静态配置,知道如何与受保护资源和授权服务器交互。

当客户端发现需要获取一个新的OAuth访问令牌时,它会将资源拥有者重定向至授权服务器,并附带一个授权请求,表示它要向资源拥有者请求一些权限(如图2-2所示)。例如,为了能读取照片,照片打印服务可以向照片存储服务请求访问权限。

图 2-2 将资源拥有者引导至授权服务器以启动授权流程

由于我们使用的是Web客户端,因此采用HTTP重定向的方式将用户代理重定向至授权服务器的授权端点。客户端应用的响应如下所示:

HTTP/1.1 302 Moved Temporarily
x-powered-by: Express
Location: http://localhost:9001/authorize?response_type=code&scope=foo&client_id=oauth-client-1&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1
Vary: Accept
Content-Type: text/html; charset=utf-8
Content-Length: 444
Date: Fri, 31 Jul 2015 20:50:19 GMT
Connection: keep-alive

这个重定向响应导致浏览器向授权服务器发送一个GET请求。

GET /authorize?response_type=code&scope=foo&client_id=oauth-client-1&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1 HTTP/1.1
Host: localhost:9001
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0)Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://localhost:9000/
Connection: keep-alive

客户端通过在发送给用户的URL中包含查询参数,来标识自己的身份和要请求的授权详情,如权限范围等。虽然请求并不是由客户端直接发出的,但授权服务器会解析这些参数并做出适当的反应。

HTTP事务查看

所有的HTTP事务都是使用现成的工具查看的,而且这样的工具有很多。像Firefox插件Firebug这样的浏览器检查工具,可以全方位监控和处理前端信道通信。后端信道通信则可以使用代理系统或者网络数据包抓取工具(如Wireshark或者Fiddler)来监控。

然后,授权服务器会要求用户进行身份认证。这一步对确认资源拥有者的身份以及能向客户端授予哪些权限来说至关重要(如图2-3所示)。

图 2-3 资源拥有者登录

用户身份认证直接在用户(和用户的浏览器)与授权服务器之间进行,这个过程对客户端应用不可见。这一重要特性避免了用户将自己的凭据透露给客户端应用,对抗这种反模式正是发明OAuth的原因(前一章已讨论)。

另外,因为资源拥有者通过浏览器与授权端点交互,所以也要通过浏览器来完成身份认证。因此,有很多身份认证技术可以用于用户身份认证流程。OAuth没有规定应该使用哪种身份认证技术,授权服务器可以自由选择,例如用户名/密码、加密证书、安全令牌、联合单点登录或者其他方式。在此我们不得不在一定程度上信任Web浏览器,特别是当资源拥有者使用像用户名和密码这样的简单身份认证方式时。但是OAuth的设计已经考虑了如何防止多种基于浏览器的攻击,我们将在第7~9章介绍。

这种隔离方案还使得客户端不会因用户身份认证方式发生变化而受到影响,让简单的客户端应用也能受益于授权服务器使用的一些新兴技术,例如基于风险的启发式认证(risk-based heuristic authentication)技术。然而,这种做法并没有向客户端传递任何有关认证用户的信息,第13章会深入讨论这个话题。

然后,用户向客户端应用授权(如图2-4所示)。在这一步,资源拥有者选择将一部分权限授予客户端应用,授权服务器提供了许多不同的选项来实现这一点。客户端可以在授权请求中指明其想要获得哪些权限(称为OAuth权限范围,将在2.4节中讨论)。授权服务器可以允许用户拒绝一部分或者全部权限范围,也可以让用户批准或者拒绝整个授权请求。

图 2-4 资源拥有者批准客户端的授权请求

此外,很多授权服务器允许将授权决策保存下来,以便以后使用。如果使用了这种方式,那么未来同一个客户端请求同样的授权时,用户将不会得到提示。用户仍然会被重定向到授权端点,并且仍然需要登录,但是会跳过批准授权环节而沿用前一次的授权决策。授权服务器甚至可以通过像客户端白名单或黑名单这样的内部策略来否决用户的决策。

然后,授权服务器将用户重定向回客户端应用(如图2-5所示)。

图 2-5 将授权码发送给客户端

这一步采用HTTP重定向的方式,回到客户端的redirect_uri

HTTP 302 Found
Location: http://localhost:9000/oauth_callback?code=8V1pr0rJ&state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1

这又会导致浏览器向客户端发出如下请求。

GET /callback?code=8V1pr0rJ&state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1
HTTP/1.1 Host: localhost:9000

请注意,这个HTTP请求是发送给客户端而不是授权服务器的。

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0)
Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://localhost:9001/authorize?response_type=code&scope=foo&client_id=oauth-client-1&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&
state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1
Connection: keep-alive

由于使用的是授权码许可类型,因此该重定向链接中包含一个特殊的查询参数code。这个参数的值被称为授权码,它是一次性的凭据,表示用户授权决策的结果。客户端会在接收到请求之后解析该参数以获取授权码,并在下一步使用该授权码。客户端还会检查state参数值是否与它在前一个步骤中发送的值匹配。

现在客户端已经得到授权码,它可以将其发送给授权服务器的令牌端点(如图2-6所示)。

图 2-6 客户端将授权码和自己的凭据发送给授权服务器

客户端发送一个POST请求,在HTTP主体中以表单格式传递参数,并在HTTP基本认证头部中设置client_idclient_secret。这个HTTP请求由客户端直接发送给授权服务器,浏览器或者资源拥有者不参与此过程。

POST /token
Host: localhost:9001
Accept: application/json
Content-type: application/x-www-form-encoded
Authorization: Basic b2F1dGgtY2xpZW50LTE6b2F1dGgtY2xpZW50LXNlY3JldC0x

grant_type=authorization_code&
redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&code=8V1pr0rJ

这种将不同的HTTP连接分开的做法保证了客户端能够直接进行身份认证,让其他组件无法查看或者操作令牌请求。

授权服务器接收该请求,如果请求有效,则颁发令牌(如图2-7所示)。授权服务器需要执行多个步骤以确保请求是合法的。首先,它要验证客户端凭据(通过Authorization头部传递)以确定是哪个客户端请求授权。然后,从请求主体中读取code参数的值,并从中获取关于该授权码的信息,包括发起初始授权请求的是哪个客户端,执行授权的是哪个用户,授权的内容是什么。如果授权码有效且尚未使用过,而且发起该请求的客户端与最初发起授权请求的客户端相同,则授权服务器会生成一个新的访问令牌并返回给客户端。

图 2-7 客户端接收访问令牌

该令牌以JSON对象的格式通过HTTP响应返回给客户端。

HTTP 200 OK
Date: Fri, 31 Jul 2015 21:19:03 GMT
Content-type: application/json

{
  "access_token": "987tghjkiu6trfghjuytrghj",
  "token_type": "Bearer"
}

然后客户端可以解析令牌响应并从中获取令牌的值来访问受保护资源。在这个案例中,我们使用了OAuth bearer令牌,这是通过响应中的token_type字段描述的。令牌响应中还可以包含一个刷新令牌(用于获取新的访问令牌而不必重新请求授权),以及一些关于访问令牌的附加信息,比如令牌的权限范围和过期时间。客户端可以将访问令牌存储在一个安全的地方,以便以后在用户不在场时也能够随时使用。

bearer令牌的使用权

OAuth核心规范对bearer令牌的使用做了规定,无论是谁,只要持有bearer令牌就有权使用它。除非特别注明,本书中所有的示例都使用bearer令牌。bearer令牌具有特殊的安全属性,这将在第10章列举,第15章将先介绍非bearer令牌。

有了令牌,客户端就可以在访问受保护资源时出示令牌(如图2-8所示)。

图 2-8 客户端使用访问令牌执行任务

客户端出示令牌的方式有多种,本例中将使用备受推荐的方式:使用Authorization头部。

GET /resource HTTP/1.1
Host: localhost:9002
Accept: application/json
Connection: keep-alive
>Authorization: Bearer 987tghjkiu6trfghjuytrghj

受保护资源可以从头部中解析出令牌,判断它是否有效,从中得知授权者是谁以及授权内容,然后返回响应。受保护资源检查令牌的方式有多种,这将在第11章深入讨论。最简单的方式是让授权服务器和资源服务器共享存储令牌信息的数据库。授权服务器在生成新的令牌时将其写入数据库,资源服务器在收到令牌时从数据库中读取它们。

2.3 OAuth中的角色:客户端、授权服务器、资源拥有者、受保护资源

如上一节所讨论的,OAuth系统中有4个主要的角色:客户端、授权服务器、资源拥有者以及受保护资源(如图2-9所示)。这些组件分别负责OAuth协议的不同部分,并且相互协作使OAuth协议运转。

图 2-9 OAuth 2.0协议中的重要组件

OAuth客户端是代表资源拥有者访问受保护资源的软件,它使用OAuth来获取访问权限。得益于OAuth的设计,客户端通常是OAuth系统中最简单的组件,它的职责主要是从授权服务器获取令牌以及在受保护资源上使用令牌。客户端不需要理解令牌,也不需要查看令牌的内容。相反,客户端只需要将令牌视为一个不透明的字符串即可。OAuth客户端可以是Web应用、原生应用,甚至浏览器内的JavaScript应用,第6章将介绍这些客户端类型之间的区别。在云打印例子中,打印服务就属于OAuth客户端。

受保护资源能够通过HTTP服务器进行访问,在访问时需要OAuth访问令牌。受保护资源需要验证收到的令牌,并决定是否响应以及如何响应请求。在OAuth架构中,受保护资源对是否认可令牌拥有最终决定权。在云打印例子中,照片存储网站就属于受保护资源。

资源拥有者是有权将访问权限授权给客户端的主体。与OAuth系统中的其他组件不同,资源拥有者不是软件。在大多数情况下,资源拥有者是一个人,他使用客户端软件访问受他控制的资源。至少在部分过程中,资源拥有者要使用Web浏览器(通常称为用户代理)与授权服务器交互。资源拥有者可能还会使用浏览器与客户端交互,如这里所展示的,但这完全取决于客户端性质。在云打印例子中,资源拥有者就是想要打印照片的最终用户。

OAuth授权服务器是一个HTTP服务器,它在OAuth系统中充当中央组件。授权服务器对资源拥有者和客户端进行身份认证,让资源拥有者向客户端授权、为客户端颁发令牌。某些授权服务器还会提供额外的功能,例如令牌内省、记忆授权决策。在云打印例子中,照片存储网站拥有自己的授权服务器,用于保护其资源。

2.4 OAuth的组件:令牌、权限范围和授权许可

除了上述这些角色之外,OAuth生态系统还依赖其他几种机制,概念性的和实体性的都有。它们将上一节中的各个角色整合成一个协议。

2.4.1 访问令牌

OAuth访问令牌,有时也简称为令牌,由授权服务器颁发给客户端,表示客户端已被授予权限。OAuth并没有定义令牌本身的格式和内容,但它总是代表着:客户端请求的访问权限、对客户端授权的资源拥有者,以及被授予的权限(通常包含一些受保护资源标识)。

OAuth令牌对于客户端来说是不透明的,也就是说客户端不需要(通常也不能)查看令牌内容。客户端要做的就是持有令牌,向授权服务器请求令牌,并向受保护资源出示令牌。OAuth令牌并非对系统中的所有组件都不透明:授权服务器的任务是颁发令牌,受保护资源的任务则是验证令牌。因此,它们都需要理解令牌本身,并知道其含义。然而,客户端对这一切一无所知。这使得客户端简单得多,同时也使得授权服务器和受保护资源可以十分灵活地部署令牌。

2.4.2 权限范围

OAuth的权限范围表示一组访问受保护资源的权限。OAuth协议中使用字符串表示权限范围,可以用空格分隔的列表将它们合并为一个集合。因此,权限范围的值不能包含空格。OAuth并没有规定权限范围值的格式和结构。

权限范围是一种重要机制,它界定了客户端获取的权限范围。权限范围是由受保护资源根据其自身提供的API来定义的。客户端可以请求某些权限范围,授权服务器则允许资源拥有者在客户端发出请求时许可或者否决特定的权限范围。权限范围具有可叠加的特性。

回到云打印的例子,照片存储服务的API为照片访问定义了多种权限范围:read-photoread-metadataupdate-photoupdate-metadatacreatedelete。照片打印服务只要能读取照片就足以完成工作,所以它会请求read-photo权限范围。只要拥有一个该权限范围的令牌,它就能够读取照片并按要求打印出来。如果用户想要使用依据照片日期将照片打印成册的高级功能,则打印服务还需要read-metadata权限范围。由于这是一个额外的访问权限,照片打印服务需要通过正常的OAuth流程来请求用户授予它这个额外的权限范围。只要照片打印服务拥有包含这两个权限范围的令牌,它就能使用该令牌执行相应的操作。

2.4.3 刷新令牌

OAuth刷新令牌在概念上与访问令牌很相似,它也是由授权服务器颁发给客户端的令牌,客户端也不知道或不关心该令牌的内容。但不同的是,该令牌从来不会被发送给受保护资源。相反,客户端使用刷新令牌向授权服务器请求新的访问令牌,而不需要用户参与(如图2-10所示)。

图 2-10 使用刷新令牌

为什么客户端需要刷新令牌?在OAuth中,访问令牌随时可能失效。令牌有可能被用户撤销,也可能过期,或者其他系统导致令牌失效。访问令牌失效后,客户端在使用时会收到错误响应。当然,客户端可以再次向资源拥有者请求权限,但是如果资源拥有者不在场呢?

在OAuth 1.0中,客户端除了等资源拥有者回来重新授权之外别无他法。为避免这种情况,OAuth 1.0中的令牌往往会一直保持有效,直到被明确地撤销。这是有问题的,因为它增加了被盗令牌的攻击面:攻击者可以永久使用该令牌。OAuth 2.0提供了让令牌自动过期的选项,但是我们需要在用户不在场的时候仍然能访问资源。现在,刷新令牌取代了永不过期的访问令牌,但它的作用不是访问资源,而是获取新的访问令牌来访问资源。这种做法以一种独立但互补的方式限制了刷新令牌和访问令牌的暴露范围。

刷新令牌还可以让客户端缩小它的权限范围。如果客户端被授予A、B、C三个权限范围,但是它知道某特定请求只需要A权限范围,则它可以使用刷新令牌重新获取一个仅包含A权限范围的访问令牌。这让足够智能的客户端可以遵循最小权限安全原则,但也不会给不那么智能的客户端带来负担,即无须查明某个API需要哪些权限。虽然多年的部署经验表明,OAuth客户端往往并不智能,但是对于那些想要实践这种智能的客户端来说,这一高级功能还是很有价值的。

如果刷新令牌本身也失效了怎么办?如果用户在场,客户端可以随时劳烦用户再次授权。换句话说,客户端退回到了需要重新进行OAuth授权的状态。

2.4.4 授权许可

授权许可是OAuth协议中的权限获取方法,OAuth客户端用它来获取受保护资源的访问权限,成功之后客户端会得到一个令牌。这可能是OAuth 2.0中最令人困惑的术语之一,因为它既表示用户授权所用的特定方式,也表示授权这个行为本身。前面详细介绍过的授权码许可类型加剧了这种困惑,因为开发人员有时候会看见传回给客户端的授权码,并误以为这个授权码(仅授权码)就是授权许可。虽然授权码确实代表用户的授权决策,但它不是授权许可本身。相反,整个OAuth流程才是授权许可:客户端将用户重定向至授权端点,然后接收授权码,最后用授权码换取令牌。

换句话说,授权许可就是获取令牌的方式。在本书中,就像在OAuth社区中一样,会偶尔将其称为OAuth协议的一个流程。OAuth协议中有多种授权许可方法,并且各有特点。第6章将对这些许可类型进行详细介绍,但是大部分例子和练习(如上一节中的那样)都使用了授权码这种授权许可类型。

2.5 OAuth的角色与组件间的交互:后端信道、前端信道和端点

了解OAuth系统的不同部分之后,现在来看看它们之间到底是如何通信的。OAuth是一个基于HTTP的协议,但是与大多数基于HTTP的协议不同,OAuth中的交互并不总是通过简单的HTTP请求和响应来完成。

非HTTP信道之上的OAuth

虽然OAuth是基于HTTP的协议,但已有很多规范定义了如何将OAuth流程中的不同部分迁移到非HTTP协议上。例如,已经有标准草案提出了如何在通用安全服务应用程序接口(GSS-API)1和受限应用程序协议(CoAP)2上使用OAuth令牌。在这些草案中,仍然可以使用HTTP来启动OAuth流程,但它们是想将基于HTTP的OAuth组件直接搬到其他协议上去。

1RFC 7628:https://tools.ietf.org/html/rfc7628

2https://tools.ietf.org/html/draft-ietf-ace-oauth-authz

2.5.1 后端信道通信

OAuth流程中的很多部分都使用标准的HTTP请求和响应格式来相互通信。由于这些请求通常都发生在资源拥有者和用户代理的可见范围之外,因此它们统称为后端信道通信(如图2-11所示)。

这些请求和响应使用了所有常规的HTTP机制来通信:头部、查询参数、HTTP方法和HTTP主体都能承载对OAuth事务至关重要的信息。请注意,由于多数简单的Web API只需要客户端开发人员关注响应主体,这可能包含了你不熟悉的一些HTTP机制。

授权服务器提供了一个授权端点,供客户端请求访问令牌和刷新令牌。客户端直接向该端点发出请求,携带一组表单格式的参数,授权服务器解析并处理这些参数。然后授权服务器返回一个代表令牌的JSON对象。

图 2-11 后端信道通信

另外,当客户端连接受保护资源的时候,它也是在后端信道上直接发出HTTP请求。这种连接的细节完全依赖于受保护资源,因为OAuth能保护的API和系统种类繁多、风格各异。对于任何类型的受保护资源,都需要客户端出示令牌,并且受保护资源必须能理解令牌及其代表的权限。

2.5.2 前端信道通信

在前一节中已经看到,在标准的HTTP通信中,HTTP客户端向服务器直接发送一个请求,其中包含头部、查询参数、主体及其他信息。然后HTTP服务器可以查看这些信息,并决定如何响应请求,响应中包含头部、主体及其他信息。然而,在OAuth中,在某些情况下两个组件是无法直接相互发送请求和响应的,例如客户端与授权服务器的授权端点交互的时候。前端信道通信就是一种间接通信方法,它将Web浏览器作为媒介,使用HTTP请求实现两个系统间的间接通信(如图2-12所示)。

图 2-12 前端信道通信

这一技术隔离了浏览器两端的会话,实现了跨安全域工作。例如,如果用户需要向其中一个组件进行身份认证,并不需要将凭据暴露给另一个系统。这样,在保持信息隔离的情况下,仍然能让用户在通信中发挥作用。3

3虽然不向客户端暴露凭据,但用户仍然能在经过身份认证之后做出授权决策,该授权结果(即授权码)正是通过这样的间接通信方式传递到客户端的。——译者注

两个不直接交互的软件是如何实现通信的呢?前端信道通信是这样实现的:发起方在一个URL中附加参数并指示浏览器跳转至该URL。然后接收方可以解析该入站URL(由浏览器跳转来的),并使用其中包含的信息。之后,接收方可以将浏览器重定向至发起方托管的URL,并使用同样的方式在URL中附加参数。这样,两个软件就以Web浏览器为媒介,实现了间接通信。这意味着每个前端信道的请求和响应实际上是一对HTTP请求/响应事务(如图2-13所示)。

图 2-13 前端信道的请求和响应流程

例如,在前面看到的授权码许可中,客户端需要将用户重定向至授权端点,但是也需要将其请求的内容信息传递给授权服务器。为此,客户端向浏览器发送一个HTTP重定向。这个重定向的目标是授权服务器的URL,并且其查询参数中附有特定参数。

HTTP 302 Found
Location: http://localhost:9001/authorize?client_id=oauth-client-1&response_type=code&state=843hi43824h42tj

授权服务器可以像处理一般的HTTP请求一样解析传入的URL,从参数中获取信息。在这个环节,授权服务器可以与资源拥有者进行交互,通过浏览器执行一系列HTTP事务,对资源拥有者进行身份认证并请求其授权。当需要给客户端返回授权码时,授权服务器也向浏览器返回重定向响应,但是这一次的重定向目标是客户端的redirect_uri。授权服务器也会在重定向的查询参数中附带信息。

HTTP 302 Found
Location: http://localhost:9000/oauth_callback?code=23ASKBWe4&state=843hi43824h42tj

浏览器执行这个重定向时,会向客户端应用发送一个HTTP请求。然后客户端可以解析请求中的参数。这样,客户端和授权服务器就以浏览器为媒介实现了通信,而不用直接交互。

如果我的客户端不是Web应用怎么办?

Web应用和原生应用都可以使用OAuth,但是都需要使用前端信道机制来接收授权端点返回的信息。前端信道通常需要用到Web浏览器和HTTP重定向,但常规的Web服务器一般是不提供这些支持的。幸运的是,有一些技巧可以解决这个问题,比如内部Web服务器、应用专有的URI方案、使用后端服务向客户端推送通知等。总之,只要能触发浏览器对该URI的调用即可。第6章将详细探讨这些技巧。

所有通过前端信道传递的信息都可供浏览器访问,既能被读取,也可能在最终请求发出之前被篡改。OAuth协议已经考虑到这一点,它限制了能通过前端信道传输的信息类别,并确保只要是通过前端信道传输的信息,就不能在授权任务中单独使用。在本章的典型案例中,授权码不能被浏览器直接使用,相反它必须通过后端信道与客户端凭据一起出示。在有些协议中,比如OpenID Connect,要求客户端或者授权服务器对前端信道中传输的消息签名,通过这样的安全机制增加一层保护。第13章将对此进行简要介绍。

2.6 小结

虽然OAuth协议包含很多移动组件,但它将一些简单的操作组合起来,形成了一套安全的授权方法。

  • OAuth是关于获取令牌使用令牌的。
  • OAuth系统中的不同组件各自负责授权流程中的不同环节。
  • 组件使用直接的(后端信道)和间接的(前端信道)HTTP连接相互通信。

现在,你已经了解了OAuth是什么以及它的工作原理,开始动手做点事情吧!下一章将介绍如何从头开始构建一个OAuth客户端。

目录