GDK Glassware 驗證

如果您的 GDK Glassware 需要根據網路服務驗證使用者,GDK 會提供 API,讓使用者在安裝 Glassware 時輸入憑證。

只要使用這個 API,您就能為 Glass 使用者提供一致的使用者體驗,並避免自己實作自訂驗證機制的負擔。

建立 Google API 服務帳戶

驗證設定正確後,網頁應用程式的後端會在使用者驗證服務後,使用 Mirror API 將使用者帳戶資訊推送至 Glass。

如要存取這個 API,請建立 Google API 專案,然後為「服務帳戶」建立用戶端 ID (不是「網路應用程式」)。使用服務帳戶後,使用者不必另外授予應用程式權限,即可將憑證推送至 Glass,也不會再次看到 OAuth 權限頁面和您自己的驗證頁面。

如要建立這個帳戶,請按照下列步驟操作:

  1. 前往 Google Developers Console
  2. 按一下「建立專案」按鈕,然後輸入要求的資訊。
  3. 建立專案後,請記下專案編號,後續步驟將會用到。
  4. 在「API 與驗證」下方,按一下「API」,然後為新專案啟用 Google Mirror API
  5. 在「API 與驗證」下方,依序點選「憑證」>「建立新的用戶端 ID」。勾選標示「Service account」(服務帳戶) 的方塊,為專案建立新的 OAuth 2.0 用戶端 ID。
  6. 彈出式視窗會通知您私密金鑰正在下載至電腦,並提供該私密金鑰的密碼。關閉這個視窗後,您就無法再下載這組私密金鑰或查看密碼。如果資料遺失,您就必須重新建立。
  7. 請記下服務帳戶的電子郵件地址,因為您稍後需要用來呼叫 API。

提供 Glassware 的相關中繼資料

準備提交 Glassware 時,請提供下列資訊。這樣一來,我們就能在您實作時,設定 Glassware 以便正確驗證。

  • 驗證網址:使用者在 MyGlass 中開啟 Glassware 時,系統會將他們重新導向至這個網址。
  • 帳戶類型 (在 Glass 裝置上呼叫 Android AccountManager API 時使用的字串)
  • AndroidManifest.xml 中的應用程式套件名稱
  • 您在上述步驟中建立的專案的 Google API 專案 ID 數字
  • 要上傳到 MyGlass 的 APK。進行測試時,您只需提供這個 APK 一次,即可在 Glassware 透過 MyGlass 開啟時處理初始下載作業;之後,您可以在本機重複執行並偵錯,方法是覆寫裝置上的 APK。請注意,此 APK 必須符合下列條件:
    • 必須是 ZIP 對齊。
    • 此後,請勿再變更套件名稱或私人簽署金鑰 (如果變更這兩項,Android 套件管理員將不允許升級)。
    • 檔案大小不得超過 50 MB。
    • 必須使用最新版 GDK 進行編譯。

實作驗證流程

下圖顯示 GDK Glassware 的基本驗證流程:

如要實作驗證流程,請按照下列步驟操作:

  1. 當使用者在 MyGlass 中開啟 Glassware 時,系統會將他們重新導向至驗證網址。這些要求包含名為 userToken 的查詢參數,您需要稍後使用該參數。

  2. 使用者會在驗證頁面輸入憑證。

  3. 您的伺服器會驗證使用者的憑證。如果憑證有效,請對 mirror.accounts.insert 方法發出 Mirror API 呼叫。使用這個方法時,您必須在建構 Mirror 服務物件時指定 https://www.googleapis.com/auth/glass.thirdpartyauth 範圍。帳戶建立範例中列出了使用原始 HTTP 或 Java 呼叫此 API 的範例。

    您在下方提供的參數和要求主體,與您直接在裝置上建立帳戶時,提供給 Android AccountManager 的資訊相同。

    屬性名稱 說明
    features[] 字串清單 功能清單 (請參閱 AccountManager.hasFeatures)。
    password 字串 帳戶密碼 (請參閱 AccountManager.getPassword)。建議您不要在這個欄位「儲存使用者的實際密碼」,而是用來儲存長期私人資料,例如更新權杖。
    userData[] 物件清單 與帳戶相關聯的一或多組使用者資料 (請參閱 AccountManager.getUserData)。
    userData[].key 字串 與特定使用者資料鍵/值組合相關聯的鍵。
    userData[].value 字串 與特定使用者資料鍵/值組合相關聯的值。
    authTokens[] 物件清單 與帳戶相關聯的一或多個驗證權杖 (請參閱 AccountManager.getAuthToken)。
    authTokens[].type 字串 驗證權杖的類型。
    authTokens[].authToken 字串 驗證權杖。
  4. 收到 mirror.account.insert 要求後,Mirror API 會將帳戶推送至使用者的 Glass 裝置,您現在可以使用 AccountManager 類別存取該帳戶。

請按照下列規範實作使用者友善的驗證流程:

  • 針對行動裝置最佳化流程。
  • 如果您的流程具有範圍,且使用者取消,請提供精心設計的錯誤訊息。
  • 請確認您要求的範圍確實在 Glassware 中使用。
  • 如果可以連結使用者帳戶,請務必連結。
  • 並盡可能將使用者資料備份到雲端。

如要維持 Glassware 驗證的一致性,請使用下列其中一種驗證流程:

在沒有帳戶的情況下鏡像或混合

  1. 在 MyGlass 中切換為開啟後,系統會在彈出式視窗中開啟驗證網址。
  2. 這會直接將使用者導向接受的範圍。
  3. 在使用者接受或取消範圍後,請關閉彈出式視窗。

使用帳戶鏡像

  1. 在 MyGlass 中切換為開啟後,系統會在彈出式視窗中開啟驗證網址。
    • 如果使用者已登入您的服務,請直接將使用者傳送至範圍。
    • 如果使用者未登入,請顯示登入欄位,允許使用者登入服務,然後傳送至範圍。
    • 如果使用者沒有帳戶,請提供建立帳戶的連結。使用者必須能夠在安裝流程中建立帳戶。
  2. 使用者接受範圍。
    • 如果您的 Glassware 可調整設定,請將使用者導向至設定頁面,且選取合理的預設值。
    • 如果 Glassware 沒有可設定的設定,請將使用者帶往確認頁面。如果不需要額外設定,請關閉彈出式視窗。

與帳戶混合

  1. 在 MyGlass 中切換為開啟後,系統會在彈出式視窗中開啟驗證網址。
    • 如果使用者已經登入您的服務,請直接將使用者傳送至範圍。
    • 如果使用者未登入,顯示登入欄位,允許使用者登入,然後傳送至範圍。
    • 如果使用者沒有帳戶,請提供建立帳戶的連結。
  2. 使用者接受範圍。
  3. 傳送要求至 Mirror API,插入 GDK 帳戶。
    • 將使用者導向已選取合理預設值的設定頁面。
    • 傳送確認頁面給使用者。如果不需要額外設定,請關閉彈出式視窗。

使用帳戶和自訂範圍建立鏡像或混合模式

  1. 在 MyGlass 中切換為開啟後,系統會在彈出式視窗中開啟驗證網址。
    • 如果使用者已登入您的服務,請將使用者傳送至您的內部範圍
    • 如果使用者未登入,顯示登入欄位,允許使用者登入,然後傳送至內部範圍
    • 如果使用者沒有帳戶,請提供建立帳戶的連結。
  2. 使用者接受您的自訂範圍後,請將使用者傳送到 Google 的範圍。
  3. 傳送要求至 Mirror API,插入 GDK 帳戶。
    • 將使用者導向已選取合理預設值的設定頁面。
    • 傳送確認頁面給使用者。如果不需要額外設定,請關閉彈出式視窗。

透過 Android/iPhone 應用程式享受鏡像或混合地圖

  1. 在 MyGlass 中切換為開啟後,系統會在彈出式視窗中開啟驗證網址。
  2. 這會直接將使用者傳送至同意範圍。
  3. 使用者接受權限範圍後:
    • 如果使用者已安裝隨附應用程式並完成驗證,請關閉彈出式視窗。
    • 如果沒有,請將使用者導向插頁式廣告,引導他們前往 Google Play 商店或 iOS 商店下載應用程式
  4. 安裝應用程式並進行驗證後,請關閉彈出式視窗

GDK 和沒有帳戶

這個流程只需要在 MyGlass 中切換 Glassware 開關。

GDK (登入帳戶)

  1. 在 MyGlass 中切換為開啟後,系統會在彈出式視窗中開啟驗證網址。
    • 如果使用者已經登入服務,請將他們導向至確認畫面。
    • 如果使用者未登入,請顯示登入欄位,讓他們登入,然後將他們傳送至確認畫面。
    • 如果使用者沒有帳戶,請提供建立帳戶的連結。
  2. 使用者接受範圍。
  3. 傳送要求至 Mirror API,以插入 GDK 帳戶。
  4. 顯示確認畫面,並在顯示確認後關閉畫面。

建立帳戶的範例

盡可能使用 Mirror API 的用戶端程式庫。這樣一來,您就能更輕鬆地呼叫 mirror.accounts.insert 建立帳戶。

原始 HTTP 範例

以下範例只會顯示要求的網址,以及預期的 JSON 主體範例。代表服務帳戶發出原始 HTTP 要求的程序相當複雜 (詳情請參閱「針對伺服器對伺服器應用程式使用 OAuth 2.0」),因此建議您盡可能使用 Google API 用戶端程式庫,以便簡化這項作業。

要求方法和網址:

POST https://www.googleapis.com/mirror/v1/accounts/{userToken}/com.example.myapp/username%40email.com

要求主體:

{
    "features": ["a", "b", "c"],
    "userData": [
        { "key": "realName", "value": "Rusty Shackleford" },
        { "key": "foo", "value": "bar" }
    ],
    "authTokens": [
        { "type": "your_token_type", "authToken": "zT419Ma3X2pBr0L..." }
    ]
}

將要求網址中的 {userToken} 替換為在實作驗證流程步驟 1 中傳送至驗證網址的權杖。

Java 範例

本範例說明如何使用 Java 用戶端程式庫呼叫 mirror.accounts.insert

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.mirror.Mirror;
import com.google.api.services.mirror.model.Account;
import com.google.api.services.mirror.model.AuthToken;
import com.google.common.collect.Lists;
...

/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL =
    "<some-id>@developer.gserviceaccount.com";

/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH =
    "/path/to/<public_key_fingerprint>-privatekey.p12";

/** The account type, usually based on your company or app's package. */
private static final String ACCOUNT_TYPE = "com.example.myapp";

/** The Mirror API scopes needed to access the API. */
private static final String MIRROR_ACCOUNT_SCOPES =
    "https://www.googleapis.com/auth/glass.thirdpartyauth";

/**
 * Build and returns a Mirror service object authorized with the service accounts.
 *
 * @return Mirror service object that is ready to make requests.
 */
public static Mirror getMirrorService() throws GeneralSecurityException,
    IOException, URISyntaxException {
  HttpTransport httpTransport = new NetHttpTransport();
  JacksonFactory jsonFactory = new JacksonFactory();
  GoogleCredential credential = new GoogleCredential.Builder()
      .setTransport(httpTransport)
      .setJsonFactory(jsonFactory)
      .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
      .setServiceAccountScopes(MIRROR_ACCOUNT_SCOPES)
      .setServiceAccountPrivateKeyFromP12File(
          new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
      .build();
  Mirror service = new Mirror.Builder(httpTransport, jsonFactory, null)
      .setHttpRequestInitializer(credential).build();
  return service;
}

/**
 * Creates an account and causes it to be synced up with the user's Glass.
 * This example only supports one auth token; modify it if you need to add
 * more than one, or to add features, user data, or the password field.
 *
 * @param mirror the service returned by getMirrorService()
 * @param userToken the user token sent to your auth callback URL
 * @param accountName the account name for this particular user
 * @param authTokenType the type of the auth token (chosen by you)
 * @param authToken the auth token
 */
public static void createAccount(Mirror mirror, String userToken, String accountName,
    String authTokenType, String authToken) {
  try {
    Account account = new Account();
    List<AuthToken> authTokens = Lists.newArrayList(
        new AuthToken().setType(authTokenType).setAuthToken(authToken));
    account.setAuthTokens(authTokens);
    mirror.accounts().insert(
        userToken, ACCOUNT_TYPE, accountName, account).execute();
  } catch (IOException e) {
    e.printStackTrace();
  }
}

在 Glass 上擷取帳戶

在 Glass 上擷取及使用 Account 物件,與使用標準 Android AccountManager 類似。

  1. AndroidManifest.xml 檔案中宣告下列資訊清單權限:

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    
  2. 擷取 Glassware 的帳戶:

    AccountManager accountManager = AccountManager.get(mContext);
    // Use your Glassware's account type.
    Account[] accounts = accountManager.getAccountsByType("com.example");
    
    // Pick an account from the list of returned accounts.
    
  3. Account 擷取驗證權杖:

    // Your auth token type.
    final String AUTH_TOKEN_TYPE = "oauth2:https://www.example.com/auth/login";
    
    accountManager.getAuthToken(account, AUTH_TOKEN_TYPE, null, activity, new AccountManagerCallback<Bundle>() {
        public void run(AccountManagerFuture<Bundle> future) {
            try {
                String token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
                // Use the token.
            } catch (Exception e) {
                // Handle exception.
            }
        }
    }, null);