OAuth(Open Authorization,开放授权)是一个关于授权的开放网络标准。OAuth 允许用户授权第三方应用程序(Third-Party Application)访问他们存储在其它服务提供商(HTTP Service)上的资源(Resource),而不需要将用户名和密码提供给第三方应用程序或分享他们的全部资源。
假设有一个“云冲印”网站,可以将用户存储在 Google 上的照片冲印出来。用户为了使用该服务,必须让“云冲印”读取自己存储在 Google 上的照片。
问题是:只有得到用户的授权,Google 才会同意“云冲印”读取这些照片。那么“云冲印”怎样获得用户的授权呢?
传统方法是:用户将自己的 Google 用户名和密码告诉“云冲印”。这样做有以下几个严重的缺点:
在详细讲解 OAuth 2.0 之前,需要了解以下专用名词:
OAuth 的作用是:让“客户端”安全可控地获取“用户”的授权,与“服务商提供商”进行互动。
OAuth 在“客户端”与“服务提供商”之间,设置一个授权层(Authorization Layer)。“客户端”不能直接登录“服务提供商”,只能登录授权层,以此将用户与“客户端”区分开。“客户端”登录授权层所用的令牌(Token),与用户密码不同。用户可以在登录时,指定授权层令牌的权限范围和有效期。
“客户端”登录授权层后,“服务提供商”根据令牌的权限范围和有效期向“客户端”开放用户存储的资料。
授权码模式(Authorization Code)是功能最完整、流程最严密的授权模式。它的特点是:通过“客户端”的后台服务器,与“服务提供商”的认证服务器进行互动。
其步骤如下:
用户访问“客户端”,后者将前者导向认证服务器。 “客户端”申请认证的 URI 包含以下参数:
response_type
:授权类型,必选项,其值固定为 code
client_id
:客户端 ID,必选项
redirect_uri
:重定向 URI,可选项
scope
:申请的权限范围,可选项
state
:客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回该值
下面是一个例子:
xxxxxxxxxx
https://graph.qq.com/oauth/show?which=Login&display=pc&response_type=code&client_id=100270989&redirect_uri=https%3A%2F%2Fpassport.csdn.net%2Faccount%2Flogin%3Foauth_provider%3DQQProvider&state=test
用户选择是否给“客户端”授权
假设用户给予授权,认证服务器将用户导向“客户端”事先指定的重定向 URI(Redirection URI),同时附上一个授权码。 服务器回应客户端的 URI,包含以下参数:
code
:授权码,必选项。该授权码的有效期很短,通常设为 10 分钟,该授权码只能被“客户端”使用一次,否则会被授权服务器拒绝。该授权码与客户端 ID 和重定向 URI 一一对应
state
:如果客户端的请求中包含该参数,认证服务器的回应也必须包含该参数
下面是一个例子:
xxxxxxxxxx
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
“客户端”收到授权码,附上早先的重定向 URI,向认证服务器申请令牌。该步骤在“客户端”的后台服务器上完成,对用户不可见。 “客户端”向认证服务器申请令牌的 HTTP 请求,包含以下参数:
grant_type
:使用的授权模式,必选项,其值固定为 authorization_code
code
:上一步获得的授权码,必选项
redirect_uri
:重定向 URI,必选项,必须与第一步中的值保持一致
client_id
:客户端 ID,必选项
下面是一个例子:
xxxxxxxxxx
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
认证服务器核对授权码和重定向 URI,确认无误后,向“客户端”发送访问令牌(Access Token)和更新令牌(Refresh Token)。 认证服务器发送的 HTTP 响应,包含以下参数:
access_token
:访问令牌,必选项
token_type
:令牌类型,该值大小写不敏感,必选项,可以是 bearer 类型或 mac 类型
expires_in
:过期时间,单位为秒。如果省略该参数,必须使用其它方式设置过期时间
refresh_token
:更新令牌,用来获取访问令牌,可选项
scope
:权限范围,如果与客户端申请的范围一致,此项可省略
下面是一个例子:
xxxxxxxxxx
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
如果客户端的访问令牌已经过期,那么需要使用更新令牌申请新访问令牌。客户端发出的更新令牌的 HTTP 请求,包含以下参数:
grant_type
:使用的授权模式,其值固定为 refreshtoken,必选项refresh_token
:先前收到的更新令牌,必选项scope
:申请的授权范围,不可以超出上次申请的范围,如果省略该参数,那么表示与上次一致下面是一个例子:
xxxxxxxxxx
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
OAuth 2.0 定义了一组端点(endpoint),端点通常是 Web 服务器上的 URI。端点的定义如下:
授权端点和 Token 端点都在授权服务器上,重定向端点在第三方应用服务器上:
OAuth 2.0 的定义没有描述这些端点的 URI,它们由实现者决定。
1. 授权端点:
授权端点是授权服务器上的端点,资源所有者会登录它,给第三方应用程序授权
2. Token端点:
Token 端点是授权服务器上的端点,第三方应用程序会和它交换授权码、Client ID、Client 密码,以获取访问令牌
3. 重定向端点:
重定向端点是第三方应用服务器上的端点,在授权端点授权之后,资源拥有者会被重定向到该端点