OAuth2.0

李AK發表於2020-11-18

官方文件https://tools.ietf.org/html/rfc6749

1. why

The OAuth 2.0 認證框架使第三方應用受限的訪問http服務成為了可能

2. what在這裡插入圖片描述

圖去中示範的OAuth 2.0協議流描述了四個角色之間的互動。包含一下步驟:

(A)客戶端請求資源擁有者的認證,認證請求可以直接發給資源擁有者(如圖所示),或是通過認證伺服器來做中介

(B)客戶端收到認證授權,此認證資訊代表了資源擁有者的認證,表達使用了本規格定義的四種授權型別之一或是使用了擴充套件的授權型別。認證授權型別取決於客戶端請求認證使用的方法和認證伺服器支援的授權型別

(C)客戶端通過認證伺服器驗證和展示認證授權來請求訪問令牌

(D)認證伺服器驗證客戶端並確認認證授權是否有效,如果有效,分發一個訪問令牌

(E)客戶端通過呈現訪問令牌請求資源伺服器的受保護資源

(F)資源伺服器確認訪問令牌的有效性,如果有效,處理請求

參考https://www.cnblogs.com/cjsblog/p/9174797.html

授權碼模式

參考 https://www.cnblogs.com/jfire/p/11973092.html

其中授權碼模式是步驟流程最為詳細嚴謹的一種模式。而網路上大部分的第三方Oauth2實現都是基於授權碼模式的。本文也是主要講解授權碼模式中的相關流程性問題。

下面來分別講解其中的幾個點

第三方引導使用者跳轉至認證伺服器的授權頁面

在引導跳轉的時候需要攜帶如下的幾個引數

  1. response_type:授權型別。授權碼模式下,就固定為code
  2. app_id:第三方應用的標識id。
  3. redirect_uri:重定向uri,也就是在授權成功後認證伺服器讓使用者重定向的地址。一般而言也就是當前使用者在第三方應用中最初的請求地址
  4. scope:授權範圍。可選內容,可以根據第三方應用和實現方的要求自行制定合適的值。
  5. state:透明的驗證引數。RFC6749文件推薦認證伺服器在重定向的時候應該原封不同的返還這個引數。注意,該引數嚴格來說應該是一個必須引數。用來防止CSRF攻擊。也就是說用於讓第三方伺服器驗證重定向回來的uri的確是認證伺服器的行為而不是其他的攻擊者偽造的。一般來說跳轉到認證伺服器的授權頁面是走的https,但是認證伺服器重定向到回撥地址的時候可能走的就是http。此時code存在洩漏以及url存在被偽造的風險。那麼第三方應用必須要有辦法驗證該回撥是否的確由認證伺服器發起,並且的確是之前自己的授權請求導致的回撥。做法其實也不復雜,就是在session中儲存一個隨機值,作為state引數。認證伺服器回撥的時候帶上該state引數,第三方應用驗證該引數是否與自己session中的state引數值一致即可。如果認證的授權頁面不是https加密的,那麼在發出請求的時候,認證state引數可能會被竊取。那麼這個時候還有另外一種做法。也就是第三方應用傳送的是加密後的state引數,而認證伺服器重定向的時候攜帶的是解密後的state引數。第三方應用只要在session中判斷解密後的值是否與session的一致,也可以達到防止攻擊的目的。這樣,授權頁面也就是可以走在普通的http之中了。

使用者選擇是否給予授權

這一步是一個使用者行為。目前基本的做法都是讓使用者在授權頁面上輸入使用者名稱和密碼。為了保證安全性,這個頁面需要由https來進行保護。當然,如果有其他的方式來保證使用者名稱密碼,以及認證的state引數不會洩露也是可以的。如果使用者輸入正確的使用者名稱和密碼,一般就確認為使用者給予授權。

認證伺服器生成code並且讓使用者重定向至指定的url

如果使用者給予授權,則認證伺服器需要生成一個唯一的授權碼code。該code的時效性應該比較短,在5分鐘以內比較合適。並且該code只能使用一次,下次就會失效。同時,該code與客戶端的id,redirect-uri引數是一一對應的關係。認證伺服器此時應該讓使用者重定向至一開始指定的redirect_uri。攜帶上state和code引數

第三方應用使用code到認證伺服器處兌換令牌access token

第三方應用在驗證過state引數的正確性後,接著就可以使用code到認證伺服器處換取token。這一步,第三方應用需要攜帶上的引數有

  1. code:就是認證伺服器給予的code引數
  2. appid:客戶端的唯一標識
  3. redirect_uri:也就是第一步請求中的重定向引數。因為code實際上是與appid和redirect_uri一一對應的。所以用code換取令牌的時候也要攜帶上這兩個引數
  4. grant_type: 授權模式,這裡固定為"authorization_code"
  5. appkey:用於驗證應用的身份。appid和appkey可以理解為應用自己的使用者名稱和密碼。
    oauth2的伺服器本身都是走https。所以都可以直接明文傳輸不需要考慮安全性問題。不過如果不是http的,也可以直接引數使用者名稱密碼登入的方式,就是給appkey進行md5運算。
    關於為何不直接傳遞accesstoken的問題,是基於安全考慮。因為認證伺服器是基於Https,而第三方應用可以是http的。如果在回撥的時候直接帶上accesstoken,就存在著洩露的問題。

認證伺服器返回accesstoken

認證伺服器在驗證過引數的合法性後,生成一個全域性唯一的token,並且返回給第三方應用。返回的內容採用json表示,返回的引數主要有

  1. access_token: 用於獲取對應資源的令牌
  2. expires_time: 該令牌的有效期
  3. re flesh_token: 使用者獲取新的accesstoekn的token。由於accesstoken的有效期比較短,一旦失效,使用者需要再走上面的流程是比較繁瑣的。為了提升使用者體驗,可以使用reflesh_token來獲取新的accesstoken。不過這個做法,已經有不同的實現方將這個返回引數去掉了。因為實際上 reflesh_token也就意味著accesstoekn是永久有效的了。那和直接延長accesstoken的有效期也沒有直接區別了。

具體實現-java-Spring Security

Spring Security Oauth2配置

相關文章