OAuth2 為什麼需要 Authorization Code?
emm。。。今天我搜了一下OAuth2的流程,發現無論是中文還是英文,一上來都是跟你講,一共是五個步驟blablabla。。。
我就在想,為啥不能不要五步,OAuth2為什麼中間需要一個 Authorization Code 呢?為什麼不能直接:
- 向指定的OAuth伺服器發起請求,並且帶上回調地址
- 使用者同意授權
-
OAuth伺服器重定向到給定的回撥地址並且把生成的
access_token
和refresh_token
帶上
+--------++---------------+ ||--(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 ---|| +--------++---------------+
結果沒有哪個教程直接了當的告訴我可以。其實想到這一步是很自然的,為什麼三步能做完的事情要
五步來做呢?例如,我做了一個應用,使用微博登入。第一步,到微博的OAuth2伺服器,第二步,
我點選允許使用微博登入,第三步,微博的OAuth2伺服器回撥我給定的地址並且附帶上access_token
和refresh_token
。
然後我去翻了ofollow,noindex" target="_blank">RFC6749 , 才發現這是可以的。OAuth2一共有四種模式:
-
第一種:
- 首先使用者在客戶端上點選要用哪個系統的OAuth2來認證,此時客戶端附上回調地址
- 使用者在OAuth2伺服器上選擇是否授權
- 使用者給予授權,OAuth2伺服器重定向到第一步給定的回撥地址,同時附上 Authorization Code
-
回撥地址所在伺服器帶上 Authorization Code向OAuth2伺服器申請
access_token
和refresh_token
-
OAuth2伺服器返回
access_token
和refresh_token
-
第二種:
- 使用者在客戶端上點選要哪個系統的OAuth2來認證,此時客戶端附上回調地址
- 使用者在OAuth2伺服器上選擇是否授權
-
使用者給於授權,OAuth2伺服器重定向到第一步給定的回撥地址,並且附上
access_token
和refresh_token
-
第三種:
- 使用者直接輸入使用者名稱和密碼,這種情況針對自家的APP或者100%信任的APP可以這麼幹
-
第四種:
- 客戶端自帶認證,使用者向客戶端認證就可以
後來看完RFC發現這樣一個特點,一般第二種是用於瀏覽器的,第一種是用於APP的。其實我覺得沒差。因為HTTP
請求裡的所有欄位都可以偽造呀,伺服器很難分清楚到底是來自APP還是瀏覽器的吧。唯一一個想得到的說的通的
原因就是:第一種方式OAuth2伺服器具有更強的控制權
。為什麼呢?第一種方式裡,可以要求客戶端預先
在OAuth2伺服器上註冊,獲得client_id
或者是app_secret
。然後:
- 首先使用者在客戶端上點選要用哪個系統的OAuth2來認證,此時客戶端附上回調地址
- 使用者在OAuth2伺服器上選擇是否授權
- 使用者給予授權,OAuth2伺服器重定向到第一步給定的回撥地址,同時附上 Authorization Code
-
回撥地址所在伺服器帶上 Authorization Code和回撥地址,
app_secret
向OAuth2伺服器申請access_token
和refresh_token
-
OAuth2伺服器返回
access_token
和refresh_token
這樣OAuth2伺服器可以知道使用者到底在誰家(哪個客戶端提供商)上授權。而第二種模式就不能這麼做,因為
OAuth2伺服器返回了access_token
和refresh_token
之後,誰都可以拿著這兩個東西去訪問資源。
第一種模式為什麼知道?因為在第三步的時候,OAuth2伺服器只是返回一個Authorization Code,然後客戶端
拿著這個Code和自己的app_secret
去申請access_token
和refresh_token
。這也就意味著,伺服器
可以在這個時候記錄下app_secret
和access_token
的關聯關係。
不過,這只是我的猜想,我也不知道設計者咋想的,是不是這樣的。