Android에서 전화번호로 Firebase에 인증

Firebase 인증을 사용하면 사용자의 전화로 SMS 메시지를 전송하여 로그인하는 것이 가능합니다. 사용자는 SMS 메시지에 포함된 일회용 코드를 사용하여 로그인합니다.

앱에 전화번호 로그인을 추가하는 가장 쉬운 방법은 FirebaseUI를 사용하는 것입니다. 여기에는 비밀번호 기반 및 제휴 로그인뿐만 아니라 전화번호 로그인의 과정을 구현하는 삽입형 로그인 위젯이 포함됩니다. 이 문서에서는 Firebase SDK를 사용하여 전화번호 로그인 과정을 구현하는 방법을 설명합니다.

시작하기 전에

  1. 아직 추가하지 않았다면 Android 프로젝트에 Firebase를 추가합니다.
  2. 모듈(앱 수준) Gradle 파일(일반적으로 <project>/<app-module>/build.gradle.kts 또는 <project>/<app-module>/build.gradle)에서 Firebase 인증 Android 라이브러리의 종속 항목을 추가합니다. 라이브러리 버전 관리 제어에는 Firebase Android BoM을 사용하는 것이 좋습니다.

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth-ktx")
    }
    

    Firebase Android BoM을 사용하면 앱에서 항상 호환되는 Firebase Android 라이브러리 버전만 사용합니다.

    (대안) BoM을 사용하지 않고 Firebase 라이브러리 종속 항목을 추가합니다.

    Firebase BoM을 사용하지 않도록 선택한 경우에는 종속 항목 줄에 각 Firebase 라이브러리 버전을 지정해야 합니다.

    앱에서 여러 Firebase 라이브러리를 사용하는 경우 모든 버전이 호환되도록 BoM을 사용하여 라이브러리 버전을 관리하는 것이 좋습니다.

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth-ktx:22.1.2")
    }
    

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth")
    }
    

    Firebase Android BoM을 사용하면 앱에서 항상 호환되는 Firebase Android 라이브러리 버전만 사용합니다.

    (대안) BoM을 사용하지 않고 Firebase 라이브러리 종속 항목을 추가합니다.

    Firebase BoM을 사용하지 않도록 선택한 경우에는 종속 항목 줄에 각 Firebase 라이브러리 버전을 지정해야 합니다.

    앱에서 여러 Firebase 라이브러리를 사용하는 경우 모든 버전이 호환되도록 BoM을 사용하여 라이브러리 버전을 관리하는 것이 좋습니다.

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth:22.1.2")
    }
    
  3. 아직 Firebase 프로젝트에 앱을 연결하지 않았다면 Firebase Console에서 연결합니다.
  4. Firebase Console에서 앱의 SHA-1 해시를 설정하지 않았다면 지금 설정합니다. 앱의 SHA-1 해시를 찾는 방법은 클라이언트 인증을 참조하세요.

보안 문제

전화번호만 사용하는 인증은 편리하기는 하지만, 전화번호 소유권은 사용자 간에 쉽게 이전될 수 있으므로 다른 방식보다 보안성이 떨어집니다. 또한 기기에 여러 사용자 프로필이 있는 경우 SMS 메시지를 받을 수 있는 사람이라면 누구든지 기기의 전화번호로 계정에 로그인할 수 있습니다.

앱에서 전화번호 기반 로그인을 사용하는 경우 더 안전한 로그인 방법을 함께 제공해야 하고, 전화번호 로그인을 사용하면 보안이 약화된다는 점을 사용자에게 알려야 합니다.

Firebase 프로젝트에서 전화번호 로그인 사용 설정

SMS 메시지로 사용자를 로그인 처리하려면 우선 Firebase 프로젝트에서 전화번호 로그인 방법을 사용 설정해야 합니다.

  1. Firebase Console에서 인증 섹션을 엽니다.
  2. 로그인 방법 페이지에서 전화번호 로그인 방법을 사용 설정합니다.

Firebase의 전화번호 로그인 요청 할당량은 대부분의 앱에서 불편을 겪지 않을 정도로 충분히 높습니다. 그러나 전화번호 인증으로 처리할 로그인 사용자가 매우 많다면 요금제를 업그레이드해야 할 수도 있습니다. 자세한 내용은 가격 책정 페이지를 참조하세요.

앱 인증 사용 설정

전화번호 인증을 사용하려면 전화번호 로그인 요청이 앱에서 발생한 것인지 Firebase에서 확인할 수 있어야 합니다. Firebase 인증은 다음 세 가지 방법으로 이를 수행합니다.

  • Play Integrity API: 사용자가 Google Play 서비스가 설치된 기기를 보유하고 있고 Firebase 인증에서 Play Integrity API로 기기가 합법적임을 확인할 수 있는 경우 전화번호 로그인을 진행할 수 있습니다. Play Integrity API는 사용자 프로젝트가 아닌 Google 소유 프로젝트에서 Firebase 인증을 통해 사용 설정됩니다. 이는 사용자 프로젝트의 Play Integrity API 할당량에 영향을 주지 않습니다. Play Integrity 지원은 인증 SDK v21.2.0 이상(Firebase BoM v31.4.0 이상)에서 제공됩니다.

    Play Integrity를 사용하려면 아직 앱의 SHA-256 디지털 지문을 지정하지 않은 경우, Firebase Console의 프로젝트 설정에서 지정합니다. 앱의 SHA-256 디지털 지문을 얻는 방법에 대한 자세한 내용은 클라이언트 인증을 참조하세요.

  • reCAPTCHA 인증: 사용자의 기기에 Google Play 서비스가 설치되지 않았을 때와 같이 Play Integrity를 사용할 수 없는 경우 Firebase 인증에서는 reCAPTCHA 인증을 사용하여 전화 로그인 과정을 완료합니다. 사용자가 문제를 풀지 않아도 reCAPTCHA 테스트를 완료할 수 있는 경우도 많습니다. 이 과정을 진행하려면 SHA-1이 애플리케이션과 연결되어야 합니다. 또한 API 키가 제한되지 않거나 PROJECT_ID.firebaseapp.com의 허용 목록에 있어야 합니다.

    reCAPTCHA가 트리거되는 몇 가지 시나리오는 다음과 같습니다.

    • 최종 사용자의 기기에 Google Play 서비스가 설치되어 있지 않은 경우
    • 앱이 Google Play 스토어를 통해 배포되지 않은 경우(인증 SDK v21.2.0 이상)
    • 획득한 SafetyNet 토큰이 유효하지 않은 경우(인증 SDK 버전 v21.2.0 미만)

    SafetyNet 또는 Play Integrity가 앱 인증에 사용되는 경우 SMS 템플릿의 %APP_NAME% 필드가 Google Play 스토어에서 결정한 앱 이름으로 채워집니다. reCAPTCHA가 트리거되는 시나리오에서는 %APP_NAME%PROJECT_ID.firebaseapp.com으로 채워집니다.

forceRecaptchaFlowForTesting을 사용하여 reCAPTCHA 인증 과정을 강제 적용할 수 있습니다. setAppVerificationDisabledForTesting을 사용하여 앱 인증(가상 전화번호를 사용하는 경우)을 사용 중지할 수 있습니다.

문제 해결

  • 앱 인증에 reCAPTCHA를 사용할 때 '초기 상태 누락' 오류가 발생함

    이는 reCAPTCHA 흐름이 성공적으로 완료되었지만 사용자를 다시 네이티브 애플리케이션으로 리디렉션하지 않을 때 발생할 수 있습니다. 이 경우 사용자는 대체 URL(PROJECT_ID.firebaseapp.com/__/auth/handler)로 리디렉션됩니다. Firefox 브라우저에서는 네이티브 앱 링크를 여는 기능이 기본적으로 사용 중지되어 있습니다. Firefox에 위 오류가 표시되면 네이티브 앱에서 링크를 열도록 Android용 Firefox 설정하기의 단계에 따라 앱 링크를 열 수 있도록 합니다.

사용자 휴대전화로 인증 코드 전송

전화번호 로그인을 시작하려면 사용자에게 전화번호 입력을 요청하는 인터페이스를 제시합니다. 지역에 따라 현지 법규가 다르지만 일반적으로는 사용자가 제반 상황을 미리 알 수 있도록 전화 로그인을 사용하면 인증용 SMS 메시지가 발송되고 일반 요금이 부과될 수 있다는 점을 알려야 합니다.

그런 다음 PhoneAuthProvider.verifyPhoneNumber 메서드에 전화번호를 전달하여 Firebase가 사용자의 전화번호를 확인하도록 요청합니다. 예를 들면 다음과 같습니다.

Kotlin+KTX

val options = PhoneAuthOptions.newBuilder(auth)
    .setPhoneNumber(phoneNumber) // Phone number to verify
    .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
    .setActivity(this) // Activity (for callback binding)
    .setCallbacks(callbacks) // OnVerificationStateChangedCallbacks
    .build()
PhoneAuthProvider.verifyPhoneNumber(options)

Java

PhoneAuthOptions options = 
  PhoneAuthOptions.newBuilder(mAuth) 
      .setPhoneNumber(phoneNumber)       // Phone number to verify
      .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
      .setActivity(this)                 // (optional) Activity for callback binding
      // If no activity is passed, reCAPTCHA verification can not be used.
      .setCallbacks(mCallbacks)          // OnVerificationStateChangedCallbacks
      .build();
  PhoneAuthProvider.verifyPhoneNumber(options);     

verifyPhoneNumber 메서드는 재진입할 수 있습니다. 즉, 활동의 onStart 메서드에서와 같이 verifyPhoneNumber 메서드를 여러 번 호출해도 원래 요청이 시간 초과되지 않았으면 SMS를 재차 보내지 않습니다.

사용자가 로그인하기 전에 앱이 종료되면(예: 사용자가 SMS 앱을 사용하는 중) 이 동작을 사용하여 전화번호 로그인 절차를 재개할 수 있습니다. verifyPhoneNumber를 호출한 후 인증이 진행 중임을 나타내는 플래그를 설정합니다. 그런 다음 액티비티의 onSaveInstanceState 메서드에서 플래그를 저장하고 onRestoreInstanceState에서 플래그를 복원합니다. 마지막으로 액티비티의 onStart 메서드에서 인증이 진행 중인지 확인하고 진행 중이라면 verifyPhoneNumber를 다시 호출합니다. 인증 완료 또는 실패 시에는 플래그를 해제해야 합니다(인증 콜백 참조).

화면 회전 및 액티비티가 재시작되는 기타 상황을 손쉽게 처리하려면 verifyPhoneNumber 메서드에 액티비티를 전달합니다. 액티비티가 중지되면 콜백이 자동으로 분리되므로 콜백 메서드에 UI 전환 코드를 자유롭게 작성할 수 있습니다.

Auth 인스턴스의 setLanguageCode 메서드를 통해 auth 언어를 지정하는 방법으로 Firebase에서 보내는 SMS 메시지를 현지화할 수도 있습니다.

Kotlin+KTX

auth.setLanguageCode("fr")
// To apply the default app language instead of explicitly setting it.
// auth.useAppLanguage()

Java

auth.setLanguageCode("fr");
// To apply the default app language instead of explicitly setting it.
// auth.useAppLanguage();

PhoneAuthProvider.verifyPhoneNumber를 호출할 때는 요청 결과를 처리하는 콜백 함수의 구현을 포함하는 OnVerificationStateChangedCallbacks의 인스턴스도 제공해야 합니다. 예를 들면 다음과 같습니다.

Kotlin+KTX

callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

    override fun onVerificationCompleted(credential: PhoneAuthCredential) {
        // This callback will be invoked in two situations:
        // 1 - Instant verification. In some cases the phone number can be instantly
        //     verified without needing to send or enter a verification code.
        // 2 - Auto-retrieval. On some devices Google Play services can automatically
        //     detect the incoming verification SMS and perform verification without
        //     user action.
        Log.d(TAG, "onVerificationCompleted:$credential")
        signInWithPhoneAuthCredential(credential)
    }

    override fun onVerificationFailed(e: FirebaseException) {
        // This callback is invoked in an invalid request for verification is made,
        // for instance if the the phone number format is not valid.
        Log.w(TAG, "onVerificationFailed", e)

        if (e is FirebaseAuthInvalidCredentialsException) {
            // Invalid request
        } else if (e is FirebaseTooManyRequestsException) {
            // The SMS quota for the project has been exceeded
        } else if (e is FirebaseAuthMissingActivityForRecaptchaException) {
            // reCAPTCHA verification attempted with null Activity
        }

        // Show a message and update the UI
    }

    override fun onCodeSent(
        verificationId: String,
        token: PhoneAuthProvider.ForceResendingToken,
    ) {
        // The SMS verification code has been sent to the provided phone number, we
        // now need to ask the user to enter the code and then construct a credential
        // by combining the code with a verification ID.
        Log.d(TAG, "onCodeSent:$verificationId")

        // Save verification ID and resending token so we can use them later
        storedVerificationId = verificationId
        resendToken = token
    }
}

Java

mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

    @Override
    public void onVerificationCompleted(@NonNull PhoneAuthCredential credential) {
        // This callback will be invoked in two situations:
        // 1 - Instant verification. In some cases the phone number can be instantly
        //     verified without needing to send or enter a verification code.
        // 2 - Auto-retrieval. On some devices Google Play services can automatically
        //     detect the incoming verification SMS and perform verification without
        //     user action.
        Log.d(TAG, "onVerificationCompleted:" + credential);

        signInWithPhoneAuthCredential(credential);
    }

    @Override
    public void onVerificationFailed(@NonNull FirebaseException e) {
        // This callback is invoked in an invalid request for verification is made,
        // for instance if the the phone number format is not valid.
        Log.w(TAG, "onVerificationFailed", e);

        if (e instanceof FirebaseAuthInvalidCredentialsException) {
            // Invalid request
        } else if (e instanceof FirebaseTooManyRequestsException) {
            // The SMS quota for the project has been exceeded
        } else if (e instanceof FirebaseAuthMissingActivityForRecaptchaException) {
            // reCAPTCHA verification attempted with null Activity
        }

        // Show a message and update the UI
    }

    @Override
    public void onCodeSent(@NonNull String verificationId,
                           @NonNull PhoneAuthProvider.ForceResendingToken token) {
        // The SMS verification code has been sent to the provided phone number, we
        // now need to ask the user to enter the code and then construct a credential
        // by combining the code with a verification ID.
        Log.d(TAG, "onCodeSent:" + verificationId);

        // Save verification ID and resending token so we can use them later
        mVerificationId = verificationId;
        mResendToken = token;
    }
};

인증 콜백

대부분의 앱에서는 onVerificationCompleted, onVerificationFailed, onCodeSent 콜백을 구현합니다. 앱의 요구사항에 따라 onCodeAutoRetrievalTimeOut을 구현할 수도 있습니다.

onVerificationCompleted(PhoneAuthCredential)

이 메서드는 2가지 상황에서 호출됩니다.

  • 즉시 인증: 경우에 따라 인증 코드를 보내거나 입력하지 않고 전화번호를 즉시 인증할 수 있습니다.
  • 자동 검색: 일부 기기에서는 수신되는 인증 SMS를 Google Play 서비스가 자동으로 감지하여 사용자의 개입 없이 인증을 수행할 수 있습니다. 일부 이동통신사에서는 이 기능을 제공하지 않을 수 있습니다. SMS 메시지 끝에 11자리 해시를 포함하는 SMS Retriever API를 사용합니다.
두 경우 모두 사용자의 전화번호가 정상적으로 인증된 것이므로 콜백에 전달된 PhoneAuthCredential 객체를 사용하여 사용자를 로그인 처리할 수 있습니다.

onVerificationFailed(FirebaseException)

이 메서드는 요청에 잘못된 전화번호 또는 인증 코드가 지정된 경우와 같이 잘못된 인증 요청에 대한 응답으로 호출됩니다.

onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken)

(선택사항) 이 메서드는 제공된 전화번호로 인증 코드가 SMS를 통해 전송된 후에 호출됩니다.

이 메서드가 호출되면 대부분의 앱은 사용자에게 SMS 메시지로 받은 인증 코드를 입력하라는 UI를 표시합니다. 이와 동시에 백그라운드에서 자동 인증이 진행될 수도 있습니다. 사용자가 인증 코드를 입력하면 인증 코드와 이 메서드에 전달된 인증 ID를 사용하여 PhoneAuthCredential 객체를 만들고 이 객체로 사용자를 로그인 처리할 수 있습니다. 앱에 따라서는 onCodeAutoRetrievalTimeOut이 호출될 때까지 기다린 후에 인증 코드 UI를 표시할 수도 있지만, 이 방법은 권장되지 않습니다.

onCodeAutoRetrievalTimeOut(String verificationId)

(선택사항) 이 메서드는 onVerificationCompleted가 아직 트리거되기 전에 verifyPhoneNumber에 지정된 제한 시간이 경과된 후에 호출됩니다. 기기에 SIM 카드가 없으면 SMS 자동 검색이 불가능하므로 이 메서드가 즉시 호출됩니다.

앱에 따라서는 우선 사용자 입력을 차단했다가 자동 인증 제한시간이 경과한 후에 사용자에게 SMS 메시지로 받은 인증 코드를 입력하라는 UI를 표시하지만, 이 방법은 권장되지 않습니다.

PhoneAuthCredential 객체 만들기

사용자가 Firebase에서 사용자의 전화로 보낸 인증 코드를 입력하면 인증 코드 및 onCodeSent 또는 onCodeAutoRetrievalTimeOut 콜백에 전달된 인증 ID를 사용하여 PhoneAuthCredential 객체를 만듭니다. onVerificationCompleted가 호출되면 PhoneAuthCredential 객체를 직접 가져오게 되므로 이 단계를 건너뛸 수 있습니다.

PhoneAuthCredential 객체를 만들려면 다음과 같이 PhoneAuthProvider.getCredential을 호출합니다.

Kotlin+KTX

val credential = PhoneAuthProvider.getCredential(verificationId!!, code)

Java

PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);

사용자 로그인

onVerificationCompleted 콜백 또는 PhoneAuthProvider.getCredential 호출을 통해 PhoneAuthCredential 객체를 가져온 후 FirebaseAuth.signInWithCredentialPhoneAuthCredential 객체를 전달하여 로그인 과정을 완료합니다.

Kotlin+KTX

private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
    auth.signInWithCredential(credential)
        .addOnCompleteListener(this) { task ->
            if (task.isSuccessful) {
                // Sign in success, update UI with the signed-in user's information
                Log.d(TAG, "signInWithCredential:success")

                val user = task.result?.user
            } else {
                // Sign in failed, display a message and update the UI
                Log.w(TAG, "signInWithCredential:failure", task.exception)
                if (task.exception is FirebaseAuthInvalidCredentialsException) {
                    // The verification code entered was invalid
                }
                // Update UI
            }
        }
}

Java

private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithCredential:success");

                        FirebaseUser user = task.getResult().getUser();
                        // Update UI
                    } else {
                        // Sign in failed, display a message and update the UI
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid
                        }
                    }
                }
            });
}

가상 전화번호로 테스트

Firebase Console을 통해 개발용 가상 전화번호를 설정할 수 있습니다. 가상 전화번호로 테스트하면 다음과 같은 이점이 있습니다.

  • 사용 할당량을 소비하지 않고 전화번호 인증을 테스트할 수 있습니다.
  • 실제 SMS 메시지를 보내지 않고 전화번호 인증을 테스트할 수 있습니다.
  • 제한 없이 동일한 전화번호로 연속 테스트를 실행할 수 있습니다. 앱 스토어 검토 절차 중에 검토자가 동일한 전화번호를 테스트에 사용하게 될 경우 번호가 거부될 위험이 최소화됩니다.
  • 별도의 노력 없이도 개발 환경에서 쉽게 테스트할 수 있습니다. 예를 들어 Google Play 서비스 없이 iOS 시뮬레이터 또는 Android Emulator에서 개발할 수 있습니다.
  • 프로덕션 환경에서 실제 전화번호에 일반적으로 적용되는 보안 검사에 의해 차단되지 않고 통합 테스트를 작성할 수 있습니다.

가상 전화번호는 다음 요구사항을 충족해야 합니다.

  1. 실제로 존재하지 않는 가상의 전화번호여야 합니다. Firebase 인증에서는 실제 사용자가 사용하는 기존 전화번호를 테스트 전화번호로 설정할 수 없습니다. 전화번호를 만드는 방법 중 하나는 555로 시작하는 번호(예: +1 650-555-3434)를 미국 테스트 전화번호로 사용하는 것입니다.
  2. 길이 및 기타 조건에 맞게 전화번호 형식을 올바르게 지정해야 합니다. 테스트 전화번호도 실제 사용자의 전화번호와 동일한 유효성 검사를 거칩니다.
  3. 개발용으로 최대 10개의 전화번호를 추가할 수 있습니다.
  4. 다른 사람이 추측하기 어려운 테스트 전화번호와 코드를 사용하고 자주 변경합니다.

가상 전화번호 및 인증 코드 생성

  1. Firebase Console에서 인증 섹션을 엽니다.
  2. 전화 제공업체를 아직 사용 설정하지 않은 경우 로그인 방법 탭에서 사용 설정합니다.
  3. 테스트용 전화번호 아코디언 메뉴를 엽니다.
  4. 테스트할 전화번호(예: +1 650-555-3434)를 입력합니다.
  5. 해당 번호에 사용할 6자리 인증 코드(예: 654321)를 입력합니다.
  6. 번호를 추가합니다. 필요한 경우 해당 행 위에 마우스를 가져가서 휴지통 아이콘을 클릭하면 전화번호와 코드를 삭제할 수 있습니다.

직접 테스트

애플리케이션에서 직접 가상 전화번호를 사용할 수 있습니다. 따라서 할당량 문제나 제한 없이 개발 단계 중에 직접 테스트를 수행할 수 있습니다. 또한 Google Play 서비스를 설치하지 않고 iOS 시뮬레이터 또는 Android 에뮬레이터에서 바로 테스트할 수 있습니다.

가상 전화번호를 입력하고 인증 코드를 보내도 실제 SMS 메시지가 전송되지 않습니다. 그 대신 이전에 구성한 인증 코드를 입력하여 로그인을 완료해야 합니다.

로그인이 완료되면 해당 전화번호로 Firebase 사용자가 생성됩니다. 사용자는 실제 전화번호 사용자와 동일한 행동과 속성을 가지며 동일한 방식으로 실시간 데이터베이스, Cloud Firestore 및 기타 서비스에 액세스할 수 있습니다. 이 절차 중에 발급된 ID 토큰에는 실제 전화번호 사용자와 같은 서명이 있습니다.

액세스 권한을 좀 더 제한하고 싶은 경우에 사용할 수 있는 다른 방법은 이러한 사용자에게 커스텀 클레임을 통해 테스트 역할을 설정하여 허위 사용자로 구분하는 것입니다.

테스트용 reCAPTCHA 흐름을 수동으로 트리거하려면 forceRecaptchaFlowForTesting() 메서드를 사용하세요.

// Force reCAPTCHA flow
FirebaseAuth.getInstance().getFirebaseAuthSettings().forceRecaptchaFlowForTesting();

통합 테스트

Firebase 인증은 직접 테스트 외에도 전화 인증 테스트용 통합 테스트를 작성할 수 있는 API를 제공합니다. 이러한 API는 웹에서 reCAPTCHA 요구사항을, iOS에서 백그라운드 푸시 알림을 중지하여 앱 인증을 사용 중지합니다. 따라서 이러한 흐름에서 테스트를 자동화하고 더 쉽게 구현할 수 있습니다. 또한 Android에서 즉시 인증 흐름을 테스트하는 기능도 제공합니다.

Android에서는 signInWithPhoneNumber 호출 전에 setAppVerificationDisabledForTesting()을 호출합니다. 이렇게 하면 앱 인증이 자동으로 사용 중지되어 수동으로 해결하지 않아도 전화번호를 전달할 수 있습니다. Play Integrity 및 reCAPTCHA가 사용 중지되어 있더라도 실제 전화번호를 사용하면 로그인에 실패하게 됩니다. 이 API로는 가상 전화번호만 사용할 수 있습니다.

// Turn off phone auth app verification.
FirebaseAuth.getInstance().getFirebaseAuthSettings()
   .setAppVerificationDisabledForTesting();

가상 번호로 verifyPhoneNumber를 호출하여 onCodeSent 콜백이 트리거되면 해당 인증 코드를 입력해야 합니다. 그러면 Android 에뮬레이터에서 테스트할 수 있습니다.

Java

String phoneNum = "+16505554567";
String testVerificationCode = "123456";

// Whenever verification is triggered with the whitelisted number,
// provided it is not set for auto-retrieval, onCodeSent will be triggered.
FirebaseAuth auth = FirebaseAuth.getInstance();
PhoneAuthOptions options = PhoneAuthOptions.newBuilder(auth)
        .setPhoneNumber(phoneNum)
        .setTimeout(60L, TimeUnit.SECONDS)
        .setActivity(this)
        .setCallbacks(new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onCodeSent(@NonNull String verificationId,
                                   @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
                // Save the verification id somewhere
                // ...

                // The corresponding whitelisted code above should be used to complete sign-in.
                MainActivity.this.enableUserManuallyInputCode();
            }

            @Override
            public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
                // Sign in with the credential
                // ...
            }

            @Override
            public void onVerificationFailed(@NonNull FirebaseException e) {
                // ...
            }
        })
        .build();
PhoneAuthProvider.verifyPhoneNumber(options);

Kotlin+KTX

val phoneNum = "+16505554567"
val testVerificationCode = "123456"

// Whenever verification is triggered with the whitelisted number,
// provided it is not set for auto-retrieval, onCodeSent will be triggered.
val options = PhoneAuthOptions.newBuilder(Firebase.auth)
    .setPhoneNumber(phoneNum)
    .setTimeout(30L, TimeUnit.SECONDS)
    .setActivity(this)
    .setCallbacks(object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        override fun onCodeSent(
            verificationId: String,
            forceResendingToken: PhoneAuthProvider.ForceResendingToken,
        ) {
            // Save the verification id somewhere
            // ...

            // The corresponding whitelisted code above should be used to complete sign-in.
            this@MainActivity.enableUserManuallyInputCode()
        }

        override fun onVerificationCompleted(phoneAuthCredential: PhoneAuthCredential) {
            // Sign in with the credential
            // ...
        }

        override fun onVerificationFailed(e: FirebaseException) {
            // ...
        }
    })
    .build()
PhoneAuthProvider.verifyPhoneNumber(options)

또한 setAutoRetrievedSmsCodeForPhoneNumber를 호출하여 자동 검색을 위한 가상 번호 및 해당 인증 코드를 설정하면 Android에서 자동 검색 과정을 테스트할 수 있습니다.

verifyPhoneNumber를 호출하면 바로 PhoneAuthCredential을 통해 onVerificationCompleted가 트리거됩니다. 이 방식은 가상 전화번호에서만 작동합니다.

Google Play 스토어에 애플리케이션을 게시할 때 이 기능이 사용 중지되었는지, 가상 전화번호가 앱에 하드코딩되어 있지 않은지 확인해야 합니다.

Java

// The test phone number and code should be whitelisted in the console.
String phoneNumber = "+16505554567";
String smsCode = "123456";

FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
FirebaseAuthSettings firebaseAuthSettings = firebaseAuth.getFirebaseAuthSettings();

// Configure faking the auto-retrieval with the whitelisted numbers.
firebaseAuthSettings.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode);

PhoneAuthOptions options = PhoneAuthOptions.newBuilder(firebaseAuth)
        .setPhoneNumber(phoneNumber)
        .setTimeout(60L, TimeUnit.SECONDS)
        .setActivity(this)
        .setCallbacks(new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onVerificationCompleted(@NonNull PhoneAuthCredential credential) {
                // Instant verification is applied and a credential is directly returned.
                // ...
            }

            // ...
        })
        .build();
PhoneAuthProvider.verifyPhoneNumber(options);

Kotlin+KTX

// The test phone number and code should be whitelisted in the console.
val phoneNumber = "+16505554567"
val smsCode = "123456"

val firebaseAuth = Firebase.auth
val firebaseAuthSettings = firebaseAuth.firebaseAuthSettings

// Configure faking the auto-retrieval with the whitelisted numbers.
firebaseAuthSettings.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode)

val options = PhoneAuthOptions.newBuilder(firebaseAuth)
    .setPhoneNumber(phoneNumber)
    .setTimeout(60L, TimeUnit.SECONDS)
    .setActivity(this)
    .setCallbacks(object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        override fun onVerificationCompleted(credential: PhoneAuthCredential) {
            // Instant verification is applied and a credential is directly returned.
            // ...
        }

        // ...
    })
    .build()
PhoneAuthProvider.verifyPhoneNumber(options)

다음 단계

사용자가 처음으로 로그인하면 신규 사용자 계정이 생성되고 사용자가 로그인할 때 사용한 사용자 인증 정보(사용자 이름과 비밀번호, 전화번호 또는 인증 제공업체 정보)에 연결됩니다. 이 신규 계정은 Firebase 프로젝트의 일부로 저장되며 사용자의 로그인 방법에 관계없이 프로젝트 내 모든 앱에서 사용자를 식별하는 데 사용될 수 있습니다.

  • 앱의 FirebaseUser 객체에서 사용자의 기본 프로필 정보를 가져올 수 있습니다. 사용자 관리를 참조하세요.

  • Firebase 실시간 데이터베이스와 Cloud Storage 보안 규칙auth 변수에서 로그인한 사용자의 고유 사용자 ID를 가져온 후 이 ID를 통해 사용자가 액세스할 수 있는 데이터를 관리할 수 있습니다.

인증 제공업체의 사용자 인증 정보를 기존 사용자 계정에 연결하면 사용자가 여러 인증 제공업체를 통해 앱에 로그인할 수 있습니다.

사용자를 로그아웃시키려면 signOut을 호출합니다.

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();