GDK Glass 소프트웨어 인증

GDK Glass 소프트웨어에서 웹 서비스를 통해 사용자를 인증해야 하는 경우 GDK는 사용자가 Glass 소프트웨어 설치 시 사용자 인증 정보를 입력할 수 있는 API를 제공합니다.

이 API를 사용하면 Glass 사용자에게 일관된 사용자 환경을 제공하고 자체 커스텀 인증 스키마를 구현하는 오버헤드를 피할 수 있습니다.

Google API 서비스 계정 만들기

인증이 올바르게 설정되면 웹 앱의 백엔드에서 사용자가 서비스를 인증한 후 Mirror API를 사용하여 사용자의 계정 정보를 Glass로 푸시합니다.

이 API에 액세스하려면 Google API 프로젝트를 만든 후 '웹 애플리케이션'이 아니라 '서비스 계정'에 대한 클라이언트 ID를 만듭니다. 서비스 계정을 사용하면 사용자 인증 정보를 Glass에 푸시하기 위해 애플리케이션에 권한을 별도로 부여할 필요가 없으며 OAuth 권한 페이지와 자체 인증 페이지가 다시 표시되지 않습니다.

이 계정을 만드는 방법은 다음과 같습니다.

  1. Google Developers Console로 이동합니다.
  2. Create Project 버튼을 클릭하고 요청된 정보를 입력합니다.
  3. 프로젝트가 생성되면 나중에 필요한 프로젝트 번호를 기록합니다.
  4. API 및 인증에서 API를 클릭하고 새 프로젝트에 Google Mirror API를 사용 설정합니다.
  5. API 및 인증에서 사용자 인증 정보를 클릭한 다음 새 클라이언트 ID 만들기를 클릭합니다. 서비스 계정 라벨이 지정된 체크박스를 선택하여 프로젝트의 새 OAuth 2.0 클라이언트 ID를 만듭니다.
  6. 팝업 창에 비공개 키가 컴퓨터에 다운로드되고 있다는 사실과 이 비공개 키의 비밀번호가 제공됩니다. 이 창을 닫으면 이 비공개 키를 다운로드하거나 비밀번호를 다시 볼 수 없게 됩니다. 분실할 경우 새 계정을 만들어야 합니다.
  7. 나중에 API를 호출하는 데 필요한 서비스 계정의 이메일 주소를 기록해 둡니다.

Glass 소프트웨어에 대한 메타데이터 제공

Glass 소프트웨어 제출 준비가 완료되면 다음 정보를 제공해야 합니다. 이를 통해 Glassware를 구현할 때 올바르게 인증되도록 설정할 수 있습니다.

  • 인증 URL: 사용자가 MyGlass에서 Glass 소프트웨어를 켤 때 리디렉션되는 URL입니다.
  • 계정 유형(Glass 기기에서 Android AccountManager API를 호출할 때 사용할 문자열)
  • AndroidManifest.xml에서 애플리케이션의 패키지 이름
  • 위에서 만든 프로젝트의 숫자 Google API 프로젝트 ID
  • MyGlass에 업로드할 APK 테스트를 위해 Glass가 켜진 상태에서 MyGlass를 켤 때 이 APK를 한 번만 제공하면 됩니다. 그런 다음 기기에서 APK를 덮어써서 로컬에서 반복하고 디버그할 수 있습니다. 이 APK는 다음 기준을 충족해야 합니다.
    • 우편번호에 맞게 정렬해야 합니다.
    • 이후 패키지 이름 또는 비공개 서명 키를 변경하면 안 됩니다 (Android 패키지 관리자는 이러한 변경사항 중 어느 하나라도 하나라도 변경하면 업그레이드를 허용하지 않음).
    • 50MB 미만이어야 합니다.
    • 최신 버전의 GDK를 사용하여 컴파일해야 합니다.

인증 흐름 구현

다음 다이어그램은 GDK Glass 소프트웨어의 기본 인증 흐름을 보여줍니다.

인증 흐름을 구현하는 방법은 다음과 같습니다.

  1. 사용자가 MyGlass에서 Glass 웨어를 사용 설정하면 인증 URL로 리디렉션됩니다. 이러한 요청에는 나중에 사용해야 하는 userToken라는 쿼리 매개변수가 포함됩니다.

  2. 사용자가 인증 페이지에 사용자 인증 정보를 입력합니다.

  3. 서버가 사용자의 사용자 인증 정보를 확인합니다. 사용자 인증 정보가 유효하면 mirror.accounts.insert에 대한 미러링 API 호출을 수행합니다. 이 메서드를 사용하려면 미러 서비스 객체를 빌드할 때 https://www.googleapis.com/auth/glass.thirdpartyauth 범위를 지정해야 합니다. 원시 HTTP 또는 자바를 사용하여 이 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 요청을 수신하면 미러링 API가 계정을 사용자의 Glass 기기에 푸시합니다. 그러면 이제 AccountManager 클래스를 사용하여 계정에 액세스할 수 있습니다.

사용자 친화적인 인증 흐름을 구현하려면 다음 가이드라인을 따르세요.

  • 휴대기기에 맞게 흐름을 최적화합니다.
  • 흐름에 범위가 있고 사용자가 취소한다면 잘 설계된 오류 메시지가 표시됩니다.
  • 요청한 범위가 Glassware에서 실제로 사용되고 있는지 확인합니다.
  • 사용자 계정을 연결할 수 있으면 연결해야 합니다.
  • 가능한 경우 사용자 데이터를 클라우드에 백업해야 합니다.

Glassware 인증의 일관성을 유지하려면 다음 인증 흐름 중 하나를 사용하세요.

계정 없이 미러링 또는 하이브리드

  1. MyGlass에서 사용 설정하면 팝업으로 인증 URL이 열립니다.
  2. 이렇게 하면 사용자가 수락할 범위가 바로 전송됩니다.
  3. 사용자가 범위를 수락하거나 취소한 후 팝업을 닫습니다.

계정으로 미러링

  1. MyGlass에서 사용 설정하면 팝업으로 인증 URL이 열립니다.
    • 사용자가 이미 서비스에 로그인한 경우 사용자를 직접 범위로 보냅니다.
    • 사용자가 로그인 상태가 아니라면 로그인 필드를 표시하고 사용자가 서비스에 로그인하도록 허용하여 범위를 전송합니다.
    • 사용자에게 계정이 없는 경우 계정을 만들 수 있는 링크를 제공하세요. 사용자는 설치 흐름 과정에서 계정을 만들 수 있어야 합니다.
  2. 사용자가 범위를 수락합니다.
    • Glass 소프트웨어에 구성 가능한 설정이 있는 경우 합당한 기본값을 선택하여 사용자를 설정 페이지로 안내합니다.
    • Glass 소프트웨어에 구성 가능한 설정이 없으면 사용자를 확인 페이지로 보냅니다. 추가 구성이 필요하지 않으면 팝업을 닫습니다.

계정과 하이브리드

  1. MyGlass에서 사용 설정하면 팝업으로 인증 URL이 열립니다.
    • 사용자가 이미 서비스에 로그인한 경우 사용자를 직접 범위로 보냅니다.
    • 사용자가 로그인하지 않은 경우 로그인 필드를 표시하고 로그인하도록 허용한 후 범위로 보냅니다.
    • 사용자에게 계정이 없는 경우 계정을 만들 수 있는 링크를 제공하세요.
  2. 사용자가 범위를 수락합니다.
  3. GDK 계정을 삽입하기 위한 요청을 Mirror API로 보냅니다.
    • 적절한 기본값이 선택된 설정 페이지로 사용자를 보냅니다.
    • 사용자에게 확인 페이지를 보냅니다. 추가 구성이 필요하지 않으면 팝업을 닫습니다.

계정 및 맞춤 범위로 미러링 또는 하이브리드

  1. MyGlass에서 사용 설정하면 팝업으로 인증 URL이 열립니다.
    • 사용자가 이미 서비스에 로그인한 경우 내부 범위로 사용자를 보냅니다.
    • 사용자가 로그인 상태가 아니라면 로그인 필드를 표시하고 로그인하도록 허용한 후 내부 범위로 보냅니다.
    • 사용자에게 계정이 없는 경우 계정을 만들 수 있는 링크를 제공하세요.
  2. 사용자가 맞춤 범위를 수락하면 Google의 범위로 사용자를 보냅니다.
  3. GDK 계정을 삽입하기 위한 요청을 Mirror API로 보냅니다.
    • 적절한 기본값이 선택된 설정 페이지로 사용자를 보냅니다.
    • 사용자에게 확인 페이지를 보냅니다. 추가 구성이 필요하지 않으면 팝업을 닫습니다.

Android/iPhone 앱으로 미러/하이브리드 사용

  1. MyGlass에서 사용 설정하면 팝업으로 인증 URL이 열립니다.
  2. 이렇게 하면 사용자가 수락할 범위가 바로 전송됩니다.
  3. 사용자가 범위를 수락한 후:
    • 사용자가 호환 앱을 가지고 있고 인증된 경우 팝업 창을 닫습니다.
    • 그렇지 않은 경우 사용자를 Google Play 스토어 또는 iOS 스토어에서 앱을 다운로드하도록 안내하는 전면 광고로 보냅니다.
  4. 앱을 설치하고 인증한 후 팝업 창을 닫습니다.

GDK 및 계정 없음

MyGlass에서 Glassware를 사용 설정하기만 하면 이 절차를 진행할 수 있습니다.

계정이 있는 GDK

  1. MyGlass에서 사용 설정하면 팝업으로 인증 URL이 열립니다.
    • 사용자가 이미 서비스에 로그인한 경우 사용자를 확인 화면으로 보냅니다.
    • 사용자가 로그인하지 않은 경우 로그인 필드를 표시하고 로그인하도록 허용한 다음 확인 화면으로 보냅니다.
    • 사용자에게 계정이 없는 경우 계정을 만들 수 있는 링크를 제공하세요.
  2. 사용자가 범위를 수락합니다.
  3. GDK 계정을 삽입하기 위한 요청을 Mirror API로 보냅니다.
  4. 확인 화면을 표시하고 잠시 기다린 후 화면을 닫습니다.

계정 생성 예시

가능한 경우 Mirror API의 클라이언트 라이브러리를 사용하세요. 이렇게 하면 mirror.accounts.insert를 호출하여 계정을 더 쉽게 만들 수 있습니다.

원시 HTTP 예시

아래는 요청의 URL과 예상 JSON 본문의 예만 보여줍니다. 서비스 계정을 대신하여 원시 HTTP 요청을 수행하는 것이 훨씬 더 복잡하므로 (자세한 내용은 서버 간 애플리케이션에 OAuth 2.0 사용을 참조) 가능한 경우 Google API 클라이언트 라이브러리 중 하나를 사용하는 것이 좋습니다.

요청 방법 및 URL:

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..." }
    ]
}

요청 URL의 {userToken}인증 흐름 구현의 1단계에서 인증 URL에 전달된 토큰으로 바꿉니다.

자바 예시

이 예에서는 자바 클라이언트 라이브러리를 사용하여 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);