Android 向けアプリ切り替え

OAuthベースのアプリフリップリンク(App Flip)は、AndroidアプリをGoogleアカウントリンクフローに挿入します。従来のアカウントリンクフローでは、ユーザーがブラウザにクレデンシャルを入力する必要があります。 App Flipを使用すると、Androidアプリへのユーザーのログインが延期され、既存の認証を活用できるようになります。ユーザーがアプリにサインインしている場合、アカウントをリンクするために資格情報を再入力する必要はありません。 AndroidアプリにAppFlipを実装するには、最小限のコード変更が必要です。

このドキュメントでは、AppFlipをサポートするようにAndroidアプリを変更する方法を学習します。

サンプルをお試しください

リンクのAppフリップサンプルアプリは、 Android上で統合を結ぶのAppフリップ互換アカウントを示しています。このアプリを使用して、Googleモバイルアプリからの着信AppFlipインテントに応答する方法を確認できます。

サンプルアプリはと統合するために事前に設定されてAndroid用アプリのフリップテストツールあなたが設定しグーグルとの連携を占める前に、アプリのフリップを使ってAndroidアプリの統合を確認するために使用することができ、。このアプリは、AppFlipが有効になっているときにGoogleモバイルアプリによってトリガーされるインテントをシミュレートします。

使い方

App Flip統合を実行するには、次の手順が必要です。

  1. Googleのアプリをチェックし、あなたのアプリは、そのパッケージ名を使用して、デバイスにインストールされている場合。
  2. Googleアプリは、パッケージの署名チェックを使用して、インストールされているアプリが正しいアプリであることを検証します。
  3. Googleアプリは、アプリで指定されたアクティビティを開始するインテントを構築します。このインテントには、リンクに必要な追加データが含まれています。また、Androidフレームワークを介してこのインテントを解決することにより、アプリがAppFlipをサポートしているかどうかを確認します。
  4. アプリは、リクエストがGoogleアプリからのものであることを検証します。そのために、アプリはパッケージの署名と提供されたクライアントIDを確認します。
  5. アプリがOAuth2.0サーバーに認証コードを要求します。このフローの最後に、認証コードまたはエラーのいずれかをGoogleアプリに返します。
  6. Googleアプリは結果を取得し、アカウントのリンクを続行します。認証コードが提供されている場合、トークンの交換は、ブラウザベースのOAuthリンクフローの場合と同じように、サーバー間で行われます。

AppFlipをサポートするようにAndroidアプリを変更します

App Flipをサポートするには、Androidアプリに次のコード変更を加えます。

  1. 追加<intent-filter>あなたへAndroidManifest.xmlアプリフリップテントフィールドに入力された値と一致したアクション文字列を含むファイル。

    <activity android:name="AuthActivity">
      <!-- Handle the app flip intent -->
      <intent-filter>
        <action android:name="INTENT_ACTION_FROM_CONSOLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </activity>
    
  2. 呼び出し元のアプリの署名を検証します。

    private fun verifyFingerprint(
            expectedPackage: String,
            expectedFingerprint: String,
            algorithm: String
    ): Boolean {
    
        callingActivity?.packageName?.let {
            if (expectedPackage == it) {
                val packageInfo =
                    packageManager.getPackageInfo(it, PackageManager.GET_SIGNATURES)
                val signatures = packageInfo.signatures
                val input = ByteArrayInputStream(signatures[0].toByteArray())
    
                val certificateFactory = CertificateFactory.getInstance("X509")
                val certificate =
                    certificateFactory.generateCertificate(input) as X509Certificate
                val md = MessageDigest.getInstance(algorithm)
                val publicKey = md.digest(certificate.encoded)
                val fingerprint = publicKey.joinToString(":") { "%02X".format(it) }
    
                return (expectedFingerprint == fingerprint)
            }
        }
        return false
    }
    
  3. インテントパラメータからクライアントIDを抽出し、クライアントIDが期待値と一致することを確認します。

    private const val EXPECTED_CLIENT = "<client-id-from-actions-console>"
    private const val EXPECTED_PACKAGE = "<google-app-package-name>"
    private const val EXPECTED_FINGERPRINT = "<google-app-signature>"
    private const val ALGORITHM = "SHA-256"
    ...
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val clientId = intent.getStringExtra("CLIENT_ID")
    
        if (clientId == EXPECTED_CLIENT &&
            verifyFingerprint(EXPECTED_PACKAGE, EXPECTED_FINGERPRINT, ALGORITHM)) {
    
            // ...authorize the user...
        }
    }
    
  4. 認証が成功したら、結果の認証コードをGoogleに返します。

    // Successful result
    val data = Intent().apply {
        putExtra("AUTHORIZATION_CODE", authCode)
    }
    setResult(Activity.RESULT_OK, data)
    finish()
    
  5. エラーが発生した場合は、代わりにエラー結果を返します。

    // Error result
    val error = Intent().apply {
        putExtra("ERROR_TYPE", 1)
        putExtra("ERROR_CODE", 1)
        putExtra("ERROR_DESCRIPTION", "Invalid Request")
    }
    setResult(-2, error)
    finish()
    

ローンチインテントの内容

アプリを起動するAndroidインテントには、次のフィールドが含まれます。

  • CLIENT_IDString ):Googleはclient_idのアプリの下に登録されています。
  • SCOPEString[] ):要求されたスコープのリスト。
  • REDIRECT_URIString ):リダイレクトURL。

応答データの内容

Googleのアプリに返されたデータは、呼び出すことによって、あなたのアプリケーションに設定されているsetResult()このデータには次のものが含まれます。

  • AUTHORIZATION_CODEString ):認証コード値。
  • resultCodeint ):通信プロセスの成功または失敗と、次のいずれかの値をとります。
    • Activity.RESULT_OK :成功を示します。認証コードが返されます。
    • Activity.RESULT_CANCELLED :ユーザーがプロセスをキャンセルしたことを通知することを。この場合、Googleアプリは認証URLを使用してアカウントのリンクを試みます。
    • -2 :エラーが発生したことを示します。さまざまな種類のエラーについて、以下で説明します。
  • ERROR_TYPEint ):エラーの種類、次のいずれかの値をとります。
    • 1 :回復可能エラー:Googleのアプリは、認証URLを使用してリンクするアカウントを試みます。
    • 2 :回復不能なエラー:Googleのアプリのアボートは、リンクを占めています。
    • 3 :無効または欠落しているリクエストパラメータ。
  • ERROR_CODEint ):エラーの性質を表す整数。各エラーコード手段は、参照ものを見るためにエラーコードのテーブル
  • ERROR_DESCRIPTIONString 、オプション):エラーを説明する人間可読状態メッセージ。

AUTHORIZATION_CODEするとき期待されているresultCode == Activity.RESULT_OK 。他のすべての場合で、値AUTHORIZATION_CODE空である必要があります。場合resultCode == -2 、次いでERROR_TYPE値が移入されることが期待されます。

エラーコードの表

次の表は、さまざまなエラーコードと、それぞれが回復可能なエラーであるか回復不可能なエラーであるかを示しています。

エラーコード意味回復可能回復不能
1 INVALID_REQUEST
2 NO_INTERNET_CONNECTION
3 OFFLINE_MODE_ACTIVE
4 CONNECTION_TIMEOUT
5 INTERNAL_ERROR
6 AUTHENTICATION_SERVICE_UNAVAILABLE
8 CLIENT_VERIFICATION_FAILED
9 INVALID_CLIENT
10 INVALID_APP_ID
11 INVALID_REQUEST
12 AUTHENTICATION_SERVICE_UNKNOWN_ERROR
13 AUTHENTICATION_DENIED_BY_USER
14 CANCELLED_BY_USER
15 FAILURE_OTHER
16 USER_AUTHENTICATION_FAILED

すべてのエラー・コードの場合、あなたは経由してエラー結果を返さなければならないsetResult適切なフォールバックがtrigerredされていることを確認します。