이 가이드에서는 Google로 로그인을 구현하는 방법을 설명하고 다음 단계를 다룹니다.
- 앱에 종속 항목을 추가합니다.
CredentialManager을 인스턴스화합니다.- 하단 시트 흐름을 만듭니다.
- 버튼 흐름을 만듭니다.
- 로그인 응답을 처리합니다.
- 오류를 처리합니다.
- 로그아웃을 처리합니다.
앱에 종속 항목 추가
모듈의 build.gradle 파일에서 최신 버전의 인증 관리자, Play 서비스 인증 및 googleid을 사용하여 종속 항목을 선언합니다.
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.6.0-rc02") implementation("androidx.credentials:credentials-play-services-auth:1.6.0-rc02") implementation("com.google.android.libraries.identity.googleid:googleid:<latest version>") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.6.0-rc02" implementation "androidx.credentials:credentials-play-services-auth:1.6.0-rc02" implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>" }
인증 관리자 인스턴스화
앱 또는 활동 컨텍스트를 사용하여 CredentialManager 객체를 만듭니다.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)
하단 시트 흐름 만들기
하단 시트는 인증 관리자의 내장 UI입니다. 이 UI를 사용하면 비밀번호, 패스키, Google 계정으로 로그인 등 모든 인증 방법에서 일관된 환경이 만들어집니다.
이전에 승인된 계정의 로그인 요청 구성
GetGoogleIdOption으로 Google 로그인 요청을 시도하여 사용자의 Google ID 토큰을 가져옵니다.
다음 스니펫은 계정이 승인된 계정인지 확인합니다.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(WEB_CLIENT_ID)
.setAutoSelectEnabled(true)
.setNonce(generateSecureRandomNonce())
.build()
요청 googleIdOption 객체는 다음과 같이 구성됩니다.
이전에 승인된 계정 필터링: 이전에 앱에 로그인하는 데 사용된 승인된 계정을 가져오려면
setFilterByAuthorizedAccounts을true로 설정합니다.setFilterByAuthorizedAccounts의 기본값은true이므로 하단 시트 UI의 기본 동작은 이전에 승인된 계정만 표시하는 것입니다.서버 클라이언트 ID 설정:
setServerClientId매개변수를 설정합니다.webClientId는 기본 요건을 완료하는 동안 Google Cloud 프로젝트에서 OAuth용으로 설정한 웹 클라이언트 ID입니다.자동 로그인 사용 설정 (선택사항): 재방문 사용자를 위해 자동 로그인을 사용 설정하려면
setAutoSelectEnabled(true)및setFilterByAuthorizedAccounts(true)를 사용하세요. 앱 사용자의 경우 이전에 이미 로그인한 경우 불필요한 마찰이 제거됩니다.다음 기준이 충족되는 경우에만 자동 로그인이 가능합니다.
- 기기에 승인된 계정이 하나만 있고 이 승인된 계정이 이전에 기기에서 앱에 로그인하는 데 사용되었습니다. 기기에 승인된 계정이 여러 개 있으면 자동 로그인이 사용 중지됩니다.
- 사용자가 이전 세션에서 앱을 명시적으로 로그아웃하지 않았습니다.
- 사용자가 Google 계정 설정에서 자동 로그인을 사용 중지하지 않았습니다.
넌스 설정 (선택사항): 보안을 강화하려면 서버 측 확인을 위한 넌스를 설정합니다. 재생 공격을 방지하려면
setNonce()를 사용하여 서버 측 확인을 위한 nonce를 포함하면 됩니다. 서버 측 코드가 요청 및 응답 nonce가 동일한지 확인해야 합니다.넌스를 생성하려면 지정된 길이의 암호화적으로 강력한 무작위 넌스를 생성하고
Base64를 사용하여 인코딩하는 다음 함수와 유사한 함수를 사용합니다.
fun generateSecureRandomNonce(byteLength: Int = 32): String {
val randomBytes = ByteArray(byteLength)
SecureRandom().nextBytes(randomBytes)
return Base64.encodeToString(randomBytes, Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING)
}
로그인 요청
getCredential 메서드를 호출하여 기기에 승인된 계정이 있는지 확인합니다.
val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(googleIdOption)
.build()
coroutineScope {
try {
val result = credentialManager.getCredential(
request = request,
context = activityContext,
)
handleSignIn(result)
} catch (e: GetCredentialException) {
// Handle failures
}
}
승인된 계정이 없는 경우 로그인 요청 구성
기기에 앱의 승인된 사용자가 없으면 CredentialManager에서 NoCredentialException을 반환합니다. 이 시나리오에서는 사용자가 다른 계정을 사용하여 가입할 수 있도록 승인된 계정 필터를 사용 중지합니다.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(WEB_CLIENT_ID)
.setNonce(generateSecureRandomNonce())
.build()
그런 다음 승인된 계정에서와 마찬가지로 로그인을 요청합니다.
버튼 흐름 만들기
다음 조건에서 사용자가 Google 계정으로 로그인할 수 있도록 하려면 버튼을 사용하세요.
- 사용자가 사용자 인증 정보 관리자 하단 시트 UI를 닫았습니다.
- 기기에 Google 계정이 없습니다.
- 기기의 기존 계정에 재인증이 필요합니다.
버튼 UI 만들기
Jetpack Compose 버튼으로 이 작업을 수행할 수 있지만 Google 계정으로 로그인 브랜딩 가이드라인 페이지에서 사전 승인된 브랜드 아이콘을 사용할 수 있습니다.
로그인 흐름 만들기
GetSignInWithGoogleOption을 사용하여 Google ID 토큰을 가져오는 Google 로그인 요청을 만듭니다.
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
serverClientId = WEB_CLIENT_ID
).setNonce(generateSecureRandomNonce())
.build()
다음으로 하단 시트 UI에서와 마찬가지로 로그인을 요청합니다.
하단 시트와 버튼의 공유 로그인 함수 만들기
로그인을 처리하려면 다음 단계를 완료하세요.
- CredentialManager의
getCredential()함수를 사용합니다. 응답이 성공하면CustomCredential를 추출합니다.CustomCredential는GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL유형이어야 합니다. GoogleIdTokenCredential.createFrom()메서드를 사용하여 객체를GoogleIdTokenCredential로 변환합니다.신뢰 당사자 서버에서 사용자 인증 정보를 검증합니다.
오류를 적절하게 처리해야 합니다.
fun handleSign(result: GetCredentialResponse) {
// Handle the successfully returned credential.
val credential = result.credential
when (credential) {
is CustomCredential -> {
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
try {
// Use googleIdTokenCredential and extract the ID for server-side validation.
val googleIdTokenCredential = GoogleIdTokenCredential
.createFrom(credential.data)
} catch (e: GoogleIdTokenParsingException) {
Log.e(TAG, "Received an invalid google id token response", e)
}
} else {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential")
}
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential")
}
}
}
오류 처리
문제 해결에 나열된 오류를 검토하여 코드가 가능한 모든 오류 시나리오를 처리하는지 확인합니다.
로그아웃 처리
사용자가 앱에서 로그아웃할 수 있는 메커니즘을 제공하는 것이 중요합니다. 예를 들어 사용자가 기기에 여러 Google 계정을 보유하고 다른 계정으로 로그인하기로 결정할 수 있습니다. 예를 들어 설정 페이지에서 이를 제공할 수 있습니다.
사용자 인증 정보 제공자는 활성 사용자 인증 정보 세션을 저장하고 이를 사용하여 향후 로그인 요청의 로그인 옵션을 제한할 수 있습니다. 예를 들어 사용 가능한 다른 사용자 인증 정보보다 활성 사용자 인증 정보에 우선순위를 부여할 수 있습니다.
사용자가 앱에서 로그아웃하면 API clearCredentialState() 메서드를 호출하여 모든 사용자 인증 정보 제공업체에서 현재 사용자 인증 정보 상태를 지웁니다.
이렇게 하면 지정된 앱의 저장된 사용자 인증 정보 세션을 삭제해야 한다고 모든 사용자 인증 정보 제공업체에 알리므로 다음에 사용자에게 전체 로그인 옵션이 제공됩니다.