auth2.0四種受權模式

OAuth 2.0 的標準是 RFC 6749 文件 。html

OAuth 2.0 規定了四種得到令牌的流程。你能夠選擇最適合本身的那一種,向第三方應用頒發令牌。下面就是這四種受權方式。前端

  • 受權碼(authorization-code)
  • 隱藏式(implicit)
  • 密碼式(password):
  • 客戶端憑證(client credentials)

注意,無論哪種受權方式,第三方應用申請令牌以前,都必須先到系統備案,說明本身的身份,而後會拿到兩個身份識別碼:客戶端 ID(client ID)和客戶端密鑰(client secret)。這是爲了防止令牌被濫用,沒有備案過的第三方應用,是不會拿到令牌的。後端

第一種受權方式:受權碼

受權碼(authorization code)方式,指的是第三方應用先申請一個受權碼,而後再用該碼獲取令牌。api

這種方式是最經常使用的流程,安全性也最高,它適用於那些有後端的 Web 應用。受權碼經過前端傳送,令牌則是儲存在後端,並且全部與資源服務器的通訊都在後端完成。這樣的先後端分離,能夠避免令牌泄漏。瀏覽器

第一步,A 網站提供一個連接,用戶點擊後就會跳轉到 B 網站,受權用戶數據給 A 網站使用。下面就是 A 網站跳轉 B 網站的一個示意連接。安全

https://b.com/oauth/authorize?
  response_type=code&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read

上面 URL 中,response_type參數表示要求返回受權碼(code),client_id參數讓 B 知道是誰在請求,redirect_uri參數是 B 接受或拒絕請求後的跳轉網址,scope參數表示要求的受權範圍(這裏是只讀)。服務器

第二步,用戶跳轉後,B 網站會要求用戶登陸,而後詢問是否贊成給予 A 網站受權。用戶表示贊成,這時 B 網站就會跳回redirect_uri參數指定的網址。跳轉時,會傳回一個受權碼,就像下面這樣。session

https://a.com/callback?code=AUTHORIZATION_CODE

上面 URL 中,code參數就是受權碼。前後端分離

第三步,A 網站拿到受權碼之後,就能夠在後端,向 B 網站請求令牌。curl

https://b.com/oauth/token?
 client_id=CLIENT_ID&
 client_secret=CLIENT_SECRET&
 grant_type=authorization_code&
 code=AUTHORIZATION_CODE&
 redirect_uri=CALLBACK_URL

上面 URL 中,client_id參數和client_secret參數用來讓 B 確認 A 的身份(client_secret參數是保密的,所以只能在後端發請求),grant_type參數的值是AUTHORIZATION_CODE,表示採用的受權方式是受權碼,code參數是上一步拿到的受權碼,redirect_uri參數是令牌頒發後的回調網址。

第四步,B 網站收到請求之後,就會頒發令牌。具體作法是向redirect_uri指定的網址,發送一段 JSON 數據。

{    
  "access_token":"ACCESS_TOKEN",
  "token_type":"bearer",
  "expires_in":2592000,
  "refresh_token":"REFRESH_TOKEN",
  "scope":"read",
  "uid":100101,
  "info":{...}
}

上面 JSON 數據中,access_token字段就是令牌,A 網站在後端拿到了。

第二種方式:隱藏式

有些 Web 應用是純前端應用,沒有後端。這時就不能用上面的方式了,必須將令牌儲存在前端。RFC 6749 就規定了第二種方式,容許直接向前端頒發令牌。這種方式沒有受權碼這個中間步驟,因此稱爲(受權碼)"隱藏式"(implicit)。

第一步,A 網站提供一個連接,要求用戶跳轉到 B 網站,受權用戶數據給 A 網站使用。

https://b.com/oauth/authorize?
  response_type=token&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read

上面 URL 中,response_type參數爲token,表示要求直接返回令牌。

第二步,用戶跳轉到 B 網站,登陸後贊成給予 A 網站受權。這時,B 網站就會跳回redirect_uri參數指定的跳轉網址,而且把令牌做爲 URL 參數,傳給 A 網站。

https://a.com/callback#token=ACCESS_TOKEN

上面 URL 中,token參數就是令牌,A 網站所以直接在前端拿到令牌。

注意,令牌的位置是 URL 錨點(fragment),而不是查詢字符串(querystring),這是由於 OAuth 2.0 容許跳轉網址是 HTTP 協議,所以存在"中間人攻擊"的風險,而瀏覽器跳轉時,錨點不會發到服務器,就減小了泄漏令牌的風險。

這種方式把令牌直接傳給前端,是很不安全的。所以,只能用於一些安全要求不高的場景,而且令牌的有效期必須很是短,一般就是會話期間(session)有效,瀏覽器關掉,令牌就失效了。

第三種方式:密碼式

若是你高度信任某個應用,RFC 6749 也容許用戶把用戶名和密碼,直接告訴該應用。該應用就使用你的密碼,申請令牌,這種方式稱爲"密碼式"(password)。

第一步,A 網站要求用戶提供 B 網站的用戶名和密碼。拿到之後,A 就直接向 B 請求令牌。

https://oauth.b.com/token?
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  client_id=CLIENT_ID

上面 URL 中,grant_type參數是受權方式,這裏的password表示"密碼式",usernamepassword是 B 的用戶名和密碼。

第二步,B 網站驗證身份經過後,直接給出令牌。注意,這時不須要跳轉,而是把令牌放在 JSON 數據裏面,做爲 HTTP 迴應,A 所以拿到令牌。

這種方式須要用戶給出本身的用戶名/密碼,顯然風險很大,所以只適用於其餘受權方式都沒法採用的狀況,並且必須是用戶高度信任的應用。

第四種方式:憑證式

最後一種方式是憑證式(client credentials),適用於沒有前端的命令行應用,即在命令行下請求令牌。

第一步,A 應用在命令行向 B 發出請求。

https://oauth.b.com/token?
  grant_type=client_credentials&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET

上面 URL 中,grant_type參數等於client_credentials表示採用憑證式,client_idclient_secret用來讓 B 確認 A 的身份。

第二步,B 網站驗證經過之後,直接返回令牌。

這種方式給出的令牌,是針對第三方應用的,而不是針對用戶的,即有可能多個用戶共享同一個令牌。

令牌的使用

A 網站拿到令牌之後,就能夠向 B 網站的 API 請求數據了。

此時,每一個發到 API 的請求,都必須帶有令牌。具體作法是在請求的頭信息,加上一個Authorization字段,令牌就放在這個字段裏面。

curl -H "Authorization: Bearer ACCESS_TOKEN" \
"https://api.b.com"

上面命令中,ACCESS_TOKEN就是拿到的令牌。

更新令牌

令牌的有效期到了,若是讓用戶從新走一遍上面的流程,再申請一個新的令牌,極可能體驗很差,並且也沒有必要。OAuth 2.0 容許用戶自動更新令牌。

具體方法是,B 網站頒發令牌的時候,一次性頒發兩個令牌,一個用於獲取數據,另外一個用於獲取新的令牌(refresh token 字段)。令牌到期前,用戶使用 refresh token 發一個請求,去更新令牌。

https://b.com/oauth/token?
  grant_type=refresh_token&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET&
  refresh_token=REFRESH_TOKEN

上面 URL 中,grant_type參數爲refresh_token表示要求更新令牌,client_id參數和client_secret參數用於確認身份,refresh_token參數就是用於更新令牌的令牌。

B 網站驗證經過之後,就會頒發新的令牌。

相關文章
相關標籤/搜索