Привязка 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 необходимы следующие шаги:
- Приложение Google проверяет, установлено ли ваше приложение на устройстве, используя имя его пакета .
- Приложение Google использует проверку подписи пакета, чтобы убедиться, что установленное приложение является правильным.
- Приложение Google формирует намерение начать определенное действие в вашем приложении. Это намерение включает дополнительные данные, необходимые для связывания. Он также проверяет, поддерживает ли ваше приложение App Flip, разрешая это намерение через платформу Android.
- Ваше приложение подтверждает, что запрос поступает из приложения Google. Для этого ваше приложение проверяет подпись пакета и предоставленный идентификатор клиента.
- Ваше приложение запрашивает код авторизации с вашего сервера OAuth 2.0. В конце этого потока он возвращает приложению Google либо код авторизации, либо ошибку.
- Приложение Google получит результат и продолжит привязку аккаунта. Если предоставлен код авторизации, обмен токенами происходит между серверами так же, как и в процессе связывания OAuth на основе браузера.
Измените свое приложение Android, чтобы оно поддерживало App Flip.
Чтобы поддержать App Flip, внесите следующие изменения кода в свое приложение Android:
Добавьте
<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>
Проверьте подпись вызывающего приложения.
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 }
Извлеките идентификатор клиента из параметров намерения и убедитесь, что идентификатор клиента соответствует ожидаемому значению.
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... } }
При успешной авторизации верните полученный код авторизации обратно в Google.
// Successful result val data = Intent().apply { putExtra("AUTHORIZATION_CODE", authCode) } setResult(Activity.RESULT_OK, data) finish()
Если произошла ошибка, вместо этого верните результат ошибки.
// 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
): Googleclient_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
, чтобы обеспечить срабатывание соответствующего резервного варианта.