OAuth2.0协议详解

一、什么是OAuth2.0

OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本,但不兼容OAuth 1.0(即完全废止了OAuth1.0)。
OAuth 2.0 规范定义了一个授权(delegation)协议。

二、应用场景

第三方应用授权登录:在APP或者网页接入一些第三方应用时,时长会需要用户登录另一个合作平台,比如QQ(或是微博,微信)的授权登录。

三、OAuth2.0的四个重要角色

在OAuth2.0的完整授权流程中有4个重要的角色参与进来:

Resource Owner: 资源拥有者,上述例子中的用户。
Resource Server: 资源服务器,上述例子中的QQ(或是微博,微信)。
Client: 客户端,上述例子中的第三方应用,代指任何可以消费资源服务器的第三方应用;
Authorization Server : 授权服务器,管理Resource Owner,Client和Resource Server的三角关系的中间层。

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

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

四、OAuth2.0的授权流程

OAuth2.0协议详解_第1张图片

在上述的OAuth完整流程中,
(A)->(B)->(C)->(D)是授权的过程(参与者有用户,第三方应用,QQ(或是微博,微信),Authorization server);
(E)->(F)是消费资源的过程(参与者有第三方应用和QQ(或是微博,微信))。

(A)用户打开Client(第三方应用)以后,Client(第三方应用)向QQ(或是微博,微信)发起授权请求。

(B)用户同意给予Client(第三方应用)授权,并返回授权许可给Client(第三方应用)。

(C)Client(第三方应用)使用上一步获得的授权,向Authorization server(认证服务器)申请令牌。

(D)Authorization server(认证服务器)验证第三方应用的身份和授权许可,确认无误,同意发放Access Token(访问令牌)给Client(第三方应用)。

(E)Client(第三方应用)使用Access Token(访问令牌),向Resource Server(资源服务器)申请获取资源。

(F)Resource Server(资源服务器)确认令牌无误,同意向Client(第三方应用)开放资源。

这其中比较重要的一个概念是Access Token(访问令牌),它代表的信息是整个OAuth2.0的核心,也是ABCD这些步骤最终要得到的信息。
访问令牌是对第三方应用可以在QQ访问某个用户(假设为User_A)的部分信息这个完整权限的一个抽象,比如第三方应用要访问User_B在QQ的信息,那么就是另外一个访问令牌了。

访问令牌背后抽象的信息有哪些呢?
①第三方应用标识(比如Client_A);
②用户标识(比如User_A);
③客户端能访问资源所有者的哪些资源以及其相应的权限。
有了这三类信息,那么资源服务器(Resouce Server)就可以区分出来是哪个第三方应用(Client)要访问哪个用户(Resource Owner)的哪些资源(以及有没有权限)。

五、四种授权模式

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

①授权码模式(authorization code)
②简化模式(implicit)
③密码模式(resource owner password credentials)
④客户端模式(client credentials)

5.1)授权码模式Authorization code

授权码模式(authorization code)是功能最完整、流程最严密的授权模式。
OAuth2.0协议详解_第2张图片
(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返回访问令牌(Access Token)和可选的刷新令牌(Refresh Token)以及令牌有效时间等信息给Client。

5.1.1)备注说明:
Authorization Request - 请求获取授权码:

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

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

示例:

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

Authorization Response - 认证服务器返回授权码:

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

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

示例:

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

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

Access Token Request - 请求获取访问令牌(access token):

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

  • grant_type:必选。固定值“authorization_code”。
  • code : 授权码,必选。Authorization Response 中响应的code。
  • redirect_uri:重定向URL,必选。必须和Authorization Request中提供的redirect_uri相同。
  • client_id:必选。必须和Authorization Request中提供的client_id相同。

示例:

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

grant_type=authorization_code&code=123&client_id=1&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2

Access Token Response - 认证服务器返回访问令牌(access token):

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

  • access_token:访问令牌。
  • refresh_token:刷新令牌。
  • 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”
}

之后就能用access_token去获取用户数据了。

5.2)简化模式Implicit

这个是Authorization Code的简化版本。其中省略掉了颁发授权码(Authorization Code)给客户端的过程,而是直接返回访问令牌和可选的刷新令牌,就安全系数而言更低。
其适用于没有Server服务器来接受处理Authorization Code的第三方应用,其流程如下:
OAuth2.0协议详解_第3张图片

Authorization Request - 请求获取访问令牌:

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

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

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

示例:

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

Access Token Response - 认证服务器返回访问令牌:

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

  • access_token:访问令牌。
  • refresh_token:刷新令牌。
  • 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

OAuth2.0协议详解_第4张图片
这种模式再一步简化,和授权码模式(Authorzation Code)重要的区别就是省略了Authorization Request和Authorization Response。而是Client直接使用 用户(Resource owner)提供的username和password来直接请求access_token(直接发起Access Token Request然后返回Access Token Response信息)。这种模式一般适用于Resource server高度信任第三方Client的情况下。

客户端提供以下参数请求Authorization Server获取访问令牌:

对应(B),由Client发送用户名、密码至认证服务器。

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

示例:

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

5.4)客户端模式 Client Credentials

这种类型就更简化了,Client直接以自身的名义而不是Resource owner(用户)的名义去要求访问Resource server(资源服务器)的一些受保护资源。

OAuth2.0协议详解_第5张图片

客户端提供以下参数请求Authorization Server:
  • grant_type:必选。值固定为“client_credentials”。
  • scope:可选。表示授权范围。

示例:

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

目前微信公共号开发使用的是这种授权模式,它提供由这类的OAuth2.0许可类型,这个场景下得到的access_token的所属人是公众号的,可以用此access_token来获取所有已关注的用户的信息,而不局限于特定的某一个用户。

六、知识点梳理

①OAuth2.0刷新令牌?

获取访问令牌(access_token)时,一般会提供一个过期时间和刷新令牌。以便在访问令牌过期失效的时候可以由客户端自动获取新的访问令牌,而不是让用户再次登陆授权。

通过刷新令牌获取新的访问令牌(access_token):

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

请求示例:

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

响应:

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”
}

②OAuth2.0 Token 撤销(RFC7009 - OAuth2 Token Revocation)

简单来说,这个协议规定了一个Authorization server提供一个怎样的API来供Client撤销access_token或者refresh_token。

例如Client发起一个如下的请求

POST /revoke HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token

其中各项含义如下:
/revoke:是Authorization Server需要提供的API地址,Client使用Post方式请求这个地址。
Content-Type: application/x-www-form-urlencoded:固定此格式。
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW:访问受保护资源的授权凭证。
token:必选,可以是access_token或者refresh_token的内容。
token_type_hint:可选,表示token的类型,值为”access_token“或者"refresh_token"。
如果撤销成功,则返回一个HTTP status code为200的响应。

你可能感兴趣的:(授权认证)