驗證 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. 按一下 [Create Project] 按鈕,然後輸入所需資訊。
  3. 建立專案之後,請記下「Project Number」(專案編號),稍後您會在後續步驟中使用。
  4. 在「API 與驗證」下方,按一下「API」,然後為新專案啟用「Google Mirror API」
  5. 在「APIs & amp; auth」下方,依序點選 [Credentials] 和 [Create New Client 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。為進行測試,您只需要在從 MyGlass 開啟 Glassware 時,提供一次此 APK 來處理初始下載;之後,您可以覆寫裝置上的 APK,對本機進行疊代和偵錯。請注意,這個 APK 必須符合下列條件:
    • 必須根據 Zip 對齊
    • 操作完成後,您將無法變更套件名稱或私人簽署金鑰 (如果上述任何變更,Android 套件管理員不允許進行升級)。
    • 必須小於 50 MB。
    • 必須使用最新版的 GDK 進行編譯。

實作驗證流程

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

如何實作驗證流程:

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

  2. 使用者在您的驗證頁面輸入自己的憑證。

  3. 您的伺服器會驗證使用者的憑證。如果憑證有效,請對 mirror.accounts.insert 方法發出 Mirror API 呼叫。此方法需要您在建構鏡像服務物件時指定 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();
  }
}

在 Google 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);