2015年4月7日 星期二

在已安裝應用程式中取得 Google OAuth 2.0 授權

在前篇文章中簡單介紹如何在網站應用程式中取得 Google OAuth 2.0 授權, 本篇文章要說明的是如何在「已安裝應用程式中取得 Google OAuth 2.0 授權」。 這二者的授權流程是相似的,比較相異的有以下三點:

  • 申請的憑證類型不同,必須是「已安裝應用程式」類型。
  • 憑證中的 Client ID, Client Secret 是嵌在程式碼之中的。
  • OAuth Server 回傳的 Authorization Code 是直接放在應用程式的 Title bar 或者 http://localhost 網址的參數中。

另外要注意的是,若要使用「已安裝應用程式」類型,你的系統中必須含有預設的瀏灠器,並且該應用程式有權限存取該瀏灠器。

申請「已安裝應用程式」憑證

存取 Google API 必須先至 Google Developers Console 申請應用程式憑證。

取得 Access Token

若是要在已安裝的應用程式中取得存取憑證,做法也可以參考上一篇<在網站應用程式中取得 Google OAuth 2.0 授權>的作業流程,以取得存取憑證。 只不過這麼一來,就必須透過 Browser 元件自行處理回應的訊息。 另外較方便的方式就是下載 Google 提供的「用戶端類別庫」,可以在已安裝的應用程式中很方便的取得 OAuth 2.0 的存取憑證。

類別庫下載

  • Google APIs OAuth Client Library
  • Google APIs Client Library
  • Google APIs Core Library

UserCredential 和 AuthorizationCodeFlow

Google API OAuth 類別庫中,它透過 GoogleWebAuthorizationBroker.AuthorizeAsync 靜態方法來建立 UserCredential 類別,以便向 Google 服務取得 access token 。 UserCredential 是類別庫中,用來記錄 access token 的物件,並且可以在憑證過期時自動 refresh token 。 而 GoogleWebAuthorizationBroker 則是一個 Code Flow 類型的物件,也就是它在執行時其實是包含多個步驟,它會依實際狀況,自動執行必要的步驟。 例如,如果程式找不到本機端儲存的 access token ,則會開啟使用者 consent 頁面,等待使用者授權程式存取他的資料。 如果使用者按下了同意按鈕,應用程式將自動取得 access token ,並將值保存下來,留待下一次執行時使用。 如果該 access token 已過有效期限已,就會自動送出 refresh token 以便更新 access token 。 這一連串的步驟 Google OAuth2 API 都已經包裝起來,我們只要照以下程式碼的設定即可。

下面這個例子,Broker 會將憑證資料儲存在底下這個檔案中: "%AppData%\Roaming\Google.Apis.Auth\Google.Apis.Auth.OAuth2.Responses.TokenResponse-user"。

public UserCredential GetCredential()
{
    UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
    new ClientSecrets
    {
        ClientId = "XXXX.apps.googleusercontent.com",
        ClientSecret = "et-OimYoEOwuhQgrFaoNInwv",
    },
    new[] { "https://www.googleapis.com/auth/blogger" },
    "user",
    CancellationToken.None
    ).Result;

    return credential;
}

底下簡單說明建立 UserCredential 物件時,會使用到的參數值:

ClientSecrets

在使用 Blogger API 時,你必須先替應用程式申請一組憑證(申請方法請看<Google OAuth 2.0>),再使用核發憑證中的 ClientID 和 Secret 建立 ClientSecrets 。 當 request 無法獲得有效的 access token 時,則必須使用這組資訊,重新建立 access token 。 另外,你也可以將當初向 Google 申請的憑證下載回來,然後在建立 ClientSecrets 時,直接使用開啟檔案的方法,匯入憑證。例如:

public UserCredential GetCredential()
{
    UserCredential credential;
    using (var stream = new FileStream(@"d:\mydll\client_secrets.json", FileMode.Open, FileAccess.Read))
    {
        credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
            GoogleClientSecrets.Load(stream).Secrets,
            new[] { "https://www.googleapis.com/auth/blogger" },
            "userxxx",
            CancellationToken.None,
            new FileDataStore("Auth.Blogger")).Result;
    }

    return credential;
}

若要下載已申請的憑證,你可以到 Google Console 網站中找到以下連結。

Scope

AuthorizeAsync 這個方法中的 scope 指的是授權內容的範圍。 在 Google 的 OAuth 實作中,定義了很多 scope ,例如:Blogger、Picasa、Google Map 等等, 當程式開發時,就利用這個參數來告訴 Google 開啟相關的授權資訊讓使用者 consent 。

例如,若 scope = BloggerService.Scope.Blogger ,授權頁的內容如下:

例如,若 scope = BloggerService.Scope.BloggerReadonly ,則授權頁的內容如下:

user_account

第3個參數,只是用來識別不同的使用者,如果這個用戶端程式只有一個人使用,那麼使用任何一個固定的字串也是可以的。

CancellationToken

這個參數是用來設定授權作業時是否可以被中斷。

FileDataStore

第5個參數是用來指定存放 access token 的目錄,你可以指定一個 File Store 或者 Data Store 物件當做參數值。 這個參數非必要欄位,如果沒有指定,則會自動儲存在預設的位置。 預設的位置會使用 "Google.Apis.Auth" 當做參數值,然後將這個目錄建立在 Environment.SpecialFolder.ApplicationData 之中。 所以上面例子中,Broker 會由 d:\mydll\client_secrets.json 讀取用戶端憑證資料,並將使用者授權後的存取憑證資料儲存在底下這個檔案中: "%AppData%\Roaming\Auth.Blogger\Google.Apis.Auth.OAuth2.Responses.TokenResponse-userxxx"。

更新與撤銷存取憑證

當應用程式取得使用者的 OAuth 授權後,若需要更新或撤銷憑證,也可以直接叫用 UserCredential 的方法即可。

/// 更新授權憑證
    credential.RefreshTokenAsync(CancellationToken.None)

    /// 撤銷授權憑證
    credential.RevokeTokenAsync(CancellationToken.None)

沒有留言:

張貼留言