본문 바로가기
프로그래밍/Flutter & Dart

Flutter 구글 로그인 Trouble shooting, PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null, null)

by 어느덧중반 2021. 11. 4.
반응형

Flutter 구글 로그인 구현 중 PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null, null) 에러를 만나게 된다면...

 

Flutter로 많은 앱들을 개발하며 구글 로그인도 접해왔지만 가끔 구현 중에 이상하게 로그인이 안되던 이슈들이 생긴 적이 있었다. 그 때마다 어떻게 해결했는지는 정확하게 기억하질 못해서, 얼마 전까지 이유는 모르지만 열심히 구글링한 덕분에 해결했다는 뿌듯함만 남긴 채 기억에서 지워지곤 했었는데, 이번에도 비슷한 상황이 벌어졌고 꼭 정리를 하고 넘어가야겠다고 판단해서 포스팅을 해보기로 한다.

 

 

어떤 현상인가?

 구글 로그인 버튼을 누르고 아이디 / 패스워드 입력까지 마친 후에 정상적으로 로그인이 되어야 하는데 아래의 에러메시지와 함께 로그인이 되지 않는다.

구글 로그인에 실패하는 경우 보통 저 에러문구를 확인하게 될 것이다.

 

첫 번째 해결법

많은 경우에서 아래의 방법으로 해결이 가능할 것이다. 문제의 원인은 바로 Firebase 프로젝트 설정에서 안드로이드앱 중 SHA-1 추가를 해주지 않아서이다. SHA-1 추가를 어디서 하는지는 아래의 캡쳐화면을 따라가 보자.

Firebase 프로젝트 > 설정 > 일반 > 내 앱

내 앱으로 이동하게 되면 하단에 SHA 인증서 지문 추가하는 곳이 있다.

대부분의 경우 여기서 본인의 debug.keystore 조회 후 추가해주면 될 것이다. 방법은 아래와 같다.

// 키 생성하기
1. 해당 폴더로 이동
	- Mac : /Users/{사용자이름}/.android
	- Windows : C:\Users\{사용자이름}\.android
2. (키가 없는 경우) 키 생성
	- keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000
	- keytool -genkey -v -keystore release.keystore -alias androidreleasekey -keyalg RSA -keysize 2048 -validity 10000
3. 키 조회 (PW: android)
	- keytool -list -v -keystore debug.keystore -alias androiddebugkey
	- keytool -list -v -keystore release.keystore -alias androidreleasekey

 

조회되는 2개의 키를 아래와 같이 추가해주자. (나는 3개의 키를 추가했는데 이유는 아래로 더 내리면 나올 것이다.)

하단의 SHA 인증서 지문

 

자, 인증서 지문을 추가한 후에 다시 google-services.json 파일을 내려받고 flutter 프로젝트 > android > app 폴더 아래에 위치시킨 후 다시 실행시켜보자.

google-services.json 파일을 다운받자.
Flutter 프로젝트 > android > app 폴더 하위로 복사

 

자 이제 다시 빌드를 돌려서 확인해보면 거진 다 해결이 될 것이라고 본다!

그런데, 나는 되지 않았다. 왜냐면 실제 release모드로 테스트를 위해 배포할 때와 같은 설정으로 build.gradle 파일에 여러 설정들로 인해 새로운 해시키가 필요했기 때문이다.

다시 말해보면, 나는 이런저런 설정을 통해서 기존의 인증서 지문(debug, release 해시키)만 추가한다고 되지 않았다. 추가적으로 key.jks 해시키를 조회해서 그것까지 추가해줘야했다.

 

아래의 Flutter 프로젝트 > android > app > build.gradle 파일을 보겠다.

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

// start of Gradle 서명 구성
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    compileSdkVersion 30

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.kyungsnim.xxxxxxxxxxx"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        multiDexEnabled true
    }

    //     start of signingConfigs
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
        }
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            // signingConfig signingConfigs.debug
            signingConfig signingConfigs.release

            // start of 코드난독화 및 사이즈 축소
            minifyEnabled true
            useProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            // end of 코드난독화 및 사이즈 축소
        }
    }
}

flutter {
    source '../..'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

 

설정을 보게 되면 코드 난독화도 이루어지고, signing Configs에 key.jks를 이용하게 된다.

해당 설정을 위해 Flutter 프로젝트 > android 폴더 하위에 key.properties 파일을 생성하고 아래와 같이 넣어주었다.ㅓ

아래 본인의 설정 패스워드는 본인이 각자 정해주면 된다.

앗, 여기서 조금 헷깔리는건.... 나는 아마도 언젠가 key.jks 파일을 만들었던 적이 있어서 바로 조회가 가능할텐데,

해당 위치에 key.jks 파일이 없다면 구글링을 해서 새로 생성을 해야 할 것이다.

 

 

storePassword=본인의 설정 패스워드
keyPassword=본인의 설정 패스워드
keyAlias=key
storeFile=/Users/본인폴더/key.jks

 

 

key.jks 해시키 가져오기

아래의 명령어를 통해 key.jks 키를 조회해보자.

keytool -list -v -keystore /Users/본인폴더/key.jks

 

가령, 위의 명령어를 통해 얻어낸 키를 7A:AB:BE:C4:10:81:02:57:AE:04:98:D3:2D:1C:82:82:C2:34:E6:D6 라고 가정해보자.

조회가 되었다면 아래의 명령어를 통해 최종적으로 해시키 조회가 가능하다.

echo (앱서명 인증서 SHA-1 인증서 지문) | xxd -r -p | openssl base64

 

이제 위의 예시로 들었던 인증서 지문을 대입하면 아래와 같은 명령어가 될 것이다.

echo 7A:AB:BE:C4:10:81:02:57:AE:04:98:D3:2D:1C:82:82:C2:34:E6:D6 | xxd -r -p | openssl base64

 

해당 명령어를 통해 최종 해시키를 조회할 수 있게 된다.

이제 얻은 해시키를 위에서 추가했던 Firebase 프로젝트 설정 > 일반 > 내 앱 > 인증서 지문에 추가해주고 새로 google-services.json 파일을 내려받고 Flutter 프로젝트 > android > app 폴더 하위에 새로 덮어씌우면 적용이 완료될 것이다.

 

나는 최종 테스트를 flutter run --release 명령어를 통해 실행했고, 결과는 정상적으로 잘 동작하게 되었다.

 

반응형

댓글