1 OAuth2解决什么问题的?

举个栗子先。小明QQ空间积攒了多年的照片,想挑选一些照片来打印出来。然后小明在找到一家提供在线打印并且包邮的网站(我们叫它PP吧(Print Photo缩写 ?))。

那么现在问题来了,小明有两个方案来得到打印的服务。

  1. 在自己的QQ空间把想要打印的照片下载下来,然后提供给PP(直接发邮件给PP或者网盘共享给PP等等)。
  2. 把自己的QQ账号密码给PP,然后告诉PP我要打印哪些照片。

针对方案(1):小明要去下载这些照片,然后给PP,小明累觉不爱,,,

针对方案(2):小明交出去自己的QQ账号密码,还要告诉PP哪些需要打印,哪些不需要,小明觉得自己有些小秘密不想给PP看,,,

小明觉得很痛苦,,,那么有没有不给PP账号密码,不下载照片,自己选哪些要打印直接扔给PP去打印的办法呢?OAuth走了过来扔给小明一块肥皂...

2 OAuth2简介

总结来说,OAuth2 是一个开放授权标准,它允许用户(小明)让第三方应用(PP)访问该用户在某服务的特定私有资源(QQ空间中小明的照片,可以不包含小明的小视频哦)但是不提供账号密码信息给第三方应用(PP)

有个小问题,为啥是OAuth2呢?1在哪?嗯,这个嘛,其实是有1和1.1版本的,只是因为1和1.1版本流程比较复杂,应用不是很广范,这里就不介绍了。据笔者以前做过的项目,Twitter是使用的OAuth1.1的版本,感兴趣的可以去了解下https://dev.twitter.com/oauth。

2.1 OAuth2的四个重要角色

进入正题,在OAuth2的完整授权流程中有4个重要的角色参与进来:

  1. Resource Owner:资源拥有者,上面栗子中的小明
  2. Resource Server:资源服务器,上面栗子中的QQ空间,它是小明想要分享照片给PP的照片的提供方;
  3. Client:第三方应用客户端,上面栗子中的PP,代指任何可以消费资源服务器的第三方应用;
  4. Authorization Server :授权服务器,管理Resource Owner,Client和Resource Server的三角关系的中间层

其中Authorization server和Resource server可以是独立的服务提供商,也可以是在一起的,比如腾讯提供QQ空间作为资源服务器的同时也提供授权服务。

从这里可以看出,OAuth2在解决小明遇到的问题的过程中增加了一个Authorization server的角色。又印证了那句话,在计算机领域的所有问题都可以添加一个中间层来解决。

OAuth2解决问题的关键在于使用Authorization server提供一个访问凭据给Client,使得Client可以在不知道Resource owner在Resource server上的用户名和密码的情况下消费Resource owner的受保护资源。

3 部署OAuth2需要的完成的工作

由于OAuth2引入了Authorization server来管理Resource Owner,Client和Resource Server的三角关系,那么想要用上OAuth2,是实现以下功能的。

  1. 增加一个Authorization server,提供授权的实现,一般由Resource server 来提供。
  2. Resource server 为第三方应用程序提供注册接口。
  3. Resource server 开放相应的受保护资源的API。
  4. Client 注册成为Resource server的第三方应用。
  5. Client 消费这些API。

作为资源服务提供商来说,1,2,3这三件事情是需要完成的。

作为第三方应用程序,要完成的工作是在4和5这两个步骤中。

其中作为Resource owner来说,是不用做什么的,是OAuth2受益的千千万万的最终人类用户。

3.1 作为Resource server

在一般情况下,Resource server提供Authorization server服务,主要提供两类接口:

  1. 授权接口:接受Client的授权请求,引导用户到Resource server完成登陆授权的过程。
  2. 获取访问令牌接口:使用授权接口提供的许可凭据来颁发Resource owner的访问令牌给Client,或者由Client更新过期的访问令牌。

除此之外,还需要提供一个第三方应用程序注册管理的服务。通常情况下会为注册完成的第三方应用程序分配两个成对出现的重要参数:

  1. client_id:第三方应用程序的一个标识id,这个信息通常是公开的信息,用来区分哪一个第三方应用程序。
  2. client_secret:第三方应用程序的私钥信息,这个信息是私密的信息,不允许在OAuth2流程中传递的,用于安全方面的检测和加密。

3.2 作为Client

在Client取得client_id和client_secret之后。使用这些信息来发起授权请求、获取access_token请求和消费受保护的资源。

4 OAuth2的授权流程

贴个图瞅瞅OAuth2的工作流程:

在上述的OAuth完整流程中,(A)->(B)->(C)->(D)是授权的过程(参与者有小明PPQQ空间Authorization server);(E)->(F)是消费资源的过程(参与者有PPQQ空间)。

  • (A)小明访问PPPPQQ空间发起授权请求;
  • (B)QQ空间接受PP的授权请求,并返回授权许可PP
  • (C)PP使用授权许可Authorization server发起请求
  • (D)Authorization server验证PP的身份和授权许可,发送访问令牌PP
  • (E)PP访问令牌请求小明存储在QQ空间的照片;
  • (F)QQ空间根据访问令牌,返回小明的照片信息给PP

这其中比较重要的一个概念是访问令牌 ,它代表的信息是整个OAuth2的核心,也是ABCD这些步骤最终要得到的信息。

访问令牌是对PP可以在QQ空间访问小明的哪些信息这个完整权限的一个抽象,比如PP要访问小李在QQ空间的照片,那么就是另外一个访问令牌了。

访问令牌背后抽象的信息有哪些呢?如下3类信息。

  1. 客户端标识(比如PP);
  2. 用户标识(比如小明);
  3. 客户端能访问资源所有者的哪些资源以及其相应的权限。

有了这三类信息,那么资源服务器(Resouce Server)就可以区分出来是哪个第三方应用(Client)要访问哪个用户(Resource Owner)的哪些资源(以及有没有权限)。

5 OAuth2的4种授权许可

上一小节介绍了OAuth2的授权流程,除了访问令牌之外,还有一个重要的概念授权许可(Authorization Grant)。

书面化的方式解释就是授权许可是一个代表资源所有者授权(访问受保护资源)的凭据,客户端用它来获取访问令牌。读起来比较抽象,翻一下就是授权许可是小明授予PP获得QQ空间访问令牌的一个凭据

那么如何获得这个凭据呐,OAuth2定义了四种许可类型以及用于定义其他类型的可扩展性机制:

  1. Authorization Code:授权码;
  2. Implicit:隐式许可;
  3. Resource Owner Password Credentials:资源所有者密码凭据;
  4. Client Credentials :客户端凭据。

注意:以下4种授权许可是对上述(4. OAuth2的授权流程)中的ABDE四个阶段的展开。

5.1 Authorization Code

这是OAuth2最常用的一种授权许可类型,比如QQ,微博,Facebook和豆瓣等等。要求Client具有可公开访问的Server服务器来接受Authorization Code,具体的流程如下:

上图ABCDE这5个步骤,既是完整的获取访问令牌的一个过程,其中引入了一些其他的概念,比如客户端标识,刷新令牌等和重定向URL等概念,后续会在6. OAuth2附属概念和流程介绍。

  • (A)Client使用浏览器(用户代理)访问Authorization server。也就是用浏览器访问一个URL,这个URL是Authorization server提供的,访问的收Client需要提供(客户端标识,请求范围,本地状态和重定向URL)这些参数。
  • (B)Authorization server验证Client在(A)中传递的参数信息,如果无误则提供一个页面供Resource owner登陆,登陆成功后选择Client可以访问Resource server的哪些资源以及读写权限。
  • (C)在(B)无误后返回一个授权码(Authorization Code)给Client
  • (D)Client拿着(C)中获得的授权码(Authorization Code)和(客户端标识、重定向URL等信息)作为参数,请求Authorization server提供的获取访问令牌的URL
  • (E)Authorization server返回访问令牌和可选的刷新令牌以及令牌有效时间等信息给Client

5.1.1 Authorization Request

对应步骤(A),客户端提供以下参数请求Authorization Server:

  1. response_type:必选。值固定为“code”。
  2. client_id:必选。第三方应用的标识ID。
  3. state:推荐。Client提供的一个字符串,服务器会原样返回给Client。
  4. redirect_uri:必选。授权成功后的重定向地址。
  5. scope:可选。表示授权范围。

比如以下示例:

GET /authorize?response_type=code&client_id=1&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user,photo HTTP/1.1
Host: server.example.com

5.1.2 Authorization Response

对应步骤(C),Authorization Server会返回如下信息:

  1. code:授权码。
  2. state:步骤(A)中客户端提供的state参数原样返回。

比如示例如下:

HTTP/1.1 302 Found
Location: https://client.example.com/oauth2?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

Location头部信息指向步骤(A)提供的redirect_uri地址,同时携带code信息和state信息给client,这样浏览器在重定向的时候就会已GET的方式访问Client提供的redirect_uri,同时Client接收到code信息和state信息。下一步就可以请求access_token了。

5.1.3 Access Token Request

对应步骤(D),客户端提供以下参数请求Authorization Server:

  1. grant_type:必选。固定值“authorization_code”。
  2. code : 必选。Authorization Response 中响应的code。
  3. redirect_uri:必选。必须和Authorization Request中提供的redirect_uri相同。
  4. client_id:必选。必须和Authorization Request中提供的client_id相同。

比如以下示例:

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencodedgrant_type=authorization_code&code=123&client_id=1&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2

5.1.4 Access Token Response

对应步骤(E),Authorization Server会返回如下典型的信息:

  1. access_token:访问令牌。
  2. refresh_token:刷新令牌。
  3. expires_in:过期时间。

比如以下示例:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value"
}

5.2 Implicit

这个是Authorization Code的简化版本。其中省略掉了颁发授权码(Authorization Code)给客户端的过程,而是直接返回访问令牌和可选的刷新令牌。其适用于没有Server服务器来接受处理Authorization Code的第三方应用,其流程如下:

其步骤就不做详细介绍了,相信大家都能理解。和Authorzation Code类型下重要的区分就是省略了Authorization Response和Access Token Request。而是直接由Authorization Request返回Access Token Response信息,具体如下。

5.2.1 Authorization Request

客户端提供以下参数请求Authorization Server:

  1. response_type:必选。值固定为“token”。
  2. client_id:必选。第三方应用的标识ID。
  3. state:推荐。Client提供的一个字符串,服务器会原样返回给Client。
  4. redirect_uri:可选。授权成功后的重定向地址。
  5. scope:可选。表示授权范围。

重点区别在于response_type为“token”,而不再是“code”,redirect_uri也变为了可选参数。

比如以下示例:

GET /authorize?response_type=token&client_id=1&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user,photo HTTP/1.1
Host: server.example.com

5.2.2 Access Token Response

Authorization Server会返回如下典型的信息:

  1. access_token:访问令牌。
  2. refresh_token:刷新令牌。
  3. expires_in:过期时间。

比如以下示:

HTTP/1.1 302 Found
Location: http://client.example.com/oauth2#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&expires_in=3600

注意其和Authorization Code的最大区别在于它是把token信息放在了url的hash部分(#后面),而不是作为参数(?后面)。这样浏览器在访问重定向的Location指定的url时,就不会把这些数据发送到服务器。而Client可以通过读取Location头信息中获取到access_token信息。

5.3 Resource Owner Password Credentials Grant

看看流程图:

这种模式再一步简化,和Authorzation Code类型下重要的区分就是省略了Authorization Request和Authorization Response。而是Client直接使用Resource owner提供的username和password来直接请求access_token(直接发起Access Token Request然后返回Access Token Response信息)。这种模式一般适用于Resource server高度信任第三方Client的情况下。

客户端提供以下参数请求Authorization Server:

  1. grant_type:必选。值固定为“password”。
  2. username:必选。用户登陆名。
  3. passward:必选用户登陆密码。
  4. scope:可选。表示授权范围。

比如以下示例:

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencodedgrant_type=password&username=blackheart&password=1234

Access Token Response和Authorization Code一致,就不列出来了。

5.4 Client Credentials Grant

这种类型就更简化了,Client直接已自己的名义而不是Resource owner的名义去要求访问Resource server的一些受保护资源。

客户端提供以下参数请求Authorization Server:

  1. grant_type:必选。值固定为“client_credentials”。
  2. scope:可选。表示授权范围。

比如以下示例:

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencodedgrant_type=client_credentials

Access Token Response和Authorization Code一致,就不列出来了。

以笔者以前做公共号开发的经验,它提供由这类的OAuth2许可类型,这个场景下得到的access_token的所属人是公众号的,可以用此access_token来获取所有已关注的用户的信息,而不局限于特定的某一个用户,正是Client Credentials Grant这种类型的许可的用武之地,案例文档地址在文章最后面。

6 OAuth2刷新令牌

在上述得到访问令牌(access_token)时,一般会提供一个过期时间和刷新令牌。以便在访问令牌过期失效的时候可以由客户端自动获取新的访问令牌,而不是让用户再次登陆授权。那么问题来了,是否可以把过期时间设置的无限大呢,答案是可以的,笔者记得Pocket的OAuth2拿到的访问令牌就是无限期的,好像豆瓣的也是。如下是刷新令牌的收客户端需要提供给Authorization Server的参数:

  1. grant_type:必选。固定值“refresh_token”。
  2. refresh_token:必选。客户端得到access_token的同时拿到的刷新令牌。

比如以下示例:

 POST /token HTTP/1.1Host: server.example.comgrant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

响应信息和5.1.4 Access Token Response保持一致。

7 Token传递方式

在第三方Client拿到access_token后,如何发送给Resouce Server这个问题并没有在RFC6729种定义,而是作为一个单独的RFC6750来独立定义了。这里做以下简单的介绍,主要有三种方式如下:

  1. URI Query Parameter.
  2. Authorization Request Header Field.
  3. Form-Encoded Body Parameter.

7.1 URI Query Parameter

这种使用途径应该是最常见的一种方式,非常简单,比如:

GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1

Host: server.example.com

在我们请求受保护的资源的Url后面追加一个access_token的参数即可。另外还有一点要求,就是Client需要设置以下Request Header的Cache-Control:no-store,用来阻止access_token不会被Web中间件给log下来,属于安全防护方面的一个考虑。

7.2 Authorization Request Header Field

因为在HTTP应用层协议中,专门有定义一个授权使用的Request Header,所以也可以使用这种方式:

GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM

其中"Bearer "是固定的在access_token前面的头部信息。

7.3 Form-Encoded Body Parameter

使用Request Body这种方式,有一个额外的要求,就是Request Header的"Content-Type"必须是固定的“application/x-www-form-urlencoded”,此外还有一个限制就是不可以使用GET访问,这个好理解,毕竟GET请求是不能携带Request Body的。

POST /resource HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

access_token=mF_9.B5f-4.1JqM

8 OAuth2的安全问题

在OAuth2早期的时候爆发过不少相关的安全方面的漏洞,其实仔细分析后会发现大都都是没有严格遵循OAuth2的安全相关的指导造成的,相关的漏洞事件百度以下就有了。

其实OAuth2在设计之初是已经做了很多安全方面的考虑,并且在RFC6749中加入了一些安全方面的规范指导。比如

  1. 要求Authorization server进行有效的Client验证;
  2. client_serect,access_token,refresh_token,code等敏感信息的安全存储(不得泄露给第三方)、传输通道的安全性(TSL的要求);
  3. 维持refresh_token和第三方应用的绑定,刷新失效机制;
  4. 维持Authorization Code和第三方应用的绑定,这也是state参数为什么是推荐的一点,以防止CSRF;
  5. 保证上述各种令牌信息的不可猜测行,以防止被猜测得到;

安全无小事,这方面是要靠各方面(开放平台,第三方开发者)共同防范的。如QQ互联的OAuth2 API中,state参数是强制必选的参数,授权接口是基于HTTPS的加密通道等;同时作为第三方开发者在使用消费这些服务的时候也应该遵循其相关的安全规范。

9 总结 & 参考 & 案例

OAuth2是一种授权标准框架,用来解决的是第三方服务在无需用户提供账号密度的情况下访问用户的私有资源的一套流程规范。与其配套的还有其他相关的规范,都可以到https://oauth.net/2/去延伸阅读和了解。

相关参考:

https://oauth.net/2/

https://www.oauth.com/

https://aaronparecki.com/oauth-2-simplified/

RFC6749 : The OAuth 2.0 Authorization Framework

RFC6749中文版(https://github.com/jeansfish/RFC6749.zh-cn)

RFC6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage.

RFC6819 - OAuth 2.0 Threat Model and Security Considerations.

OAuth2案例:

豆瓣OAuth2 API(Authorization Code)

QQ OAuth2 API(Authorization Code)

豆瓣OAuth2 API(Implicit )

QQ OAuth2 API(Implicit)

微信公众号获取access_token(Client Credentials Grant)。

至于Resource Owner Password Credentials Grant这种类型的许可方式,由于其适用常见,平时作为第三方开发者的开发工作中,没有遇到此类的案例。其适用场景在于第三方应用和Resoure server属于同一方这样高度可信的环境下。

转载于:https://www.cnblogs.com/linianhui/p/oauth2-authorization.html

[认证 授权] 1. OAuth2授权相关推荐

  1. [认证授权] 2.OAuth2授权(续) amp;amp; JSON Web Token

    0. RFC6749还有哪些可以完善的? 0.1. 撤销Token 在上篇[认证授权] 1.OAuth2授权 中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如 ...

  2. [认证授权] 1.OAuth2授权

    1 OAuth2解决什么问题的? 举个栗子先.小明在QQ空间积攒了多年的照片,想挑选一些照片来打印出来.然后小明在找到一家提供在线打印并且包邮的网站(我们叫它PP吧(Print Photo缩写 )). ...

  3. jws webservice 跳过https认证_基于OAuth2的OIDC (OpenId Connect)身份认证

    OIDC协议 OIDC(OpenID Connect)是在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议. OAuth2协议 OAuth2是一个授权协议,它无法提供完善的 ...

  4. Spring Security 实战干货:OAuth2授权回调的核心认证流程

    1. 前言 我们在上一篇 Spring Security 实战干货:OAuth2 授权回调的处理机制 对 OAuth2 服务端调用客户端回调的流程进行了图解, 今天我们来深入了解 OAuth2 在回调 ...

  5. 微服务架构如何设计API代理网关和OAuth2授权认证框架

    1,授权认证与微服务架构 1.1,由不同团队合作引发的授权认证问题 去年的时候,公司开发一款新产品,但人手不够,将B/S系统的Web开发外包,外包团队使用Vue.js框架,调用我们的WebAPI,但是 ...

  6. 网页提示未认证授权的应用服务器,授权认证(IdentityServer4)

    区别 OpenId: Authentication :认证 Oauth: Aurhorize :授权 输入账号密码,QQ确认输入了正确的账号密码可以登录 --->认证 下面需要勾选的复选框(获取 ...

  7. Spring Security 实战干货:客户端OAuth2授权请求的入口在哪里

    1. 前言 在Spring Security 实战干货:OAuth2 第三方授权初体验一文中我先对 OAuth2.0 涉及的一些常用概念进行介绍,然后直接通过一个 DEMO 来让大家切身感受了 OAu ...

  8. 通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权-百度版...

    目录: 一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr实现一个简单的基于.net的微服务电商系统(二)--通讯框架讲解 三.通过Dapr实现一个简单的基于.net的微服务 ...

  9. 通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权...

    Oauth2授权,熟悉微信开发的同学对这个东西应该不陌生吧.当我们的应用系统需要集成第三方授权时一般都会做oauth集成,今天就来看看在Dapr的语境下我们如何仅通过配置无需修改应用程序的方式让第三方 ...

最新文章

  1. ICRA 2020 | 实时语义立体匹配
  2. C#写的NoSQL开源项目/系统(系列)
  3. Response 和 Request
  4. Scala声明变量、常用类型、条件表达式、块表达式、循环
  5. LeetCode 2095. 删除链表的中间节点(快慢指针)
  6. 代码笔记——Toast显示文本,图片,图文
  7. 桌面下雪软件测试工程师,Snow Flakes屏幕下雪动态屏保 模拟真实降雪情景的屏保程序...
  8. stm8s103k3 周期 捕获_stm8s103k3的UART发送数据问题
  9. SAP Serial Number
  10. 不同调制方式的PWM谐波分析
  11. 《转》微商48种加人方法
  12. 水星网卡 linux驱动,水星网卡驱动下载_硬件驱动下载
  13. 20种在学习编程的同时也可以在线赚钱的方法
  14. 第三章 群体用户画像分析
  15. 网络骇客入门之UDP编程
  16. 基于ZYNQ的VGA驱动
  17. 【免费培训】腾讯WeTestTesterHome WorkShop | 一起学压测
  18. Android深入浅出系列课程---Lesson7 LLY110426_Android系统启动
  19. 还在用generator生成xxx管理系统的CRUD代码?来看看我是怎么写的
  20. 如何使用JMX_Expoter+Prometheus+Grafana监控Hadoop集群

热门文章

  1. C语言输出菱形图案(二维数组)
  2. 洛谷P1314 聪明的质检员(二分)
  3. c# spire.xls 设置文字为微软雅黑_让Word、PPT看傻,原来Excel文字排版也漂亮
  4. Python+vtk 实现激光点云数据可视化学习(2021.7.12)
  5. (全网最详细教程)康耐视读码器(以DM260S为例子)详细实用步骤
  6. 惠普服务器sd卡作用,服务器上有一个插SD卡的插槽,它到底有什么作用?
  7. 现代密码学:信息安全基础
  8. 网摘精灵的超级使用方法
  9. 浅谈云上攻防——对象存储服务访问策略评估机制研究
  10. GridView分页的实现