Firebase Authentication을 활용해 구글 로그인을 연동해보도록 하겠다.
구글 로그인의 순서는
더 자세한 내용은 공식 문서를 참고하길 바란다.
build.gradle(Module) 파일에 구글 로그인에 필요한 라이브러리들을 추가한다.
빨간줄이 그거져 있는 세 가지 라이브러리가 필요하다.앱의 SHA-1 디지털 지문을 지정한다.
첫 번째로 안드로이드 스튜디오 프로젝트에서 SHA-1을 복사해야 한다. View->Tool Windows->Gradle->Tasks->android->signingReport
로 이동하면 SHA-1을 확인할 수 있다.
이후 firebase 콘솔로 이동해 프로젝트 설정 -> 디지털 지문 추가
를 클릭해 복사한 SHA-1을 등록한다.
Authentication->Sign-in method->Google->사용설정 활성화
를 통해 구글 로그인을 사용할 수 있도록 해 준다. 구글 로그인 후 앱에서 필요한 사용자 정보를 요청하기 위해 구글로그인을 구성하는 단계이다. 아래 코드는 DEFAULT_SIGN_IN
매개변수를 사용해 사용자 ID와 기본 프로필 정보를 요청하도록 만들었다. 구성된 GoogleSignInOptions 객체를 활용해 GoogleSignInClient 객체를 생성한다.
var googleSignInClient: GoogleSignInClient? = null
//GoogleSignInOptions 객체 생성
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(clientId)
.requestEmail()
.build()
//GoogleSignInClient 객체 생성
googleSignInClient = GoogleSignIn.getClient(context, gso)
다음은 로그인 화면에서 구글 아이디로 로그인 버튼을 누르면 우리가 잘 아는 구글 로그인 화면으로 이동하도록 하는 코드이다.
override fun onCreate(savedInstanceState: Bundle?) {
...
binding.googleLoginButton.setOnClickListener {
googleSignIn()
}
}
fun googleSignIn() {
//Launcher를 실행해 LoginActivity -> 구글 로그인 화면으로 이동.
launcher!!.launch(getString(R.string.default_web_client_id))
}
LoginActivity.kt에서 구글로그인 버튼을 클릭하면 googleSignIn() 함수가 호출되도록 작성하였다. 이 때 googleSingIn() 함수는 구글로그인 인텐트를 생성해 해당 화면으로 이동하도록 하는 함수이다.
startActivityForResult()가 deprecated 되면서 registerForActivityResult()
를 사용했다.
//LoginActivity에서 구글 아이디로 로그인 버튼을 누르면 구글 로그인 화면으로 이동하는 intent를 만드는 함수.
override fun createIntent(context: Context, clientId: String): Intent {
//구글로그인 초기설정
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(clientId)
.requestEmail()
.build()
googleSignInClient = GoogleSignIn.getClient(context, gso)
//구글로그인 화면 intent
val signInIntent = googleSignInClient!!.signInIntent
return signInIntent
}
ActivityResultContract<I, O> 추상클래스를 상속한 서브 클래스를 만들어 Contract를 생성했고, createIntent() 추상메서드 안에 인텐트를 생성하는 코드를 추가했다.
로그인에 성공하면 구글에서는 로그인한 사용자의 정보를 얻을 때 필요한 IdToken을 전달
한다. 이를 가져오는 코드를 작성해 볼 것이다. ActivityResultContract<I, O> 추상클래스의 추상메소드 중에 parseResult()
가 있다. 이 메소드를 활용해 구글 로그인 화면에서 로그인 화면으로 다시 돌아온 후 구글 로그인 화면으로부터 전달 받은 IdToken을 가져오는 코드를 작성해 보자.
//구글 로그인 화면에서 다시 LoginActivity로 돌아올 때 호춯되는 함수.
override fun parseResult(resultCode: Int, intent: Intent?): String? {
return when (resultCode) {
//정상적으로 로그인이 이뤄진 경우 getTokenId 함수를 통해 얻은 tokenId를 LoginActivity에 전달.
Activity.RESULT_OK -> getTokenId(intent)
else -> null
}
}
//tokenId를 리턴해주는 함수.
fun getTokenId(data: Intent?): String? {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
// Google Sign In was successful, authenticate with Firebase
val account = task.getResult(ApiException::class.java)!!
return account.idToken
} catch (e: ApiException) {
// Google Sign In failed, update UI appropriately
println("getTokenId() tokenId를 정상적으로 얻어오지 못함=>\n${e}")
return null
}
}
IdToken으로 Firebase 사용자 인증 정보로 교환을 한 후 교환된 정보를 이용해 Firebase에 인증할 수 있다.
val credential = GoogleAuthProvider.getCredential(idToken, null)
//Firebase 사용자 인증 정보(credential)를 사용해 Firebase에 인증.
auth!!.signInWithCredential(credential)
.addOnCompleteListener(this@LoginActivity) { task: Task<AuthResult> ->
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Toast.makeText(
this@LoginActivity,
getString(R.string.signin_complete),
Toast.LENGTH_SHORT
).show()
} else {
println("firebaseAuthWithGoogle => ${task.exception}")
Toast.makeText(
this@LoginActivity, getString(R.string.signin_google_faile),
Toast.LENGTH_SHORT
).show()
}
}
credential 변수가 IdToken으로 교환 받은 Firesbase 사용자 인증 정보이고, signInWithCredential() 메서드를 통해 Firebase에 인증을 진행한다.