OAuth 기반 앱 플립 연결 (앱 플립)은 Google 계정 연결 흐름 기존 계정 연결 흐름에서는 브라우저에 사용자 인증 정보를 입력할 수 있습니다. 앱 플립 사용 시 Android 앱에 로그인할 수 있는데, 이렇게 하면 기존의 있습니다. 사용자가 앱에 로그인되어 있으면 사용자 인증 정보를 다시 입력하여 계정을 연결합니다. 최소한의 코드 양 변경사항이 없습니다.
이 문서에서는 Android 앱을 수정하여 앱 플립
샘플 사용해 보기
앱 플립 연결 샘플 앱 은 Android에서 앱 플립과 호환되는 계정 연결 통합을 보여줍니다. 나 이 앱을 사용하여 Google 모바일 앱
샘플 앱은 App Flip Test Tool과 통합되도록 사전 구성되어 있으며 Android 이는 Android 앱과 앱의 통합을 확인하는 데 사용할 수 있는 Google과의 계정 연결을 구성하기 전에 뒤집으세요. 이 앱은 앱 플립이 사용 설정된 경우 Google 모바일 앱에 의해 트리거되는 인텐트를 반환합니다.
작동 방식
앱 플립 통합을 실행하려면 다음 단계를 따라야 합니다.
- Google 앱은 다음을 사용하여 앱이 기기에 설치되어 있는지 확인합니다. 패키지 이름을 입력합니다.
- Google 앱은 패키지 서명 검사를 사용하여 설치된 올바른 앱인지 확인합니다.
- Google 앱은 앱에서 지정된 활동을 시작하는 인텐트를 빌드합니다. 이 인텐트에는 연결에 필요한 추가 데이터가 포함되어 있습니다. 또한 를 통해 이 인텐트를 해결하여 앱이 앱 플립을 지원하는지 확인합니다. Android 프레임워크입니다.
- 요청이 Google 앱에서 비롯되는지 앱이 확인합니다. 이렇게 하려면 앱이 패키지 서명과 제공된 클라이언트 ID를 확인합니다.
- 앱에서 OAuth 2.0 서버로부터 승인 코드를 요청합니다. 인증 코드 또는 오류를 반환합니다. Google 앱
- Google 앱은 결과를 검색하고 계정 연결을 계속 진행합니다. 만약 승인 코드가 제공되면 토큰 교환은 브라우저 기반 OAuth 연결에서와 동일한 방식으로 있습니다.
앱 플립을 지원하도록 Android 앱 수정
앱 플립을 지원하려면 Android 앱의 코드를 다음과 같이 변경합니다.
작업으로
AndroidManifest.xml
파일에<intent-filter>
를 추가합니다. 앱 플립 인텐트 입력란에 입력한 값과 일치하는 문자열을 반환합니다.<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>
호출 앱의 서명 유효성 검사
<ph type="x-smartling-placeholder">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 }
인텐트 매개변수에서 클라이언트 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... } }
승인이 완료되면 결과 승인 코드를 반환합니다. 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
): 프로세스의 성공 또는 실패를 전달합니다. 다음 값 중 하나를 사용합니다. <ph type="x-smartling-placeholder">- </ph>
Activity.RESULT_OK
: 성공을 나타냅니다. 승인 코드가 반환됩니다.Activity.RESULT_CANCELLED
: 사용자가 프로세스입니다 이 경우 Google 앱은 승인 URL을 입력합니다.-2
: 오류가 발생했음을 나타냅니다. 다양한 유형의 오류 아래에 설명되어 있습니다.
ERROR_TYPE
(int
): 오류 유형으로, 다음 중 하나를 취합니다. 값: <ph type="x-smartling-placeholder">- </ph>
1
: 복구 가능한 오류: Google 앱에서 다음을 사용하여 계정 연결을 시도합니다. 승인 URL입니다.2
: 복구할 수 없는 오류: Google 앱에서 계정 연결을 취소합니다.3
: 요청 매개변수가 잘못되었거나 누락되었습니다.
ERROR_CODE
(int
): 오류의 특성을 나타내는 정수입니다. 보기 자세히 알아보려면 오류 코드 표에 나와 있습니다.ERROR_DESCRIPTION
(String
, 선택사항): 사람이 읽을 수 있는 상태 메시지 반환합니다.
다음과 같은 경우 AUTHORIZATION_CODE
값이 예상됩니다.
resultCode == Activity.RESULT_OK
입니다. 다른 모든 경우에는 이
AUTHORIZATION_CODE
필드는 비어 있어야 합니다. resultCode == -2
인 경우
ERROR_TYPE
값이 채워져야 합니다.
오류 코드 표
아래 표에는 다양한 오류 코드와 각 오류가 복구 가능한 오류인지 복구할 수 없는 오류인지 여부가 나와 있습니다.
오류 코드 | 의미 | 복구 가능 | Unrecoverable |
---|---|---|---|
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
를 통해 오류 결과를 반환해야 합니다.
적절한 대체가 트리거되는지 확인합니다