Приложение Флип для Android

Привязка App Flip на основе OAuth (App Flip) вставляет ваше приложение Android в процесс привязки учетной записи Google. Традиционный процесс привязки учетной записи требует от пользователя ввода своих учетных данных в браузере. Использование App Flip откладывает вход пользователя в ваше приложение Android, что позволяет использовать существующие авторизации. Если пользователь вошел в ваше приложение, ему не нужно повторно вводить свои учетные данные, чтобы связать свою учетную запись. Для реализации App Flip в вашем приложении Android требуется минимальное количество изменений кода.

В этом документе вы узнаете, как изменить приложение Android для поддержки App Flip.

Попробуйте образец

Пример приложения привязки App Flip демонстрирует интеграцию привязки учетных записей, совместимую с App Flip, на Android. Вы можете использовать это приложение, чтобы проверить, как реагировать на входящее намерение App Flip из мобильных приложений Google.

Пример приложения предварительно настроен для интеграции с App Flip Test Tool для Android , который вы можете использовать для проверки интеграции вашего приложения Android с App Flip, прежде чем настраивать привязку учетной записи к Google. Это приложение имитирует намерение, вызванное мобильными приложениями Google, когда включен App Flip.

Как это работает

Для выполнения интеграции App Flip необходимы следующие шаги:

  1. Приложение Google проверяет, установлено ли ваше приложение на устройстве, используя имя его пакета .
  2. Приложение Google использует проверку подписи пакета, чтобы убедиться, что установленное приложение является правильным.
  3. Приложение Google формирует намерение начать определенное действие в вашем приложении. Это намерение включает дополнительные данные, необходимые для связывания. Он также проверяет, поддерживает ли ваше приложение App Flip, разрешая это намерение через платформу Android.
  4. Ваше приложение подтверждает, что запрос поступает из приложения Google. Для этого ваше приложение проверяет подпись пакета и предоставленный идентификатор клиента.
  5. Ваше приложение запрашивает код авторизации с вашего сервера OAuth 2.0. В конце этого потока он возвращает приложению Google либо код авторизации, либо ошибку.
  6. Приложение Google получит результат и продолжит привязку аккаунта. Если предоставлен код авторизации, обмен токенами происходит между серверами так же, как и в процессе связывания OAuth на основе браузера.

Измените свое приложение Android, чтобы оно поддерживало App Flip.

Чтобы поддержать App Flip, внесите следующие изменения в код своего приложения Android:

  1. Добавьте <intent-filter> в файл AndroidManifest.xml со строкой действия, соответствующей значению, введенному вами в поле App Flip Intent .

    <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. Извлеките идентификатор клиента из параметров намерения и убедитесь, что идентификатор клиента соответствует ожидаемому значению.

    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_ID ( String ): Google client_id , зарегистрированный в вашем приложении.
  • SCOPE ( String[] ): список запрошенных областей.
  • REDIRECT_URI ( String ): URL-адрес перенаправления.

Содержание данных ответа

Данные, возвращаемые в приложение Google, устанавливаются в вашем приложении с помощью вызова setResult() . Эти данные включают в себя следующее:

  • AUTHORIZATION_CODE ( String ): значение кода авторизации.
  • resultCode ( int ): сообщает об успехе или неудаче процесса и принимает одно из следующих значений:
    • Activity.RESULT_OK : указывает на успех; возвращается код авторизации.
    • Activity.RESULT_CANCELLED : сигнализирует о том, что пользователь отменил процесс. В этом случае приложение Google попытается связать учетную запись, используя ваш URL-адрес авторизации.
    • -2 : указывает на то, что произошла ошибка. Ниже описаны различные типы ошибок.
  • ERROR_TYPE ( int ): тип ошибки, принимающий одно из следующих значений:
    • 1 : Устранимая ошибка: приложение Google попытается связать учетную запись с использованием URL-адреса авторизации.
    • 2 : Неустранимая ошибка: приложение Google прерывает привязку аккаунта.
    • 3 : Неверные или отсутствующие параметры запроса.
  • ERROR_CODE ( int ): целое число, представляющее характер ошибки. Чтобы узнать, что означает каждый код ошибки, обратитесь к таблице кодов ошибок .
  • ERROR_DESCRIPTION ( String , необязательно): удобочитаемое сообщение о состоянии, описывающее ошибку.

Значение 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 , чтобы обеспечить срабатывание соответствующего резервного варианта.