OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务器提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。
OAuth 2.0是授权的行业标准协议。OAuth 2.0关注客户端开发人员的简单性,同时为web应用程序、桌面应用程序、移动电话和设备提供特定的授权流。
名词定义- Third-party application:第三方应用,也称为客户端client。
- Http service:HTTP服务提供商。
- Resource Owner:资源所有者,也称为用户user。
- User Agent:用户代理,指浏览器。
- Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。
- Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。
OAuth在客户端与服务提供商之间设置了一个授权层。客户端不能直接登录服务提供商,只能登录授权层,以此将用户与客户端区分开来。客户端登录授权层所用的令牌token与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。
客户端登录授权层后,服务提供商根据令牌的权限范围和有效提,向客户端开放用户存储的资料。
运转流程+--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+
(A):用户打开客户端后,客户端向用户请求授权。
(B):用户同意(A)步骤授权。
©:客户端通过身份验证请求访问认证服务器。
(D):认证服务器对客户端进行认证和验证授权,如果有效就发出访问令牌。
(E):客户端使用令牌,向资源服务器申请获取资源。
(F):资源服务器确认令牌无误,同意向客户端开放资源。
授权模式OAuth 2.0定义了四种授权模式:
- 授权码模式(Authorization Code)
- 简化模式(Implicit)
- 密码模式(Resource Owner Password Credentials)
- 客户端模式(Client Credentials)
授权码类型用于获取访问令牌和刷新令牌,并针对客户端进行了优化。由于这是一个基于重定向的流,客户端必须能够与资源所有者的用户代理(通常是web浏览器)交互,并能够接收来自授权服务器的(通过重定向)传入请求。
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(B)
+----|-----+ Client Identifier +---------------+
| -+----(A)-- & Redirection URI ---->| |
| User- | | Authorization |
| Agent -+----(B)-- User authenticates --->| Server |
| | | |
| -+----(C)-- Authorization Code ---<| |
+-|----|---+ +---------------+
| | ^ v
(A) (C) | |
| | | |
^ v | |
+---------+ | |
| |>---(D)-- Authorization Code ---------' |
| Client | & Redirection URI |
| | |
| |<---(E)----- Access Token -------------------'
+---------+ (w/ Optional Refresh Token)
(A):用户访问客户端,后者将前者导向认证服务器,一旦授予(或拒绝)访问,认证服务器将重定向URI到用户代理。
(B):认证服务器对资源所有者进行身份验证,确定资源所有者是否授予或拒绝客户端的访问请求。
©: 假设资源所有者给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
(D): 客户端收到授权码,附上©的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E): 授权服务器验证客户端,验证授权代码,并确保接收到的重定向URI与步骤©中用于重定向客户端的URI匹配。如果有效,授权服务器返回一个访问令牌(access token)和一个刷新令牌(refresh token可选)。
交互定义 (A)步骤Authorization Request,Content-Type:“application/x-www-form-urlencoded”,请求参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| response_type | REQUIRED | 固定为code |
| client_id | REQUIRED | 客户端在服务期申请的id |
| redirect_uri | OPTIONAL | 重定向uri |
| scope | OPTIONAL | 请求access访问的作用域 |
| state | RECOMMENDED | 客户端传递将原封不动的返回给客户端 |
# 请求示例 GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com(B)步骤
HTTP服务提供商自定义登录接口。
©步骤Authorization Response,Content-Type:“application/x-www-form-urlencoded”,响应参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| code | REQUIRED | 认证服务器生成的授权码,有效期最长10分钟。授权码只允许使用一次,多次使用认证服务器必须拒绝。 |
| state | REQUIRED | 如果客户端请求参数有就返回 |
# 响应示例 HTTP/1.1 302 Found Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz(D)步骤
客户端服务器行为,用户无感知。Access Token Request,Content-Type:“application/x-www-form-urlencoded”,请求参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| grant_type | REQUIRED | 固定为authorization_code |
| code | REQUIRED | ©步骤响应的code |
| redirect_uri | REQUIRED | 如果(A)步骤传递了redirect_uri那么必须保持一致 |
| client_id | REQUIRED | 客户端在服务期申请的id |
# 请求示例 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(E)步骤
Access Token Response,Content-Type:“application/json;charset=UTF-8”,响应参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| access_token | REQUIRED | |
| token_type | REQUIRED | 令牌类型,可以是bearer类型或mac类型 |
| expires_in | REQUIRED | 令牌过期时间单位秒 |
| refresh_token | OPTIONAL | 更新令牌,用于access_token过期时候刷新 |
| example_parameter | OPTIONAL | 权限范围 |
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"
}
简化模式
简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(B)
+----|-----+ Client Identifier +---------------+
| -+----(A)-- & Redirection URI --->| |
| User- | | Authorization |
| Agent -|----(B)-- User authenticates -->| Server |
| | | |
| |<---(C)--- Redirection URI ----<| |
| | with Access Token +---------------+
| | in Fragment
| | +---------------+
| |----(D)--- Redirection URI ---->| Web-Hosted |
| | without Fragment | Client |
| | | Resource |
| (F) |<---(E)------- Script ---------<| |
| | +---------------+
+-|--------+
| |
(A) (G) Access Token
| |
^ v
+---------+
| |
| Client |
| |
+---------+
(A): 客户端将用户导向认证服务器。
(B): 用户决定是否给于客户端授权。
©: 假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。
(D): 浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。
(E): 资源服务器返回一个网页,其中包含的代码脚本可以获取Hash值中的令牌。
(F): 浏览器执行上一步获得的脚本,提取出令牌。
(G): 浏览器将令牌发给客户端。
交互定义 (A)步骤Authorization Request,Content-Type:“application/x-www-form-urlencoded”,请求参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| response_type | REQUIRED | 固定为token |
| client_id | REQUIRED | 客户端在平台申请的id |
| redirect_uri | OPTIONAL | |
| scope | OPTIONAL | access请求的作用域 |
| state | RECOMMENDED |
# 请求示例 GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com(B)步骤
HTTP服务提供商自定义登录接口。
©步骤Access Token Response,Content-Type:“application/x-www-form-urlencoded”,响应参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| access_token | REQUIRED | |
| token_type | REQUIRED | 令牌类型,可以是bearer类型或mac类型 |
| expires_in | REQUIRED | token过期时间,单位秒 |
| scope | OPTIONAL | |
| state | REQUIRED | 客户端请求如果带有那么就返回 |
# 响应示例 HTTP/1.1 302 Found Location:http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600密码模式
密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。
+----------+
| Resource |
| Owner |
| |
+----------+
v
| Resource Owner
(A) Password Credentials
|
v
+---------+ +---------------+
| |>--(B)---- Resource Owner ------->| |
| | Password Credentials | Authorization |
| Client | | Server |
| |<--(C)---- Access Token ---------<| |
| | (w/ Optional Refresh Token) | |
+---------+ +---------------+
(A): 用户向客户端提供用户名和密码。
(B): 客户端将用户名和密码发给认证服务器,向后者请求令牌。
©: 认证服务器确认无误后,向客户端提供访问令牌。
交互定义 (A)步骤客户端自定义接口。
(B)步骤Access Token Request,Content-Type: “application/x-www-form-urlencoded”,请求参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| grant_type | REQUIRED | 固定为password |
| client_id | REQUIRED | |
| client_secret | OPTIONAL | |
| username | REQUIRED | 资源所有者账号 |
| password | REQUIRED | 资源所有者密码 |
| scope | OPTIONAL | 资源权限范围 |
# 请求示例 POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=password&username=johndoe&password=A3ddj3w&client_id=1234124&client_secret=nWDFmQmF0M©步骤
Access Token Response,Content-Type:“application/json;charset=UTF-8”,响应参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| access_token | REQUIRED | |
| token_type | REQUIRED | 令牌类型,可以是bearer类型或mac类型 |
| expires_in | REQUIRED | 令牌过期时间单位秒 |
| refresh_token | OPTIONAL | 更新令牌,用于access_token过期时候刷新 |
| example_parameter | OPTIONAL | 权限范围 |
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"
}
客户端模式
客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。
该模式的使用客户端必须属于机密可信任客户。
+---------+ +---------------+ | | | | | |>--(A)- Client Authentication --->| Authorization | | Client | | Server | | |<--(B)---- Access Token ---------<| | | | | | +---------+ +---------------+
(A):客户端向认证服务器进行身份认证,并要求一个访问令牌。
(B):认证服务器确认无误后,向客户端提供访问令牌。
交互定义 (A)步骤Access Token Request,Content-Type:“application/x-www-form-urlencoded”,请求参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| grant_type | REQUIRED | 固定为client_credentials |
| client_id | REQUIRED | |
| client_secret | OPTIONAL | |
| scope | OPTIONAL | 请求token的权限范围 |
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=client_id&client_secret=client_secret(B)步骤
Access Token Response,Content-Type:“application/json;charset=UTF-8”,请求参数如下:
| 参数 | 必填 | 描述 |
|---|---|---|
| access_token | REQUIRED | |
| token_type | REQUIRED | 令牌类型,可以是bearer类型或mac类型 |
| expires_in | REQUIRED | 令牌过期时间单位秒 |
| example_parameter | OPTIONAL | 权限范围 |
# 响应示例
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,
"example_parameter":"example_value"
}
错误响应
| 字段 | 必填 | 描述 |
|---|---|---|
| error | REQUIRED | 错误码 |
| error_description | OPTIONAL | 错误描述 |
| error_uri | OPTIONAL | 错误信息描述网站,无 |
| state | REQUIRED | 入参有就返回 |
| 错误码 | 描述 |
|---|---|
| invalid_request | 参数不齐全 |
| unauthorized_client | 客户端无权请求 |
| access_denied | 资源所有者、认证服务器拒绝 |
| unsupported_response_type | response_type类型不支持 |
| invalid_scope | 作用域无效 |
| server_error | 服务器内部错误 |
| temporarily_unavailable | 服务器临时不可用 |



