《OAuth 2.0 簡(jiǎn)明教程 中文》

OAuth 2.0 完整規(guī)格太長(zhǎng)了,不便閱讀,所以有了此帖

  1. 角色: 應(yīng)用、接口、用戶
  2. 創(chuàng)建一個(gè)應(yīng)用
  3. 授權(quán): 獲取訪問(wèn)令牌
    • 3.1 Web 服務(wù)器應(yīng)用
    • 3.2 單頁(yè)應(yīng)用
    • 3.3 移動(dòng)應(yīng)用
    • 3.4 其他授權(quán)類型
  4. 發(fā)起認(rèn)證請(qǐng)求
  5. OAuth 2.0 和 OAuth 1.0 的不同之處
    • 認(rèn)證和簽名
    • 用戶體驗(yàn)和其他可選授權(quán)流程
    • 彈性伸縮下的性能

1. 角色:

  • 第三方應(yīng)用: "Client": 客戶端是一個(gè)想訪問(wèn)用戶賬號(hào)的應(yīng)用,在此之前客戶端必須獲得用戶的許可。
  • 接口: "Resource Server": 資源服務(wù)器是一個(gè)接口服務(wù)器,用于訪問(wèn)用戶信息。
  • 授權(quán)服務(wù)器: 提供用戶批準(zhǔn)或拒絕請(qǐng)求的接口的服務(wù)器。在較小的實(shí)現(xiàn)中,這可能和 API 服務(wù)器是一個(gè)服務(wù)器,但是較大規(guī)模的部署中通常將其構(gòu)建為單獨(dú)的組件。
  • 用戶: "Resource Ownner": 資源擁有者是一個(gè)給出自己部分賬號(hào)信息供訪問(wèn)的人。

2. 創(chuàng)建一個(gè)應(yīng)用:

在開始 OAuth 流程之前,必須先向 OAuth 服務(wù)注冊(cè)你的應(yīng)用。注冊(cè)新的應(yīng)用時(shí),通常要注冊(cè)一些基本信息,如應(yīng)用的名稱、網(wǎng)站、徽標(biāo)等。此外,必須注冊(cè)用于將用戶重定向到 Web 服務(wù)器、單頁(yè)應(yīng)用或移動(dòng)應(yīng)用的重定向 URI。

  • Redirect URIs: OAuth 服務(wù)僅將用戶重定向到注冊(cè)過(guò)的 URI,這有助于防止一些攻擊。任何 HTTP 重定向 URI 都必須用 TLS 安全保護(hù),即,僅重定向到以 “https” 開頭的 URI。這樣可以防止在授權(quán)過(guò)程中令牌被截獲。原生移動(dòng)應(yīng)用可以注冊(cè)一個(gè)使用自定義 URL 方案的重定向 URI,它可能類似于 demoapp://redirect
  • Client ID and Secret: 注冊(cè)應(yīng)用后,您將收到一個(gè)客戶端 ID 和一個(gè)客戶端密碼。客戶端 ID 作為一個(gè)可以公開的信息,可以用來(lái)構(gòu)建登錄 URL,或者包含在 Javascript 代碼中。而客戶端密碼必須保持機(jī)密性。如果部署的應(yīng)用程序不能保持機(jī)密(例如單頁(yè) Javascript 應(yīng)用或本機(jī)應(yīng)用程序),就不要使用客戶端密碼。最好情況,OAuth 服務(wù)最初就不應(yīng)向這種類型的應(yīng)用發(fā)布客戶端密碼。

3. 授權(quán) Authorization:

Oauth2 第一步就是從用戶獲得授權(quán)。對(duì)于基于瀏覽器的應(yīng)用或移動(dòng)應(yīng)用來(lái)說(shuō),通常是向用戶展示授權(quán)服務(wù)提供的界面就行了。

Oauth2 提供幾種常見的 授權(quán)類型 "grant types"

  • Authorization Code - 主要用于 web 服務(wù)器、基于瀏覽器和移動(dòng)的應(yīng)用
  • Password - 主要用于使用用戶名和密碼登陸
  • Client credentials - 主要用于應(yīng)用程序訪問(wèn)
  • Implicit - 之前被推薦用在沒(méi)機(jī)密性的客戶端上,目前已經(jīng)被 Authorization Code 取代(不使用客戶端密碼)!
    接下來(lái)會(huì)詳細(xì)描述每種用例。

3.1 Web 服務(wù)器應(yīng)用

Web 服務(wù)器應(yīng)用是處理 Oauth 服務(wù)時(shí)最常見的應(yīng)用類型。Web 服務(wù)器應(yīng)用使用服務(wù)器端語(yǔ)言編寫,在源代碼對(duì)外不可見的服務(wù)器上運(yùn)行。這就意味著 Web 服務(wù)器應(yīng)用在和授權(quán)服務(wù)器通信時(shí)可以使用客戶端密碼,這樣就可以避免一些攻擊侵入。

授權(quán)環(huán)節(jié):

創(chuàng)建一個(gè)“登錄”鏈接,鏈接可以引導(dǎo)用戶到:

https://authorization-server.com/auth?response_type=code&
  client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos&state=1234zyx
  • response_type=code - 表明服務(wù)器期望接收一個(gè)授權(quán)碼
  • client_id - 創(chuàng)建應(yīng)用時(shí)收到的(在授權(quán)服務(wù)器注冊(cè)的)客戶端 ID
  • redirect_uri - 如果授權(quán)完成后要把用戶帶回到的 URI
  • scope - 一個(gè)或多個(gè)范圍值,表明希望訪問(wèn)用戶賬號(hào)信息的哪些部分
  • state - 由你的應(yīng)用生成的一個(gè)隨機(jī)字符串,稍后你將拿它作校驗(yàn)(防范CSRF攻擊)

用戶將看到授權(quán)提示:

oauth-authorization-prompt

如果用戶選擇“允許”,授權(quán)服務(wù)器返回授權(quán)碼,把用戶重定向回你的網(wǎng)站。

https://example-app.com/cb?code=AUTH_CODE_HERE&state=1234zyx
  • code - 授權(quán)服務(wù)器返回的授權(quán)碼(在查詢字符串中)
  • state - 授權(quán)服務(wù)器返回的狀態(tài)值(和你傳過(guò)去的狀態(tài)值相同)

你首先應(yīng)該比較返回的狀態(tài)值是否和剛開始的一致(通常你可以把狀態(tài)值存儲(chǔ)在 cookie 或 session 中)。這樣能確保重定向端點(diǎn)沒(méi)有安全問(wèn)題。

交換令牌環(huán)節(jié):

你的應(yīng)用會(huì)拿授權(quán)碼交換訪問(wèn)令牌:

POST https://api.authorization-server.com/token
  grant_type=authorization_code&
  code=AUTH_CODE_HERE&
  redirect_uri=REDIRECT_URI&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET
  • grant_type=authorization_code - 本次的授權(quán)類型是: authorization_code
  • code=AUTH_CODE_HERE -這是你從查詢字符串收到的 code
  • redirect_uri=REDIRECT_URI - 必須和原始鏈接中提供的重定向 URI 相同(即:和授權(quán)環(huán)節(jié)的重定向 URL 相同)
  • client_id=CLIENT_ID - 你首次創(chuàng)建應(yīng)用程序時(shí)收到的客戶端ID
  • client_secret=CLIENT_SECRET - 本次請(qǐng)求是由 Web 服務(wù)器類型的應(yīng)用發(fā)出的,因此要有客戶端密碼(單頁(yè)應(yīng)用/基于瀏覽器的應(yīng)用不需要?。?!

授權(quán)服務(wù)器回復(fù)訪問(wèn)令牌和過(guò)期時(shí)間:

{
  "access_token":"RsT5OjbzRn430zqMLgV3Ia",
  "expires_in":3600
}

或者一個(gè)錯(cuò)誤:

{
  "error":"invalid_request"
}

請(qǐng)注意,授權(quán)服務(wù)必須要求應(yīng)用程序提前注冊(cè)它們的重定向 URI!

3.2 單頁(yè)應(yīng)用

單頁(yè)應(yīng)用/基于瀏覽器的應(yīng)用,從網(wǎng)頁(yè)加載源代碼后完全在瀏覽器中運(yùn)行。因?yàn)樵创a對(duì)瀏覽器完全可見,無(wú)法保證客戶端密碼的機(jī)密性。所以不能使用客戶端密碼。除此之外,和上面例子的流程完全一樣。

注意: 在以前,單頁(yè)應(yīng)用/基于瀏覽器的應(yīng)用建議使用 "Implicit"授權(quán)類型的流程(該流程會(huì)立即返回訪問(wèn)令牌,不需要令牌交換環(huán)節(jié))。不過(guò)現(xiàn)在業(yè)界最佳實(shí)踐已經(jīng)改變了,當(dāng)前的建議是在不使用客戶端密碼的前提下使用 “授權(quán)碼 authorization code” 授權(quán)類型流程。該流程提供更多安全方案的可能,比如:PKCE 擴(kuò)展(參考:OAuth 2.0安全最佳當(dāng)前實(shí)踐OAuth 2.0用于基于瀏覽器的應(yīng)用程序

3.3 移動(dòng)應(yīng)用

像基于瀏覽器的應(yīng)用一樣,移動(dòng)應(yīng)用也不能保證客戶端密碼的機(jī)密性。因?yàn)檫@個(gè),移動(dòng)應(yīng)用在使用 Oauth 流程時(shí)也不能用客戶端密碼。為確保 Oauth 流程的安全性,移動(dòng)應(yīng)用必須牢記一些額外的事項(xiàng)!

注意: 在以前,移動(dòng)應(yīng)用/原生應(yīng)用建議使用 "Implicit"授權(quán)類型的流程,不過(guò)現(xiàn)在業(yè)界最佳實(shí)踐已經(jīng)改變了,當(dāng)前的建議是在不使用客戶端密碼的前提下使用 “授權(quán)碼 authorization code” 授權(quán)類型流程。當(dāng)然這里還為移動(dòng)應(yīng)用準(zhǔn)備了一些有價(jià)值的附加建議。

授權(quán)環(huán)節(jié):

創(chuàng)建一個(gè) "登錄" 按鈕, 該按鈕將引導(dǎo)用戶到提供授權(quán)服務(wù)的原生應(yīng)用,或者提供授權(quán)服務(wù)的移動(dòng)網(wǎng)頁(yè)(都在手機(jī)上)。如果你用的是 iphone, 應(yīng)用可以注冊(cè)自定義 uri 方案, 如 "facebook://", 每當(dāng)訪問(wèn)具有該協(xié)議的 url 時(shí), 就會(huì)啟動(dòng)本機(jī) facebook 應(yīng)用程序。如果你用的是 android, 應(yīng)用可以注冊(cè) url 匹配模式, 如果訪問(wèn)了與該模式匹配的 url, 該模式將啟動(dòng)提供授權(quán)服務(wù)的原生應(yīng)用。

使用(提供授權(quán)服務(wù)的)原生應(yīng)用:

如果用戶已經(jīng)安裝了 Facebook 移動(dòng)應(yīng)用,按鈕將引導(dǎo)用戶定向到以下URL:(參數(shù)不再做解釋)

fbauth2://authorize?response_type=code&client_id=CLIENT_ID
  &redirect_uri=REDIRECT_URI&scope=email&state=1234zyx

如果授權(quán)服務(wù)支持 PKCE 擴(kuò)展(推薦),你也應(yīng)該包含以下參數(shù)。提前是你的應(yīng)用(第三方應(yīng)用)中創(chuàng)建的有一個(gè)“驗(yàn)證碼 code_verifier”(在你的應(yīng)用本地存儲(chǔ)的一個(gè)隨機(jī)字符串,交換令牌環(huán)節(jié)會(huì)用到)

  • code_challenge=XXXXXXX - 驗(yàn)證碼(code_verifier)經(jīng)過(guò)混淆后的字符串( base64 編碼后 sha256 散列)
  • code_challenge_method=S256 - 指明混淆的加密方法,本例中為 sha256

注意: 重定向的 URI 可能看起來(lái)像 fb00000000://author...,其中的協(xié)議是應(yīng)用在 OS 中注冊(cè)的自定義 URL 方案。

在 Web 瀏覽器中使用授權(quán)服務(wù):

如果手機(jī)上沒(méi)有提供授權(quán)服務(wù)的移動(dòng)/原生應(yīng)用,可以啟動(dòng)移動(dòng)瀏覽器使用標(biāo)準(zhǔn)的 Web 授權(quán) URL。請(qǐng)注意,絕不應(yīng)該在你自己的應(yīng)用中使用嵌入式的 web 視圖,因?yàn)檫@樣不能保證用戶正在真正提供授權(quán)服務(wù)的網(wǎng)站上輸入密碼而不是釣魚站點(diǎn)中。

你應(yīng)該啟動(dòng)一個(gè)移動(dòng)瀏覽器,也可以在你的應(yīng)用中使用 新的 iOS 的 "SafariViewController" 接口來(lái)啟動(dòng)一個(gè)內(nèi)置瀏覽器。這個(gè)接口是 iOS 9 中新增的接口,它提供了一種在應(yīng)用程序內(nèi)部啟動(dòng)瀏覽器的機(jī)制,該瀏覽器還可以顯示地址欄,以便用戶可以確認(rèn)他們?cè)谡_的網(wǎng)站上,又和真正的 Safar i瀏覽器共享 cookie。它還保護(hù)瀏覽器的內(nèi)容不被監(jiān)聽和修改,因此可以認(rèn)為是安全的。

同樣,如果授權(quán)服務(wù)支持 PKCE,那么應(yīng)該像上面描述的那樣包括那些參數(shù)。(參數(shù)不再做解釋)

https://facebook.com/dialog/oauth?response_type=code&client_id=CLIENT_ID
  &redirect_uri=REDIRECT_URI&scope=email&state=1234zyx

交換令牌環(huán)節(jié):

當(dāng)單擊“批準(zhǔn)”之后,用戶將被重定向回應(yīng)用程序,其URL就像這樣: fb00000000://authorize?code=AUTHORIZATION_CODE&state=1234zyx

你的移動(dòng)應(yīng)用應(yīng)該首先驗(yàn)證該狀態(tài)值是否和初始請(qǐng)求中使用的狀態(tài)值相同,然后就可以拿授權(quán)代碼交換訪問(wèn)令牌。

交換令牌的過(guò)程看起來(lái)與 Web 服務(wù)器應(yīng)用下的完全相同,只是沒(méi)有發(fā)送客戶端密碼。如果服務(wù)器支持 PKCE,則需要包括如下所述的附加參數(shù):

POST https://api.authorization-server.com/token
  grant_type=authorization_code&
  code=AUTH_CODE_HERE&
  redirect_uri=REDIRECT_URI&
  client_id=CLIENT_ID&
  code_verifier=VERIFIER_STRING
  • code_verifier=VERIFIER_STRING - 驗(yàn)證碼:明文字符串(你之前把它哈希散列混淆后用來(lái)創(chuàng)建 code_challenge)

授權(quán)服務(wù)器將驗(yàn)證此請(qǐng)求并返回訪問(wèn)令牌。如果服務(wù)器支持PKCE,則授權(quán)服務(wù)器將校驗(yàn)該驗(yàn)證碼(對(duì)提供的明文進(jìn)行哈希散列,并確認(rèn)散列混淆后和初始授權(quán)請(qǐng)求中發(fā)送的散列字符串是否一致)。這就確保了在不支持客戶端密碼的第三方客戶端中使用授權(quán)碼授權(quán)類型的流程安全性。

3.4 其他授權(quán)類型

Password:

OAuth 2還提供了一種 “Password” 授權(quán)類型, 該類型用來(lái)直接使用用戶名和密碼交換訪問(wèn)令牌。 很顯然,應(yīng)用程序需要搜集用戶的密碼,所以該授權(quán)類型只能提供給被授權(quán)服務(wù)自己創(chuàng)建的應(yīng)用使用。 比如,一個(gè) Twitter 的應(yīng)用程序可以使用這種授權(quán)類型登錄 Twitter 的移動(dòng)或桌面應(yīng)用。

要使用密碼授權(quán)類型,只需發(fā)出如下 POST 請(qǐng)求:

POST https://api.authorization-server.com/token
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  client_id=CLIENT_ID

授權(quán)服務(wù)器回復(fù)一個(gè)訪問(wèn)令牌,令牌的格式和其他授權(quán)類型的相同。 注意:不能包含客戶端密碼!因?yàn)樵撌跈?quán)類型假定使用情景都是移動(dòng)或桌面應(yīng)用,這樣是無(wú)法保護(hù)密碼的。

Application access:

有時(shí),應(yīng)用可能需要訪問(wèn)令牌來(lái)代表自己,而不是代表用戶進(jìn)行操作。比如,一個(gè)服務(wù)可能提供一種方式讓應(yīng)用更新自己信息(如:網(wǎng)址,徽標(biāo),或者他們可能希望獲取應(yīng)用上的用戶的統(tǒng)計(jì)數(shù)據(jù))。這種情況下,應(yīng)用除了需要特殊用戶的上下文外,也需要為自己獲取訪問(wèn)令牌, Oauth 為此提供了 “客戶端憑證 client_credentials” 授權(quán)類型。

要使用客戶端憑證授權(quán)類型,請(qǐng)發(fā)出如下POST請(qǐng)求:

POST https://api.authorization-server.com/token
    grant_type=client_credentials&
    client_id=CLIENT_ID&
    client_secret=CLIENT_SECRET

響應(yīng)將包括和其他授權(quán)類型相同格式的訪問(wèn)令牌。

4. 發(fā)起認(rèn)證請(qǐng)求

無(wú)論哪種授權(quán)類型,最終結(jié)果是獲得訪問(wèn)令牌?,F(xiàn)在有了訪問(wèn)令牌,就可以向API發(fā)出請(qǐng)求了。您可以使用 cURL 快速做出 API 請(qǐng)求,如下所示:

curl -H "Authorization: Bearer RsT5OjbzRn430zqMLgV3Ia" \
https://api.authorization-server.com/1/me

就是這樣!確保始終通過(guò) HTTPS 發(fā)送請(qǐng)求,并且永遠(yuǎn)不要忽略無(wú)效的證書。HTTPS 是唯一保護(hù)請(qǐng)求不被攔截或修改的東西。

5. OAuth 2.0 和 OAuth 1.0 的不同之處

OAuth 1.0 主要基于當(dāng)時(shí)現(xiàn)有的專屬協(xié)議,比如 Flickr 的 “FlickrAuth” 和 Google 的 “AuthSub”,它是當(dāng)時(shí)實(shí)際運(yùn)作經(jīng)驗(yàn)提煉的最佳解決方案。盡管如此,在該協(xié)議下運(yùn)作了幾年后,社區(qū)通過(guò)不斷學(xué)習(xí),覺(jué)得 Oauth 1.0 有三個(gè)的方面需要反思和提升:

5.1 認(rèn)證和簽名

大部分開發(fā)人員對(duì) OAuth 1.0 的煩惱來(lái)自使用客戶端 ID 和密碼對(duì)請(qǐng)求進(jìn)行簽名并加密的需求。 無(wú)法輕松復(fù)制和粘貼 cURL 樣例,快速上手變得很難。

OAuth 2 認(rèn)識(shí)到了難處并將簽名替換為瀏覽器、客戶端和API之間的所有通信都需要HTTPS。

5.2 用戶體驗(yàn)和其他可選授權(quán)流程

OAuth 包括兩個(gè)主要部分,獲取訪問(wèn)令牌,并使用訪問(wèn)令牌進(jìn)行請(qǐng)求。OAuth 1.0 最適合于桌面 Web 瀏覽器,但是無(wú)法為本地桌面和移動(dòng)應(yīng)用程序或設(shè)備(如游戲或電視控制臺(tái))提供良好的用戶體驗(yàn)。

OAuth 2.0 為原生應(yīng)用提供了更好的用戶體驗(yàn),并且支持?jǐn)U展協(xié)議以便與未來(lái)的設(shè)備兼容。

5.3 彈性伸縮下的性能

隨著較大的提供商開始使用 OAuth 1.0,社區(qū)很快意識(shí)到該協(xié)議不能很好地?cái)U(kuò)展。許多步驟需要狀態(tài)管理和臨時(shí)憑證,這需要共享存儲(chǔ),并且很難跨數(shù)據(jù)中心同步。OAuth 1.0 還要求 API 服務(wù)器能夠訪問(wèn)應(yīng)用程序的ID和密碼,這常常會(huì)破壞大多數(shù)大型提供商的體系結(jié)構(gòu)(大多數(shù)大型提供商的授權(quán)服務(wù)器和API服務(wù)器是完全獨(dú)立的)。

OAuth 2.0 支持獲取用戶授權(quán)和處理API調(diào)用兩個(gè)角色的分離。較大的提供商需要這種彈性以便自由地實(shí)現(xiàn)功能,而較小的提供商如果愿意,可以為兩個(gè)角色使用相同的服務(wù)器。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文以一種簡(jiǎn)化的格式描述OAuth 2.0 ,以幫助開發(fā)人員和服務(wù)提供者實(shí)現(xiàn)該協(xié)議。 The OAuth 2 sp...
    JacoChan閱讀 4,322評(píng)論 1 11
  • OAuth是一個(gè)關(guān)于授權(quán)(authorization)的開放網(wǎng)絡(luò)標(biāo)準(zhǔn),在全世界得到廣泛應(yīng)用,目前的版本是2.0版。...
    謝謝寫閱讀 826評(píng)論 0 1
  • 這篇文章主要介紹了OAuth 2.0授權(quán)協(xié)議詳解,本文對(duì)OAuth協(xié)議做了詳解講解,對(duì)OAuth協(xié)議的各個(gè)方面做了...
    上山砍柴閱讀 1,325評(píng)論 0 5
  • 在藍(lán)天白云下的海灘 遠(yuǎn)處的沙雕 靜靜的望著遠(yuǎn)方 遠(yuǎn)方好似藏著他的秘密 依著閑暇時(shí)光 姑娘將一顆素心 披上滿滿的明媚...
    愛(ài)上一葉浮萍閱讀 301評(píng)論 0 4
  • 那天你忽然說(shuō):你心里有團(tuán)火 聽的人一霎亂了神 兀自不語(yǔ)好一會(huì) 黙然別過(guò)頭去 眼里冒了淚花 無(wú)以言對(duì) 回來(lái)的日子里 ...
    丁松青閱讀 263評(píng)論 12 19

友情鏈接更多精彩內(nèi)容