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