Wear での認証

スタンドアロンのスマートウォッチでは、コンパニオン アプリがインストールされていなくても、Wear OS アプリをスマートウォッチ上で完全に実行できます。この新機能は、Wear OS のスタンドアロン アプリがクラウドからデータにアクセスする必要がある場合、単独で認証を管理する必要があることも示しています。Wear OS は、スタンドアロンの Wear アプリがユーザーの認証情報を取得できる認証方法をいくつかサポートしています。

現在、Wear OS は以下の認証方法をサポートしています。

以下のセクションで、上記の認証方法を Wear アプリに組み込む方法について説明します。

Google ログイン

Google ログインでは、既存の Google アカウントを使用してログインできます。特に、Google ログインをハンドヘルド アプリにすでに実装している場合は、ユーザー エクスペリエンスを最大限に高め、サポートを容易に提供することができます。

Google ログインはおすすめのソリューションです。iOS でも問題なく機能します。次のセクションで、Google ログインの基本的な統合方法について説明します。

前提条件

Google ログインを Wear アプリに組み込むには、Google API コンソール プロジェクトと Android Studio プロジェクトを事前に設定しておく必要があります。詳しくは、Google ログインの統合ガイドをご覧ください。

注: バックエンド サーバーと通信するアプリやサイトで Google ログインを使用する場合は、バックエンド サーバー用に OAuth 2.0 ウェブ アプリケーションのクライアント ID を作成します。このクライアント ID は、アプリのクライアント ID とは異なります。詳しくは、サーバー側からのアクセスを有効化するをご覧ください。

重要: アプリがバックエンド サーバーと通信する場合、HTTPS を使用してユーザーの ID トークンを送信することにより、サーバーでログイン中のユーザーを安全に特定します。バックエンド サーバーでユーザーを認証する方法については、バックエンド サーバーで認証するをご覧ください。

Google ログインをアプリに組み込む

Google ログインを Wear アプリに組み込む手順は次のとおりです。

  1. Google ログインを設定します
  2. Google ログインボタンを追加します
  3. ログインボタンがクリックされたら、ログインフローを開始します

Google ログインを設定し、GoogleApiClient オブジェクトを作成する

ログイン アクティビティの onCreate メソッドで、アプリで必要なユーザーデータをリクエストするように Google ログインを設定します。さらに、Google ログイン API と指定したオプションへのアクセス権を持つ GoogleApiClient オブジェクトを作成します。

Kotlin

    // Configure sign-in to request the user's ID, email address, and basic
    // profile. The ID and basic profile are included in DEFAULT_SIGN_IN.
    // If you need to request additional scopes to access Google APIs, specify them with
    // requestScopes().
    googleApiClient = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build()
            .let { signInConfigBuilder ->
                // Build a GoogleApiClient with access to the Google Sign-In API and the
                // options specified in the sign-in configuration.
                GoogleApiClient.Builder(this)
                        .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                        .addApi(Auth.GOOGLE_SIGN_IN_API, signInConfigBuilder)
                        .build()
            }
    

Java

    // Configure sign-in to request the user's ID, email address, and basic
    // profile. The ID and basic profile are included in DEFAULT_SIGN_IN.
    // If you need to request additional scopes to access Google APIs, specify them with
    // requestScopes().
    GoogleSignInOptions.Builder signInConfigBuilder = new GoogleSignInOptions
            .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();

    // Build a GoogleApiClient with access to the Google Sign-In API and the
    // options specified in the sign-in configuration.
    googleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, signInConfigBuilder)
            .build();
    

Google ログインボタンをアプリに追加する

  1. SignInButton をアプリのレイアウトに追加します。
  2.      <com.google.android.gms.common.SignInButton
         android:id="@+id/sign_in_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
        
  3. アプリの onCreate() メソッドでボタンの OnClickListener を登録し、ユーザーがボタンをクリックしたときにログインできるようにします。
  4. Kotlin

        findViewById<View>(R.id.sign_in_button).setOnClickListener(this)
        

    Java

        findViewById(R.id.sign_in_button).setOnClickListener(this);
        

ログイン インテントを作成し、ログインフローを開始する

ログインボタンがクリックされたら、onCLick() メソッドでログインボタンのタップを処理します(getSignInIntent メソッドでログイン インテントを作成し、startActivityForResult メソッドでインテントを開始します)。

Kotlin

    Auth.GoogleSignInApi.getSignInIntent(googleApiClient).also { signInIntent ->
        startActivityForResult(signInIntent, RC_SIGN_IN)
    }
    

Java

    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
    

ユーザーは、ログインに使用する Google アカウントを選択するよう求められます。また、profile、email、openid 以外のスコープをリクエストした場合、ユーザーはそれらのリソースへのアクセスを許可するよう求められます。

最後に、アクティビティの onActivityResult メソッドで、getSignInResultFromIntent を使用してログイン結果を取得します。ログイン結果を取得した後、isSuccess メソッドでログインが成功したかどうかを確認できます。ログインが成功した場合は、getSignInAccount メソッドを呼び出して、ログイン中のユーザーに関する情報(ユーザー名など)を含む GoogleSignInAccount オブジェクトを取得できます。

Kotlin

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        super.onActivityResult(requestCode, resultCode, data)

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...)
        if (requestCode == RC_SIGN_IN) {
            Auth.GoogleSignInApi.getSignInResultFromIntent(data)?.apply {
                if (isSuccess) {
                    // Get account information
                    fullName = signInAccount?.displayName
                    mGivenName = signInAccount?.givenName
                    mFamilyName = signInAccount?.familyName
                    mEmail = signInAccount?.email
                }
            }
        }
    }
    

Java

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...)
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (signInResult.isSuccess()) {
                GoogleSignInAccount acct = signInResult.getSignInAccount();

                // Get account information
                fullName = acct.getDisplayName();
                givenName = acct.getGivenName();
                familyName = acct.getFamilyName();
                email = acct.getEmail();
            }
        }
    }
    

Google ログインを実装したアプリの例については、サンプルアプリをご覧ください。

OAuth 2.0 のサポート

Wear では、サードパーティ製アプリがウェブサービスを使用してユーザーを認証できるよう、OAuth 2.0 をサポートしています。Wear デバイスでは画面の表示領域が限られているため、スタンドアロンのスマートウォッチ アプリは Wear OS の OAuth サポートを通じて、スマートフォンを介して OAuth 認証フローを実行します。スタンドアロン アプリは、リクエストおよびレスポンス URL モデルを使用してユーザーを認証し、OAuth トークンを受け取ってサービスにアクセスします。

注: Wear 2.0 アプリに付属のスマートフォン アプリがある場合は、Wear アプリとそのスマートフォン アプリで同じパッケージ名を使用します。

前提条件

認証を開始する前に、バックエンド サーバー用の OAuth 2.0 ウェブ アプリケーションのクライアント ID を作成します。このクライアント ID は、アプリのクライアント ID とは異なります。Google API コンソールで、サーバーのクライアント ID の検索や作成を行うことができます。

フロー

  1. ユーザーが、認証を必要とするサードパーティ製アプリで操作を行います。
  2. サードパーティ製アプリが Wear サービス API の sendAuthorizationRequest() を使用して Wear OS コンパニオン アプリにリクエストを送信し、認証 URL でウェブビューを開きます。
  3. URL のウェブサイトがユーザーを認証します(ユーザーにユーザー名とパスワードの入力を求めます。2 要素認証などが実行されることもあります)。
  4. 認証が成功または失敗した後、リクエストで認証コードを使用して指定した(アプリのバックエンド サーバーへの)コールバック URL がサイトから呼び出されます。
  5. バックエンド サーバーが認証コードを、OAuth サーバーから取得したアクセス トークンおよび更新トークンと交換します。
  6. バックエンド サーバーがレスポンスをリダイレクトし、Wear OS コンパニオン アプリを介してサードパーティ製のスマートウォッチ アプリにアクセスします。
  7. Wear OS コンパニオン アプリがそのリダイレクトを受信し、ウェアラブル サポート API の onAuthorizationResponse() を使用して、サーバーからのレスポンス全体をスマートウォッチ アプリに返します。
  8. サードパーティ製アプリが認証サイトからのレスポンスを解析し、レスポンスから認証トークンを抽出します。
  9. サードパーティ製アプリはその後のリクエストで、この認証トークンを認証情報として使用します。

上記の認証フローを実装するには、以下を行う必要があります。

  1. クライアント ID とクライアント シークレットを作成する
  2. 認証リクエストを実行する
  3. 認証レスポンスを処理する

クライアント ID とクライアント シークレットを作成する

OAuth 2.0 を使用する Wear アプリでは、クライアント IDクライアント シークレットを作成し、OAuth プロバイダに対してアプリを指定する必要があります。これらの認証情報を取得するには、API コンソール プロジェクトを設定する必要があります。

認証リクエストを実行する

OAuth プロバイダに対して認証リクエストを実行するには、まず、onCreate() メソッドで OAuth 2.0 リクエストを作成する際に使用するクライアント オブジェクトを作成します。

注: スマートウォッチが常に画面表示モードになったときにアプリが停止しないようにするには、アプリの OAuth アクティビティで(setAmbientEnabled を使用して)常時オンを有効にします。常に画面表示モードに関するおすすめの方法については、アプリを表示したままにするをご覧ください。

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        oAuthClient = OAuthClient.create(this)
        …
    }
    

Java

    @Override
    public void onCreate(Bundle b) {
        super.onCreate(b);
        oAuthClient = OAuthClient.create(this);
        …
    }
    

次に、OAuth エンドポイントを含む URL を作成し、トークン、サーバーの OAuth クライアント ID、(バックエンド サーバーへの)リダイレクト URL、レスポンス タイプを取得します。

リクエストされた URL は次のようになります。

    https://accounts.google.com/o/oauth2/v2/auth?response_type=code
    &client_id="your_client_id_here";
    &scope=https://www.googleapis.com/auth/plus.login
    &redirect_uri=https://myserver.com
    

認証リクエストを作成すると、Wear サービス API の sendAuthorizationRequest() を使用してコンパニオン アプリにリクエストを送信できるようになります。

このリクエストによってコンパニオンに対する RPC がトリガーされ、ユーザーのスマートフォンに認証 UI が表示されます。OAuth 2.0 プロバイダはユーザーを認証し、リクエストされたスコープにアプリがアクセスすることに関してユーザーの同意を得ます。レスポンスは、指定したリダイレクト URL を使用してバックエンド サーバーに返されます。

認証レスポンスを処理する

認証が成功または失敗した後、OAuth 2.0 サーバーは、リクエストで指定された URL にリダイレクトします。ユーザーがアクセス リクエストを承認すると、レスポンスに認証コードが格納されます。ユーザーがリクエストを承認しないと、レスポンスにエラー メッセージが格納されます。

レスポンスは次のようなクエリ文字列形式になります。

    https://myserver.com/oauthtokens?code=xyz
    

バックエンド サーバーは認証コードを受け取った後、アクセス トークンと交換することができます。さらに、バックエンド サーバーは、レシーバとして登録された、https://wear.googleapis.com/3p_auth/app.html?full_suffix_from_redirect=com.your.package.name?accessToken=abc&refreshToken=xyz の形式の URL の Wear OS スマートフォン アプリに HTTP 302 リダイレクトを返します。
スマートフォン アプリはレスポンス URL を確認し、onAuthorizationResponse API を使用してサードパーティ製のスマートウォッチ アプリにレスポンスを中継します。

注: アプリのパッケージ名がリダイレクト URL 内の 3 番目のパス コンポーネントになるようにします。つまり、redirect_urihttps://wear.googleapis.com/3p_auth/<receiving app's packagename> のように指定する必要があります(例: https://wear.googleapis.com/3p_auth/com.package.name)。

スマートウォッチ上のサードパーティ製アプリはレスポンスから認証トークンを抽出し、その後のリクエストでその認証トークンを認証情報として使用します。

Kotlin

    oAuthClient.sendAuthorizationRequest(Uri.parse(requestUrl), MyOAuthCallback())
    

Java

    // The callback provided will be called when the OAuth request completes.
    oAuthClient.sendAuthorizationRequest(Uri.parse(requestUrl), new MyOAuthCallback());
    

Kotlin

    private class MyOAuthCallback : OAuthClient.Callback() {

        override fun onAuthorizationResponse(requestUrl: Uri, responseUrl: Uri) {
            Runnable {
                acquireToken()
                accessAPI()
            }.apply {
                ...
            }
        }
    }
    

Java

    private class MyOAuthCallback extends OAuthClient.Callback {
        @Override
        public void onAuthorizationResponse(Uri requestUrl, Uri responseUrl) {
            Runnable r =
                new Runnable() {
                    public void run() {
                        acquireToken();
                        accessAPI();
                    }
                };
        }
    }
    

このフローの完全な実装については、サンプルをご覧ください。

注: このサンプルでは、スマートウォッチがトークンの交換を処理しています。リダイレクト URI は、サーバーが認証コードのトークンとの交換を実行できる専用のサーバー URL に設定することをおすすめします。

データレイヤを介してトークンを渡す

このオプションは、Android スマートフォンとペア設定されているスマートウォッチでのみ使用できます。スマートフォンのコンパニオン アプリは、ウェアラブル データレイヤを介して認証データを Wear アプリに安全に転送できます。認証情報はメッセージまたはデータ項目として転送できます。

注: スマートフォン APK とスマートウォッチ APK の配信には同じパッケージ名を使用することをおすすめします。こうすることで、スマートフォン アプリと Wear アプリが DataItem レイヤを介して通信を行い、スマートフォンからスマートウォッチにバックグラウンドでトークンを転送し、認証を実行することができます。

フロー

Data Layer API を使用して認証情報を渡す独自のビジネス ロジックを使用できます。次の図は、ウェアラブル データレイヤを介してトークンを取得する方法を示しています。

カスタムコード認証

この認証方法では、ユーザーは外部ソース(モバイル デバイス、タブレット、パソコン)から認証を行う必要があります。また、身元を証明するために入力する一時的なコードを取得し、Wear デバイスでそれを認証トークンと交換する必要があります。この方法では、アプリのログイン モジュールを使用するか、サードパーティの認証プロバイダによるログイン方法をアプリのコードに手動で組み込むことにより、Wear アプリでユーザーを認証できます。この認証方法では手動での作業やセキュリティ向上のための追加作業が必要になりますが、スタンドアロンの Wear アプリで早い段階で認証を行う必要がある場合はこの方法を使用できます。

この認証フローは次のようになります。

  1. ユーザーが、認証を必要とするサードパーティ製アプリで操作を行います。
  2. サードパーティの Wear アプリがユーザーに認証画面を表示し、指定の URL でコードを入力するようユーザーに指示します。
  3. ユーザーがモバイル デバイス、タブレット、パソコンのいずれかでブラウザを起動し、Wear アプリで指定されている URL に移動してログインします。
  4. ユーザーが、Wear のオンボード キーボードを使用して Wear アプリの認証画面に入力する一時的なコードを受け取り、認証を実行します。

  5. この時点から、入力したコードを正しいユーザーであることの証拠として使用できるようになります。また、Wear デバイスに保存され、セキュリティ保護されている認証トークンとそのコードを交換し、その後の認証要求で使用できるようになります。