2.OAuth 2 combat --- OAuth Dance

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

2.OAuth 2.0授权许可的完整过程
  	授权码许可中用到了一个临时码---授权码,来表示资源拥有者同意向客户端授权。
  	如何发现服务器?
  	为了最大限度的保持灵活性,OAuth协议去除了真实api系统的很多细节。具体来说,OAuth没有规定客户端如何知悉与受保护资源交互的方式,或者客户端如何发现
  受保护资源对应的授权服务器。这些问题一般都由建立在OAuth之上的其他协议以标准方式解决,例如OpenID Connect 和 User Managed Access(UMA)。

  	首先,资源拥有者访问客户端应用,并表明他希望客户端代表自己去使用某一受保护资源。该服务是个api,客户端知道如何调用它,并且还知道需要通过OAuth调用。
  	
  	当客户端发现需要获取一个新的OAuth访问令牌时,它会将资源拥有者重定向至授权服务器,并附带一个授权请求,表示它要向资源拥有者请求一些权限。
  	由于我们使用的是web客户端,因此采用http重定向的方式将用户代理重定向至授权服务器的授权端点。
  	Location:http://localhost:9001?authorize?response_type=code&scope=foo&client_id=uauth-client-1&redirect_uri=http://localhost:9000
  	这个重定向响应导致浏览器向授权服务器发送一个GET请求。
  	GET /authorize?response_type=code&scope=foo&client_id=uauth-client-1&redirect_uri=http://localhost:9000&callback&state=werwaer
  	Host:localhost:9001
  	客户端通过在发送给用户的URL中包含查询参数,来标识自己的身份和要请求的授权详情,如权限范围等。虽然请求并不是由客户端直接发出的,但授权服务器会解析这些
   参数并做出适当的反应。

   	然后,授权服务器会要求用户进行身份认证。这一步对确认资源拥有者的身份以及能向客户端授予哪些权限来说至关重要。
   	用户身份认证直接在用户(和用户的浏览器)与授权服务器之间进行,这个过程对客户端应用不可见。这一重要特性避免了用户将自己的凭据透露给客户端应用,对抗这种反模式
   正式OAuth的原因。
   	另外,因为资源拥有者通过浏览器与授权端点交互,所以也要通过浏览器来完成身份认证。因此,有很多身份认证技术可以用于用户身份认证流程。OAuth没有规定应该使用
   那种身份认证技术,授权服务器可以自由选择,例如用户名/密码,加密证书,安全令牌,联合单点登录或者其他方式。在此我们不得不在一定程度上信任web浏览器,特别是当
   资源拥有者使用像用户名和密码这样的简单身份认证方式时。但是OAuth的设计已经考虑了如何防止多种基于浏览器的攻击。
   	这种隔离方案使得客户端不会因为用户身份认证方式发生变化而受到影响,让简单的客户端应用也能受益于授权服务器使用的一些新兴技术,例如基于风险的启发式认证技术。
   然而这种做法并没有向客户端传递任何有关认证用户的信息。

   	然后,用户向客户端应用授权。在这一步,资源拥有者选择将一部分权限授予客户端应用,授权服务器提供了许多不同的选项来实现这一点。客户端可以在授权请求中指明其想要
   获得哪些权限(称为OAuth权限范围)。授权服务器可以允许用户拒绝一部分或者全部权限范围,也可以让用户批准或者拒绝整个授权请求。
   	此外,很多授权服务器允许将授权决策保留下来,以便以后使用。如果使用了这种方式,那么未来同一个客户端请求同样的授权时,用户将不会得到提示。用户仍然会被重定向
   到授权端点,并且仍然需要登录,但是会跳过批准授权环节而沿用前一次的授权决策。授权服务器甚至可以通过像客户端白名单或黑名单这样的内部决策来否决用户的决策。

   	然后,授权服务器将用户重定向回客户端应用。
   	这一步采用http重定向的方式,回到客户端的recirect_uri。
   	HTTP 302 Found
   	Location:http://localhost:9000/oauth_callback?code=afdf93493492
   	这会导致浏览器向客户端发送如下请求:
   	GET /callback?code=afdf93493492
   	HTTP/1.1 Host:localhost:9000
   	请注意这个请求是发送给客户端而不是授权服务器的。
   	由于使用的是授权码许可类型,因此该重定向链接中包含一个特殊的查询参数code。这个参数的值被称为授权码,它是一次性的凭据,表示用户授权的结果。客户端会在接收到
   请求之后解析该参数以获取授权码,并在下一步使用该授权码。客户端还会检查state参数值是否与它前一个步骤中发送的值匹配。

   	现在客户端已经得到授权码,它可以将其发送给授权服务器的令牌端点。
   	客户端发送一个POST请求,在http主体中以表单格式传递参数,并在http基本认证头部中设置client_id和client_secret。这个http请求由客户端直接发送给授权服务器,
   浏览器或者资源拥有者不参与此过程。
   	POST /token
   	Host:localhost:9001
   	Accept:application/json
   	Content-Type:application/x-www-form-encoded
   	Authorization:Basic abd1231
   	grant_type=authorization_code&
   	redirect_uri=http://localhost:9000callback&code=afdf93493492
   	这种将不同的http连接分开的做法保证了客户端能够直接进行身份认证,让其他组件无法查看或者操作令牌请求。
   	授权服务器接收该请求,如果请求有效,则颁发令牌。授权服务器需要执行多个步骤以确保请求是合法的。首先,它要验证客户端凭据(通过Authorization头部传递)以确定
   是哪个客户端请求授权。然后,从请求主体中读取code参数的值,并从中获取关于该授权码的信息,包括发起初始授权请求的是哪个客户端,执行授权的是哪个用户,授权的内容
   是什么。如果授权码有效且尚未使用,而且发起请求的客户端与最初发起授权请求的客户端相同,则授权服务器会生成一个新的访问令牌并返回给客户端。
   	该令牌以json对象的格式通过http响应返给客户端。
   	HTTP 200 OK
   	Content-Type:applicatioin/json
   	{
   		"access_token":"abc123",
   		"token_type":"Bearer"
   	}

   	然后客户端可以解析令牌响应并从中获取令牌的值来访问受保护资源。在这个案例中,我们使用了OAuth bearer 令牌,这是通过响应中的token_type字段描述的。令牌响应
   中还可以包含一个刷新令牌(用户获取新的访问令牌而不是重新请求授权),以及一些关于访问令牌的附加信息,比如令牌的权限范围和过期时间。客户端可以将访问令牌存储在一个
   安全的地方,以便以后在用户不在场的时候也能够随时使用。
   	bearer 令牌的使用权:OAuth核心规范对bearer令牌的使用做了规定,无论是谁,只要持有bearer令牌就有权使用。bearer令牌具有特殊的安全属性。
   	有了令牌,客户端就可以在访问受保护资源时出示令牌。
   	客户端出示令牌的方式有很多种,备受推崇的方式是:使用Authorization头部。
   	GET /resource HTTP/1.1
   	Host:localhost:9002
   	Authorization:Bearer abc123
   	受保护资源可以从头部中解析出令牌,判断它是否有效,从中得出授权者是谁以及授权的内容,然后返回响应。受保护资源检查令牌的方式有很多种。最简单的方式是让授权服务器
   和资源服务器共享存储令牌信息的数据库。授权服务器在生成新的令牌时将其写入数据库,资源服务器在收到令牌时从数据库中读取他们。

3.OAuth中的角色:客户端、授权服务器、资源拥有者、受保护资源
	1.OAuth客户端是代表资源拥有者访问受保护资源的软件,它使用OAuth来获取访问权限。得益于OAuth的设计,客户端通常是OAuth系统中最简单的组件,它的职责主要是从授权服务器
  获取令牌以及在受保护资源上使用令牌。客户端不需要理解令牌,也不需要查看令牌的内容。相比,客户端只需要将令牌视为一个不透明的字符串即可。OAuth客户端可以是web应用,原生
  应用,甚至浏览器内的js应用。
  	2.受保护资源能够通过http服务器进行访问,在访问时需要OAuth访问令牌。受保护资源需要验证收到的令牌,并决定是否响应以及如何响应请求。在OAuth架构中,受保护资源对是否
  认可令牌拥有最终决定权。
  	3.资源拥有者是有权将访问权限授权给客户端的主体。与OAuth系统中的其他组件不同,资源拥有者不是软件。在大多数情况下,资源拥有者是一个人,他使用客户端软件访问受他控制的
  资源。至少在部分过程中,资源拥有者要使用web浏览器(通常称为用户代理)与授权服务器交互。资源拥有者可能还会使用浏览器与客户端交互,如这里所展示的,但这完全取决于客户端性质。
  	4.OAuth授权服务器是一个http服务器,它在OAuth系统中充当中央组件。授权服务器对资源拥有者和客户端进行身份认证,让资源拥有者向客户端授权,为客户端颁发令牌。某些授权
  服务器还会提供额外的功能,如令牌内省,记忆授权决策等。

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

	4.2 权限范围
		OAuth的权限范围表示一组受保护资源的权限。OAuth协议中使用字符串表示权限范围,可以用空格分割的列表将它们合并为一个集合。因此,权限范围的值不能包含空格。OAuth并
	  没有规定权限范围值的格式和结构。
	  	权限范围是一种最要的机制,它界定了客户端获取的权限范围。权限范围是由受保护资源根据其自身提供的api来定义的。客户端可以请求某些权限范围,授权服务器则允许资源拥有者
	  在客户端发出请求时许可或否则特定的权限范围。权限范围具有可叠加的特性。
	  	回到云打印的例子,照片存储服务的api为照片定义了多种权限范围:read-photo,read-metadata,update-photo,update-metadata,create,delete。照片打印服务只要能
	  读取照片就足以完成工作,所以它会请求read-phone权限范围。只要拥有一个该权限范围的令牌,它就能够读取照片并打印出来。如果用户还想要使用依据照片日期将照片打印成册的
	  高级功能,则打印服务还需要read-metadata权限范围。由于这是一个额外的访问权限,照片打印服务还需要通过正常的OAuth流程来请求用户授予它这个额外的权限范围。只要照片
	  打印服务拥有这2个权限范围的令牌,它就能使用该令牌执行相应的操作。

	4.3 刷新令牌
		OAuth刷新令牌在概念上与访问令牌很相似,它也是由授权服务器颁发给客户端的令牌,客户端也不知道或不关心该令牌的内容。但不同的是,该令牌从来不会被发送给受保护资源。
	  相反,客户端使用刷新令牌向授权服务器请求新的访问令牌,而不需要用户的参与。
	  	为什么客户端需要刷新令牌?在OAuth中,访问令牌随时肯能失效。令牌有可能被用户撤销,也有可能过期,或者其他系统导致令牌失效。访问令牌失效后,客户端在使用时会收到
	  错误响应。当然,客户端可以再次向资源拥有者请求权限,但是如果资源拥有者不在场呢?
	  	在OAuth1.0中,客户端除了等资源拥有者回来重新授权之外别无他法。为避免这种情况,OAuth1.0中的令牌往往会一直保持有效,直到明确的被撤销。这是有问题的,因为它增加了
	  被盗令牌的攻击面:攻击者可以永久使用该令牌。OAuth2.0提供了让令牌自动过期的选项,但是我们需要在用户不在场的时候仍然能够访问资源。现在,刷新令牌代替了永久不过期的
	  访问令牌,但它的作用不是访问资源,而是获取新的访问令牌来访问资源。这种做法以一种独立但互补的方式限制了刷新令牌和访问令牌的暴露范围。
	  	刷新令牌还可以让客户端缩小它的权限范围。如果客户端被授予了a,b,c三个权限范围,但是它知道某种特定的请求只需要a权限范围,则它可以使用刷新令牌重新获得一个仅包含a的
	  权限范围的访问令牌。这让足够智能的客户端可以遵循最小权限安全原则,但也不会给不那么智能的客户端带来负担,即无需查明某个api需要哪些权限。虽然多年的部署经验表明,OAuth
	  客户端往往并不智能,但是对于那些想要实践这种智能的客户端而言,这一高级功能还是很有价值的。
	  	如果刷新令牌失效了怎么办?如果用户在场,客户端可以随时劳烦用户再次授权。换句话说,客户端退回到了重新进行OAuth授权的状态。

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

5.OAuth的角色与组件间的交互:后端信道、前端信道和端点
	OAuth是一个基于http的协议,但是与大多数基于http的协议不同,OAuth中的交互并不总是通过简单的http请求和响应来完成。
	非http信道之上的OAuth:
		虽然OAuth基于http的协议,但已经有很多规范定义了如何将OAuth流程中的不同部分迁移到非http协议之上。如在通用安全服务器应用程序接口(GSS-API)和受限应用程序协议(CoAP)
	  上使用OAuth令牌。

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

	5.2 前端信道通信
		在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=abc123
	  	授权服务器可以像处理一般的http请求一样解析传入的url,从参数中获取信息。这个环节,授权服务器可以与资源拥有者进行交互,通过浏览器执行一系列http事务,对资源拥有者进行
	  身份认证并请求其授权。当需要给客户端返回授权码时,授权服务器也向浏览器返回重定向响应,但是这一次的重定向目标是客户端的redirect_uri.授权服务器也会在重定向的查询参数中
	  附带信息。
	  	HTTP 302 Found
	  	Location:http://localhost:9000/oauth_callback?code=ab123
	  	浏览器执行这个重定向时,会向客户端应用发送一个http请求。然后客户端可以解析请求中的参数。这样,客户端和授权服务器就以浏览器为媒介实现了通信,而不用直接交互。
	  	
	  	如果我的客户端不是web应用怎么办?
	  	web应用和原生应用都可以使用OAuth,但是都需要使用前端通信信道机制来接收授权端点返回的信息。前端通信信道通常需要用到web浏览器和http重定向,但常规的web服务器一般是
	  不提供这些支持的。幸运的是,有一些技巧可以解决这些问题,比如内部web服务器,应用专有的uri方案,使用后端服务向客户端推送通知等。总之,只要能触发浏览器对该uri的调用即可。

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

6.小结
	1.OAuth是关于获取令牌和使用令牌的。
	2.OAuth系统中的不同组件各自负责授权流程中的不同环节
	3.组件使用直接的(后端通信)和间接的(前端通信)http连接互相通信

 

Published 342 original articles · won praise 73 · views 670 000 +

Guess you like

Origin blog.csdn.net/enlyhua/article/details/104263824