Coding 之路,不由分說 .Net,MVC,jQuery

13三月/120

淺談 oAuth 2.0

Google PageRank查詢

前言

現在許多的服務都會提供給開發者 API 來存取服務或取得和操作該服務使用者的資料,像是 Windows LiveGoogleFacebookPlurkTwitter 等等的服務都有提供,但是如果在存取資料的時候都得在第三方網站輸入自己的帳號密碼甚至是讓第三方儲存帳號密碼才可以去使用這些 API 的話,安全性實在太低了,也難保第三方服務會利用帳號密碼,因此就有了 oAuth 這樣的認證,今天就來介紹什麼是 oAuth,而它的驗證流程又是如何?

說明

什麼是 oAuth?

這邊就不多做 oAuth 歷史的介紹,想知道的讀者可以前往 Wiki 查看,我們只需要知道目前有的 oAuth 有 oAuth 1.0aoAuth 2.0 兩種,雖然都是 oAuth 但是他們的驗證流程和步驟卻有很大的不同(對使用者來說卻是相同)。其中 oAuth 1.0a 的驗證流程在開發上相當的複雜且麻煩,可以參閱小朱的【[OAuth Series] OAuth 的各式參數說明】此篇文章和一系列的介紹,而今天主要要介紹的 oAuth 2.0 就是為了改善 oAuth 1.0a 流程以及因應手持裝置越來越多而發展出來的,但是目前還屬於草案階段,可能細節還會有些許差異,但是整個流程應該是有比較大的確認了。

前言中有提到使用者不需要把自己的帳號密碼給予第三方服務也就可以使用服務提供者的 API,除此之外也可以透過服務提供者所提供的介面,隨時去取消授權第三方服務,因此安全性比起直接提供帳號密碼給第三方服務高很多,所以許多服務都會採用這樣方式的驗證,讓使用者可以安心的去使用第三方的服務(但是也可能還是會有使用者總是會按允許授權而導致被濫用)。

oAuth 驗證流程

oAuth 不管是哪一版,對於使用者端驗證流程都是在第三方程式需要存取服務提供者 API 的時候會轉到或是跳出服務提供者的登入畫面(如果你沒登入的話),如果在有登入服務的狀態下會轉到提示要使用者允許授權的畫面,然後告知使用者該第三方服務要存取你的資料或是以你的名義對服務做操作,使用者授權之後我們就可以正常使用第三方服務了。這時候應該不少人發現到了,有個很熟悉的感覺... 

就是臉書很常出現的這一個畫面,這樣一整個驗證的流程就是 oAuth 的驗證流程。而 oAuth 1.0a 和 oAuth 2.0 對於使用者最大的不同就是多了授權的範圍,像是上圖左方會明確的表示這一個服務會取得使用者什麼資料以及希望授權怎樣的權限。

誰提供了 oAuth?

目前有許多服務都提供了 oAuth 來存存取 API,台灣比較常見的服務就如前言所提到的,而它們分別提供的 oAuth 版本為:

其中 Google 是兩種版本都有提供。

oAuth 程式端流程如何運作?

這邊得先提到根據草案說明,驗證的 Client 可以分為:

  • 網站程式(web application)
    就是一般看到的網站,會直接透過 Web Server 來存取使用者授權後所取得的 AccessToken。
  • 使用者代理為基礎的程式(user-agent-based application)
    透過使用者代理程式來取得 AccessToken,它呈現的方式會透過使用者代理程式(EX:瀏覽器)顯示 Token,比如說手機的 App 透過瀏覽器來取得 Token(開發者不需要自行架設網頁伺服器)。
  • 原生程式(native application)
    需要安裝的應用程式,像是桌面程式或是手機 APP 等。

而這幾種 client 在授權的流程會有些許的差異,而每一家服務實作的 oAuth 也略有差異,但是第一種網站程式的方式是比較通用,各家也較無差異,因此後面主要介紹它的程式端運作流程。

申請 ClientID 和 Secret

首先第一步就是到服務提供者端申請 ClientID 和 Secret,這是必要也是重要的流程,而針對要開發系統所申請到的 ClientID,它會是唯一的,也就是這一個 ClientID 就是對應到你所設定的程式,Secret 通常是可以在服務提供者所提供的申請介面中隨時做更換,避免 Secret 被冒用。這邊如果是網站程式的話還得設定 Callback 的網址,這在之後流程會用到。

兩階段授權流程及參數定義

圖片來源:Windows Live SDK oAuth 2.0

雖然上面流程到編號七,但是主要可以分為兩個流程,在第一個流程中我們會取得一組 Code ,而這組 Code 有時效性,得在一定時間內繼續完成第二步驟取得 AccessToken 的授權。

在後面會提到一些參數,這邊預先對它們做定義:

參數名 需求性 說明
response_type 必要 code 或 token 設定成 code
就會有下一階段的驗證。設定成 token 會直接回傳 token,但是不建議用在網站程式。
client_id 必要 之前申請的到 ClientId 根據各服務會有不一樣的名稱,目前看過 ClientId 和 AppId,但是意義上都是規範中的 ClientId
redirect_uri 非必要 申請 ClientId 時候設定的回傳網址 服務提供者回傳 code 或 token 會以參數的方式接在網址後面([redirect_uri]?access_token=[access_token]),方便 Server 端取得。如果 response_type 設定為 token 則是網址後面接上 #access_token=[access_token]([redirect_uri]#access_token=[access_token])
scope 非必要 授權的範圍 這邊會看各家服務提供者要求的格式,主要是設定我們的服務需要使用者授權的功能或資料的範圍。比如說 Facebook 設定成 email 代表我們的服務要求取得使用者的電子信箱。
state 非必要 任意字串 填入任意字串,服務提供者會傳傳一樣的值到 redirect_uri
code 必要 由服務提供者回傳 當 response_type 設定成 code 時候,服務提供者會當做參數回傳到 redirect_uri
client_secret 必要 之前申請的到 Secret 申請服務時候所取得的值,為了安全性可以在每次系統改版時候重新產生一次並且更換。
grant_type 必要 authorization_code 這邊值都是固定,代表要去驗證 code 是否有效。
access_token 由服務提供者回傳 最後會取得的值,用此值來存取 API

取得 Code 的驗證流程

服務提供者開發文件中都會有說明授權的網址,此時只需要按下面格式來 Get 網址,就換將第一階段回傳的 Code 當做參數回傳給 redirect_uri。

exsample.com/authorize?response_type=code&client_id={client_id}&state=123&redirect_uri={redirect_uri}&scope={scope}

如上在 exsample.com/authorize 之後加上參數,順序不拘, 服務提供者就會回傳 Code 到 redirect_uri

redirect_uri?code={code}

而到這一階段的時候服務提供者就會去驗證是否有該 clientid 存在,並且檢查回傳的網址和當初申請時候所設定的是否一樣,一樣的話才會成功回傳 Code,而取得的 Code 在去做驗證取得 AccessToken 的流程。

取得 AccessToken 的驗證流程

在此階段一樣服務提供者會提供一個取得 AccessToken 的網址,而這一此得用 POST 方法來送出參數給服務提供者,因為我們介紹是兩階段流程,因此會把 AccessToken 回傳到之前所提供的 redirect_uri。

exsample.com/token?client_id={client_id}&redirect_uri={redirect_uri}& client_secret={client_secret}&code={&code}&grant_type=authorization_code

這邊參數一樣順序不拘,而服務提供者在此驗證 ClientID 和 Secret 是否有對應,回傳網址是否和設定一樣, Code 是否有效且對應到此組 ClientID,最後就會以參數的形式回傳到 redirect_uri。

redirect_uri?access_token={access_token}

使用 AccessToken 來存取 API

這邊要使用 GET 或是 POST 得看服務提供者這一個 API 的說明,而 AccessToken 有兩種使用方式:

  • 當做參數接在 API 網址後面(APIUrl?access_token={access_token})
  • 在 HTTP header 加上 Authorization 並設定值成為 access_token

這兩種方式並非服務提供者都會實作,但是第一種是一定會有的實作。

結論

本文只是粗略介紹 oAuth 2.0,還有一些步驟(重新取得 Token)或是授權流程,因為比較部屬於開發網站會用到,而且每一家服務提供者實作又略有不同,所以主要介紹的部份是開發網站時候會用到,且各家服務都有實作的部份來做介紹,但是細節上可能還是略有不同,可能還需要多提供一些參數,這在未來會針對每一家服務來實作程式碼來使用 oAuth 2.0 連接 API。

目前 oAuth 2.0 還處於草案階段,因此大部分服務都還不敢貿然轉換到 oAuth 2.0,只有像 Microsoft、Facebook、Google 這種開發人員眾多的公司才有辦法一直根據草案去修改程式(或說是定義流程),根據我看文件的歷程一開始 oAuth 2.0 和 oAuth 1.0a 的差別並不大,一直到第六版草案的時候才變成比較像現在的驗證流程,我想可能還需要一陣子才會變成正式的標準,因此 oAuth 1.0a 還是會有不少服務會在提供,因此開發者可能就得多花點功能開發囉!

如果對於本文有任何疑問或是心得分享都歡迎提出來喔!

參考資料

Windows Live SDK oAuth 2.0

Using OAuth 2.0 to Access Google APIs

Facebook Authentication

oAuth 2.0

The OAuth 2.0 Authorization Protocoldraft-ietf-oauth-v2-25

oAuth Wiki

[OAuth Series] OAuth 的各式參數說明