OAuth2(一)——核心概念

OAuth 2.0 是什么

OAuth 2.0 是一个授权协议,它允许软件应用代表(而不是充当)资源拥有者去访问资源拥有者的资源。应用向资源拥有者请求授权,然后取得令牌(token),并用它来访问资源。这一切都不需要应用去充当资源拥有者的身份,因为令牌明确表示了被授予的访问权。

作为一个授权框架,OAuth 关注的是如何让一个系统组件获取对另一个系统组件的访问权限。在OAuth 的世界中,最常见的情形是客户端应用代表资源拥有者(通常是最终用户)访问受保护资源。需要关心如下组件。

  • 资源拥有者有权访问API,并能将API 访问权限委托出去。资源拥有者一般是能使用浏览器的人。
  • 受保护资源是资源拥有者有权限访问的组件。这样的组件有多种形式,但大多数情况下是某种形式的Web API。
  • 客户端代表资源拥有者访问受保护资源的软件。在OAuth 中,只要软件使用了受保护资源上的API,它就是客户端。

 客户端需要资源拥有者暴露出凭据,例如LDAP身份验证。

授权访问

OAuth 协议的设计目的是:让最终用户通过OAuth 将他们在受保护资源上的部分权限委托给客户端应用,使客户端应用代表他们执行操作。为实现这一点,OAuth 在系统中引入了另外一个组件:授权服务器

受保护资源依赖授权服务器向客户端颁发专用的安全凭据——OAuth 访问令牌。为了获取令牌,客户端首先将资源拥有者引导至授权服务器,请求资源拥有者为其授权。授权服务器先对资源拥有者进行身份认证,然后一般会让资源拥有者选择是否对客户端授权。客户端可以请求授权功能或权限范围的子集,该子集可能会被资源拥有者进一步缩小。一旦授权请求被许可,客户端就可以向授权服务器请求访问令牌。按照资源拥有者的许可,客户端可以使用该令牌对受保护资源上的API 进行访问 。在这个过程中,没有将资源拥有者的凭据暴露给客户端:资源拥有者向授权服务器进行身份认证的过程中所用的信息是独立于客户端交互的。

OAuth授权过程​​

 授权委托:重要性及应用

委托概念是OAuth 强大功能的根基。虽然OAuth 经常被称作授权协议(这是RFC 中给出的名称),但它也是一个委托协议。通常,被委托的是用户权限的子集,但是OAuth 本身并不承载或者传递权限。相反,它提供了一种方法,让客户端可以请求用户将部分权限委托给自己。然后,用户可以批准这个委托请求。被批准之后,客户端就可以去执行那些操作了。

委托协议和授权协议的区别是很重要的,因为OAuth 令牌中携带的授权信息对系统中的大部分组件是不透明的只有受保护资源需要了解授权信息,只要它能从令牌中得知授权信息(既可以直接从令牌中获取,也可以通过某种服务来获取),它就可以按要求提供API 服务。

OAuth 2.0 不能做什么

  • OAuth 没有定义HTTP 协议之外的情形。由于使用bearer 令牌的OAuth 2.0 并不提供消息签名,因此不应该脱离HTTPS(TLS 上的HTTP)使用。机密信息需要在网络上传播,所以OAuth需要TLS 这样的传输机制来保护这些信息。
  • OAuth 不是身份认证协议,尽管用户确实存在,但OAuth 事务本身并不透露关于用户的信息。
  • OAuth 没有定义用户对用户的授权机制,需要其他协议辅助,例如:User Managed Access 协议(将在第14 章中讨论)就是为此而生,它规定了如何使用OAuth 构建一个支持用户对用户授权的系统。
  • OAuth 没有定义授权处理机制
  • OAuth 没有定义令牌格式。实际上,OAuth 协议明确声明了令牌的内容对客户端是完全不透明的。
  • OAuth 2.0 没有定义加密方法。可以使用其他加密机制,例如:了JSON 对象签名和加密(JOSE)规范套件。
  • OAuth 2.0 不是单体协议。该规范被分成了多个定义和流程,每个定义和流程都有各自适用的场景

OAuth 2.0 授权过程

OAuth 是一个复杂的安全协议,它需要不同的组件相互通信,OAuth 事务中的两个重要步骤是颁发令牌使用令牌。令牌表示授予客户端的访问权,它在OAuth 2.0 的各个部分都起到核心作用。尽管每个步骤的细节会因多种因素而异,但是一个规范的OAuth 事务包含以下事件。
(1) 资源拥有者向客户端表示他希望客户端代表他执行一些任务
(2) 客户端在授权服务器上向资源拥有者请求授权
(3) 资源拥有者许可客户端的授权请求
(4) 客户端接收到来自授权服务器的令牌
(5) 客户端向受保护资源出示令牌

OAuth 2.0 授权许可的完整过程

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

(0)资源拥有者访问客户端应用,并表明他希望客户端代表自己去使用某一受保护资源。

(1)当客户端发现需要获取一个新的OAuth 访问令牌时,它会将资源拥有者重定向(WEB一般指HTTP重定向)至授权服务器,并附带一个授权请求,表示它要向资源拥有者请求一些权限 。

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

(3)授权服务器会要求用户进行身份认证。用户身份认证直接在用户(和用户的浏览器)与授权服务器之间进行,这个过程对客户端应
用不可见。

因为资源拥有者通过浏览器与授权端点交互,所以也要通过浏览器来完成身份认证。因此,有很多身份认证技术可以用于用户身份认证流程。OAuth 没有规定应该使用哪种身份认证技术,授权服务器可以自由选择,例如用户名/密码、加密证书、安全令牌、联合单点登录或者其他方式。

(4)用户向客户端应用授权。在这一步,资源拥有者选择将一部分权限授予客户端应用,授权服务器提供了许多不同的选项来实现这一点

(5)授权服务器将用户重定向回客户端应用,一般通过redirect_uri实现,并且带上授权码。它是一次性的凭据,表示用户授权决策的结果。客户端会在接收到请求之后解析该参数以获取授权码,并在下一步使用该授权码

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

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

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

bearer 令牌的使用权
OAuth 核心规范对bearer 令牌的使用做了规定,无论是谁,只要持有bearer 令牌就有权使用它

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

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

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

OAuth 系统中有4 个主要的角色:客户端、授权服务器、资源拥有者以及受保护资源。这些组件分别负责OAuth 协议的不同部分,并且相互协作使OAuth 协议运转。

 OAuth 客户端是代表资源拥有者访问受保护资源的软件,它使用OAuth 来获取访问权限。它的职责主要是从授权服务器
获取令牌以及在受保护资源上使用令牌。客户端不需要理解令牌,也不需要查看令牌的内容。相反,客户端只需要将令牌视为一个不透明的字符串即可。OAuth 客户端可以是Web 应用、原生应用,甚至浏览器内的JavaScript 应用。

受保护资源能够通过HTTP 服务器进行访问,在访问时需要OAuth 访问令牌。受保护资源需要验证收到的令牌,并决定是否响应以及如何响应请求。在OAuth 架构中,受保护资源对是否认可令牌拥有最终决定权。

资源拥有者是有权将访问权限授权给客户端的主体。与OAuth 系统中的其他组件不同,资源拥有者不是软件。在大多数情况下,资源拥有者是一个人,他使用客户端软件访问受他控制的资源。

OAuth 授权服务器是一个HTTP 服务器,它在OAuth 系统中充当中央组件。授权服务器对资源拥有者和客户端进行身份认证,让资源拥有者向客户端授权、为客户端颁发令牌。某些授权服务器还会提供额外的功能,例如令牌内省、记忆授权决策。

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

访问令牌

OAuth 访问令牌,有时也简称为令牌,由授权服务器颁发给客户端,表示客户端已被授予权限。OAuth 并没有定义令牌本身的格式和内容,但它总是代表着:客户端请求的访问权限、对客户端授权的资源拥有者,以及被授予的权限(通常包含一些受保护资源标识)。
OAuth 令牌对于客户端来说是不透明的,也就是说客户端不需要(通常也不能)查看令牌内容。客户端要做的就是持有令牌,向授权服务器请求令牌,并向受保护资源出示令牌。OAuth 令牌并非对系统中的所有组件都不透明:授权服务器的任务是颁发令牌,受保护资源的任务则是验证令牌。因此,它们都需要理解令牌本身,并知道其含义。然而,客户端对这一切一无所知。这使得客户端简单得多,同时也使得授权服务器和受保护资源可以十分灵活地部署令牌。

权限范围

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

刷新令牌

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

 为什么客户端需要刷新令牌?在OAuth 中,访问令牌随时可能失效。令牌有可能被用户撤销,也可能过期,或者其他系统导致令牌失效。访问令牌失效后,客户端在使用时会收到错误响应。OAuth 2.0 提供了让令牌自动过期的选项,但是我们需要在用户不在场的时候仍然能访问资源。现在,刷新令牌取代了永不过期的访问令牌,但它的作用不是访问资源,而是获取新的访问令牌来访问资源。这种做法以一种独立但互补的方式,限制了刷新令牌和访问令牌的暴露范围。

刷新令牌还可以让客户端缩小它的权限范围。如果客户端被授予A、B、C 三个权限范围,但是它知道某特定请求只需要A 权限范围,则它可以使用刷新令牌重新获取一个仅包含A 权限范围的访问令牌。这让足够智能的客户端可以遵循最小权限安全原则。

授权许可

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

换句话说,授权许可就是获取令牌的方式。在本书中,就像在OAuth 社区中一样,会偶尔将其称为OAuth 协议的一个流程。OAuth 协议中有多种授权许可方法,并且各有特点。

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

OAuth 是一个基于HTTP 的协议,但是与大多数基于HTTP 的协议不同,OAuth 中的交互并不总是通过简单的HTTP 请求和响应来完成。

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

后端信道通信

OAuth 流程中的很多部分都使用标准的HTTP 请求和响应格式来相互通信。由于这些请求通常都发生在资源拥有者和用户代理的可见范围之外,因此它们统称为后端信道通信
这些请求和响应使用了所有常规的HTTP 机制来通信:头部、查询参数、HTTP 方法和HTTP主体都能承载对OAuth 事务至关重要的信息。请注意,由于多数简单的Web API 只需要客户端开发人员关注响应主体,这可能包含了你不熟悉的一些HTTP 机制。
授权服务器提供了一个授权端点,供客户端请求访问令牌和刷新令牌。客户端直接向该端点发出请求,携带一组表单格式的参数,授权服务器解析并处理这些参数。然后授权服务器返回一个代表令牌的JSON 对象

前端信道通信

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

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

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

 在前面看到的授权码许可中,客户端需要将用户重定向至授权端点,但是也需要将其请求的内容信息传递给授权服务器。为此,客户端向浏览器发送一个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

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

猜你喜欢

转载自blog.csdn.net/demon7552003/article/details/107392199