Google-One Tap Login 인증관리자로 마이그레이션 하기

WonDDak·2023년 12월 19일
0

기존 안드로이드에서 구글 로그인시에는 One Tap Login을 사용하여 구현하였다.

어느날 보니 갑자기 다음과 같은 메시지가 노출되고있었다.

주의: Android용 원탭 지원이 곧 중단됩니다. 앱의 보안 및 사용성을 계속 유지하려면 지금 인증 관리자로 이전하세요. 인증 관리자는 패스키, 비밀번호, 제휴 ID 인증 (예: Google 계정으로 로그인), 더 강력한 보안, 더 일관된 사용자 환경을 지원합니다.

인증 관리자

인증 관리자는 단일 API에서 사용자 이름과 비밀번호, 패스키, 제휴 로그인 솔루션(예: Google 계정으로 로그인)과 같은 멀티 로그인 방식을 지원하여 개발자를 위해 통합을 간소화하는 Jetpack API입니다.

여기서는 다른방식은 다루지 않고 Android용 원탭 로그인을 인증관리자로 마이그레이션 하는 방법은 서술합니다.

프로젝트가 없으시다면 아래 Base Project를 클론하여 사용해보세요

Base Project를 기반으로 수정을 진행할것입니다.

종속성 추가

dependencies {
    implementation("androidx.credentials:credentials:1.3.0-alpha01")

    // optional - needed for credentials support from play services, for devices running
    // Android 13 and below.
    implementation("androidx.credentials:credentials-play-services-auth:1.3.0-alpha01")
    
    //구글 로그인 지원용
    implementation("com.google.android.libraries.identity.googleid:googleid:1.1.0"
}

googleid의 최신버전은 여기에서 확인 가능하다. 23년 8월 22일 부 최신 버전은 1.1.0이다.

Progaurd 처리

프로가드를 사용중이라면 다음을 예외처리해주자

-if class androidx.credentials.CredentialManager
-keep class androidx.credentials.playservices.** {
  *;
}

CredentialManager 설정

GoogleLoginHelper Class에 다음을 추가하겠습니다.

val credentialManager = CredentialManager.create(context)

그리고 googleIdOption을 정의해 줍시다.
원탭에서 signInRequest처럼 client값 설정을 한다고 보시면 됩니다.

        googleIdOption = GetGoogleIdOption.Builder()
            .setFilterByAuthorizedAccounts(false)
            .setServerClientId("INPUT_WEB_CLIENT_ID")
            .build()

위 아래를 비교해 보시면 좋을것 같습니다.

        signInRequest = BeginSignInRequest.builder()
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId("INPUT_WEB_CLIENT_ID")
                    // Only show accounts previously used to sign in.(true)
                    .setFilterByAuthorizedAccounts(false)
                    .build()
            )
            // Automatically sign in when exactly one credential is retrieved.
            .setAutoSelectEnabled(true)
            .build()           

인증 요청

    suspend fun requestGoogleLogin(
        activityContext : Context,
        failAction: (msg: String) -> Unit,
        successAction: (result: AuthResult) -> Unit
    ) {
        val request: GetCredentialRequest = GetCredentialRequest.Builder()
            .addCredentialOption(googleIdOption)
            .build()
        
        runCatching {
            credentialManager.getCredential(
                request = request,
                context = activityContext,
            )
        }.onSuccess {
            //성공시 액션
            val credential = it.credential
            when(credential) {
                is CustomCredential -> {
                    if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
                        try {
                            // Use googleIdTokenCredential and extract id to validate and
                            // authenticate on your server.
                            val googleIdTokenCredential = GoogleIdTokenCredential
                                .createFrom(credential.data)
                            registerToFirebase(
                                googleIdTokenCredential.idToken,
                                failAction,
                                successAction
                            )
                        } catch (e: GoogleIdTokenParsingException) {
                            Log.e(TAG, "Received an invalid google id token response", e)
                        }
                    }
                }
            }
        }.onFailure {
            //실패시 액션
            failAction(it.localizedMessage ?: "unknown error")
        }
    }

여기서 중요한 점은

  • credentialManager.getCredential이 suspend 함수 이기 때문에 coroutineScope내에서 작동되야 합니다.
  • getCredential의 context는 activity의 context여야 합니다.
  • 인증후 생성되는 GetCredentialResponseCustomCredential >> credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL으로 확인합니다.

이후

val googleIdTokenCredential = GoogleIdTokenCredential
                                .createFrom(credential.data)

형태로 구글 id토큰을 가져와 기존과 동일하게 진행 하시면 됩니다.
저는 firebase auth와 함께 사용중이라 연동시켰습니다.

profile
안녕하세요. 원딱입니다.

0개의 댓글