OAuth 2.0 rfc6749 规范
OAuth 2.0 rfc6749 规范-带目录,阅读 RFC 文档的 工具
OAuth 官网html
OAuth 是受权(authorization)框架,描述了系统中不一样角色(服务提供商、用户、第三方应用)之间怎么实现交互。目前普遍使用的是 2.0 版本。web
常见的应用场景(估计全部人都见过):受权登陆注册。好比微信有不少用户,且微信提供了 OAuth2 接口。在个人网站上,为了简化用户注册流程,对接了微信提供的这个接口,而且在注册页面提供一个“经过微信登陆”的连接或二维码,用户点击后会跳转到微信的受权登陆页面(或者微信扫码进入受权页面),微信在用户受权后会将这个用户的基本信息发到个人网站,完成注册。注册后,每次均可以经过微信受权登陆了。json
若是须要作微信这样的平台型应用,为不少合做伙伴提供受权认证服务,能够考虑搭建本身的 OAuth 2.0 系统。可是要明白,这是挺复杂的一个系统。对于大部分应用开发人员,须要掌握的是如何调用其余平台的接口。浏览器
OAuth2 提供了 4 种角色:安全
另外的经常使用名词有:bash
token 都是字符串,受权服务器须要保存全部的 token 及对应的受权信息,以便校验请求。服务器
用于访问受保护资源的凭证。这个凭证表示特定访问范围和可用时间,由资源全部者受权,并由资源服务器和受权服务器执行,并发给客户端。微信
对资源的访问,须要 access token。并发
用于再次获取 access token 的凭证。这是可选项,能够自行决定是否让受权服务器发布 refresh token。若是发布 refresh token,会跟 access token 一同发出。refresh token 能够在 access token 失效后获取新的 access token,也能够获取更多一个 access token。app
refresh token 只会跟受权服务器交互,不会发送到资源服务器。
Client 有两种类型:
详细差别能够参考 这里。
参考 RFC6750
经过在请求中简单地包含访问令牌字符串来使用:
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer mF_9.B5f-4.1JqM
经过发出消息认证代码(MAC)密钥以及用于签署 HTTP 请求的某些组件的访问令牌来使用:
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC id="h480djs93hd8",
nonce="274312:dj83hs9s",
mac="kDZvddkndxvhGRXZhvuDjEWhGeE="
+--------+ +---------------+
| |--(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 ---| |
+--------+ +---------------+
Figure 1: 抽象的协议流程
详细步骤以下:
在步骤 B 中,客户端能够得到用户的受权。有四种受权模式。
第三方应用必须获得用户受权(authorization grant)后才能得到访问令牌(access token)。OAuth2 支持四种受权模式:
另外,对于已经受权的 Client,还有两种方式能够再次获取 access token:
最经常使用,微信、GitHub 等的受权登陆注册就是这种方式。使用这种模式时,受权服务器会直接将受权发送到客户端的后台服务器,不须要通过用户代理,安全可靠。
+----------+
| 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),(B)和(C)的行在经过用户代理时分为两部分。
Figure 3: 受权码模式的流程
受权码模式用于获取访问令牌和刷新令牌,并针对机密客户端进行了优化。受权码模式基于重定向,受权开始时从客户端跳转到受权服务器的页面,受权完成后受权服务器后台通知客户端,同时跳转回客户端的页面。客户端必须可以与资源全部者的用户代理(一般是 Web 浏览器)进行交互,而且可以从受权服务器接收传入请求。
客户端经过 GET 方式使用如下参数来构造请求 URI:
受权请求示例:
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
受权服务器的响应也是“application/x-www-form-urlencoded”格式,包含如下参数:
受权响应示例:
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
客户端经过 POST 方式使用“application/x-www-form-urlencoded”格式将如下参数来构造请求 URI:
示例:
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
受权成功后,响应包含如下参数:
示例:
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" }
+----------+
| 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)的行在经过用户代理时分为两部分。
Figure 4: 隐式受权模式的流程
客户端经过添加下面的参数来构造请求 URI
客户端使用 HTTP 重定向响应或经过用户代理可用的其余方式将资源全部者定向到构造的 URI。示例:
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
受权服务器必须验证 redirect_uri 参数是否和客户端预留的参数一致。
用户受权后,受权服务器会颁发一个 access token 并发送到客户端,可用参数以下:
注意:这里没有 refresh token。
示例:
HTTP/1.1 302 Found
Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
&state=xyz&token_type=example&expires_in=3600
+----------+
| Resource |
| Owner |
| |
+----------+
v
| Resource Owner
(A) Password Credentials
|
v
+---------+ +---------------+
| |>--(B)---- Resource Owner ------->| |
| | Password Credentials | Authorization |
| Client | | Server |
| |<--(C)---- Access Token ---------<| |
| | (w/ Optional Refresh Token) | |
+---------+ +---------------+
Figure 5: 密码模式流程
资源全部者将用户名和密码发送给客户端,而后客户端用这些凭证获取受权。
客户端经过 GET 方式使用如下参数来构造请求 URI:
受权请求示例:
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
受权成功后,响应包含如下参数:
示例:
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" }
+---------+ +---------------+
| | | |
| |>--(A)- Client Authentication --->| Authorization |
| Client | | Server |
| |<--(B)---- Access Token ---------<| |
| | | |
+---------+ +---------------+
Figure 6: Client Credentials Flow
客户端以本身的名义,而不是以用户的名义,向”服务提供商”进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以本身的名义要求”服务提供商”提供服务,其实不存在受权问题。
客户端经过 GET 方式使用如下参数来构造请求 URI:
受权请求示例:
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
受权成功后,响应包含如下参数:
示例:
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" }
+--------+ +---------------+
| |--(A)------- Authorization Grant --------->| |
| | | |
| |<-(B)----------- Access Token -------------| |
| | & Refresh Token | |
| | | |
| | +----------+ | |
| |--(C)---- Access Token ---->| | | |
| | | | | |
| |<-(D)- Protected Resource --| Resource | | Authorization |
| Client | | Server | | Server |
| |--(E)---- Access Token ---->| | | |
| | | | | |
| |<-(F)- Invalid Token Error -| | | |
| | +----------+ | |
| | | |
| |--(G)----------- Refresh Token ----------->| |
| | | |
| |<-(H)----------- Access Token -------------| |
+--------+ & Optional Refresh Token +---------------+
Figure 2: 刷新过时的 Access Token
客户端经过 GET 方式使用如下参数来构造请求 URI:
受权请求示例:
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