스마트웹앱콘텐츠전문가/안드로이드

sms 인증(with파이어베이스)

9D4U 2024. 8. 29. 11:31
728x90
반응형

파이어베이스를 활용하여 

전화번호 sms 인증을 하려고 한다면

 

사전에 파이어베이스에 

프로젝트 생성 및 설정이 

되어 있어야 합니다.

 

※ 파이어베이스 인증 부분에서 '전화번호'를 추가하여야 합니다.

 

 

 

 

해당 포스팅에서는

사전 과정을 마친 이후에

진행을 합니다.

 

 

 

 

 

 

○ 안드로이드 환경 : SDK(안드로이드 API 21 이상), JDK(JDK 11이상), Gradle 빌드

 

 

 

 

 

1. 환경 설정

 

1-1. 파이어베이스 프로젝트에서 google-services.json 다운로드 받아

       해당 프로젝트 루트 디렉터리에 추가.

 

 

 

1-2. 파이어베이스(Firebase) SDK 추가 

 

프로젝트 수준의 build.gradle 파일에 플러그인을 종속 항목으로 추가

plugins {
  // ...

  // Add the dependency for the Google services Gradle plugin
  id 'com.google.gms.google-services' version '4.4.2' apply false

}

 

 

모듈(앱 수준) build.gradle 파일에서 google-services 플러그인과 앱에서 사용할 Firebase SDK를 모두 추가

plugins {
  id 'com.android.application'

  // Add the Google services Gradle plugin
  id 'com.google.gms.google-services'

  ...
}

dependencies {
  // Import the Firebase BoM
  implementation platform('com.google.firebase:firebase-bom:33.2.0')


  // TODO: Add the dependencies for Firebase products you want to use
  // When using the BoM, don't specify versions in Firebase dependencies
  // https://firebase.google.com/docs/android/setup#available-libraries
  
  // 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:16.0.4")

	// Also add the dependency for the Google Play services library and specify its version	
	implementation("com.google.android.gms:play-services-auth:20.1.0")
	

}

 

 

그리고

디펜던시로 하나더 추가해야 해주어야 합니다.

(이유는 포스팅을 쭈욱 읽어나가다 보면 아시게 됩니다.)

implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.30'

 

 

 

gradle sync 또는 빌드를 해주어 오류가 나는 지 확인해봅시다.

 

참고) 파이어베이스 SDK가 google-services.json 구성 값에 액세스할 수 있도록 하려면 구글 서비스 gradle 플러그인 필요.

 

 

 

2. 인증 로직 : 

 

파이어베이스를 사용하여 인증된 사용자만 접속(로그인)할 수 있는 동작을 구현해보도록 하겠습니다.

절차) 전화번호 입력 -> 인증코드 전송 -> 인증코드 입력 -> 로그인

 

※로그인 후, 사용자 정보를 가져오는 것도 포함

 

 

 

2-1. 레이아웃 파일 작성

 

간단하게

 

전화번호 입력, 인증코드 입력

인증코드 전송 버튼, 로그인 버튼 생성

 

<EditText
        android:id="@+id/phoneNumber"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"

        android:hint="input your phone number"
        android:textSize="70px"
        android:inputType="phone"
        android:textAlignment="center"
        />

    <Button
        android:id="@+id/phoneAuthBtn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:text="인증번호"
        />

    <EditText
        android:id="@+id/authNumber"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"

        android:hint="input your auth number"
        android:textSize="70px"
        android:inputType="phone"
        android:textAlignment="center"
        />

    <Button
        android:id="@+id/phoneLoginBtn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:text="로그인"
        />

 

 

 

 

2-2. 액티비티 파일에 텍스트 인풋, 버튼에 대한 로직 추가 : 

 

 

 

반응형

 

 

 

 

private String verificationId;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_phone);

        EditText phoneNumber = findViewById(R.id.phoneNumber);
        EditText authNumber = findViewById(R.id.authNumber);

        Button authNumberBtn = findViewById(R.id.phoneAuthBtn);
        Button loginBtn = findViewById(R.id.phoneLoginBtn);



        authNumberBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String str = phoneNumber.getText().toString();
                Log.d("PhoneNumber", str);
                sendAuthCode(str);

            }
        });

        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String code = authNumber.getText().toString();

                verifyAuthCode(code);
            }
        });

    }


    //인증번호 요청
    private void sendAuthCode(String phoneNumber) {

        Log.d("PhoneNumber sendAuthCode", phoneNumber); //010-xxxx-xxxx

        //phoneNumber trans e.164 format

        String str_parseNumber;
        try {
            PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
            Phonenumber.PhoneNumber parseNumber = phoneNumberUtil.parse(phoneNumber, "KR");
            str_parseNumber = phoneNumberUtil.format(parseNumber, PhoneNumberUtil.PhoneNumberFormat.E164);

            Log.d("PhoneNumber trans", str_parseNumber); // +821012345678

        } catch (NumberParseException e) {
            Log.d("PhoneNumber trans error", e.getMessage()); 
            throw new RuntimeException(e);
        }


        PhoneAuthOptions options = PhoneAuthOptions
                .newBuilder(FirebaseAuth.getInstance())                
                .setPhoneNumber(str_parseNumber) //e.164
                .setTimeout(60L, TimeUnit.SECONDS)
                .setActivity(this)
                .setCallbacks(phoneCallback)
                .build();

        PhoneAuthProvider.verifyPhoneNumber(options);

    }


    //인증번호 확인
    private void verifyAuthCode(String code){

        Log.d("PhoneNumber verifyAuthCode", code);

        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
        
        //로그인
        signIn(credential);
    }

    //콜백
    private PhoneAuthProvider.OnVerificationStateChangedCallbacks phoneCallback =
            new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
                @Override
                public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
                    String code = phoneAuthCredential.getSmsCode();
                    if(code != null){
                        Log.d("PhoneNumber verification completed", code);
                        verifyAuthCode(code);
                    }
                }

                @Override
                public void onVerificationFailed(@NonNull FirebaseException e) {
                    Log.d("PhoneNumber verification failed", e.getMessage());
                    Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
                }

                @Override
                public void onCodeSent(@NonNull String s, @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
                    super.onCodeSent(s, forceResendingToken);
                    verificationId = s;
                    Log.d("PhoneNumber onCodeSent", s + "/" + forceResendingToken.toString());
                }

                @Override
                public void onCodeAutoRetrievalTimeOut(@NonNull String s) {                    
                    super.onCodeAutoRetrievalTimeOut(s);
                }

            };

    
    private void signIn(PhoneAuthCredential credential){

        FirebaseAuth.getInstance()
                .signInWithCredential(credential)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {                                                

                        if (task.isSuccessful()) {
                            FirebaseUser user = task.getResult().getUser();

                            Log.d("PhoneNumber FirebaseUser", user.getPhoneNumber());                            

                            finish();
                        } else {
                            Toast.makeText(getApplicationContext(), task.getException().getMessage(), Toast.LENGTH_LONG).show();
                        }
                    }
                });
    }

 

https://firebase.google.com/docs/auth/android/phone-auth?hl=ko&authuser=0&_gl=1*1y52x1n*_ga*OTAxMDk1OTIwLjE3MjQ4OTAyNjA.*_ga_CW55HF8NVT*MTcyNDg5NTA3Ny4zLjEuMTcyNDg5NTA4My41NC4wLjA.

 

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

Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 Android에서 전화번호로 Firebase에 인증 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분

firebase.google.com

 

 

 

2-3. 입력한 전화번호로 인증코드 전송

PhoneAuthOptions options = PhoneAuthOptions
                .newBuilder(FirebaseAuth.getInstance())                
                .setPhoneNumber(str_parseNumber) //Phone number to verify ※e.164
                .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(phoneCallback) // OnVerificationStateChangedCallbacks
                .build();

PhoneAuthProvider.verifyPhoneNumber(options);

 

 

※ 파이어베이스 연동 시, 전화번호 형식은 E.164로 보내주어야 합니다.

(str_parseNumber 변수 확인)

PhoneAuthOptions options = PhoneAuthOptions
                .newBuilder(FirebaseAuth.getInstance())                
                .setPhoneNumber(str_parseNumber) //e.164
                .setTimeout(60L, TimeUnit.SECONDS)
                .setActivity(this)
                .setCallbacks(phoneCallback)
                .build();

 

앞에서 그래들 디펜던시에 'libphonenumber'을 추가한 이유가 바로 이것 때문입니다.

해당 라이브러리를 사용하면 

흔히 사용하는 전화번호(010-XXXX-XXXX) 형식을

파이어베이스가 요구하는 E.164형식(+8210XXXXXXXX)으로 간단하게 변환 가능합니다.

 

 

▷ E.164형식에 대해 알아보기

 

 

3. 인증 번호 확인 및 로그인 :

    로그인 버튼을 누르게 되면 인증 번호 검증 후에 로그인이 진행되며,

    이후 사용자 프로필 정보를 조회합니다.

 

//인증번호 확인
private void verifyAuthCode(String code){

    Log.d("PhoneNumber verifyAuthCode", code);

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

    //로그인
    signIn(credential);
}
    
    
    

private void signIn(PhoneAuthCredential credential){

    FirebaseAuth.getInstance()
            .signInWithCredential(credential)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {                                    

                    if (task.isSuccessful()) {
                        FirebaseUser user = task.getResult().getUser();

                        Log.d("PhoneNumber FirebaseUser", user.getPhoneNumber());
                        Log.d("PhoneNumber FirebaseUser", String.valueOf(user));

                        finish();
                    } else {
                        Toast.makeText(getApplicationContext(), task.getException().getMessage(), Toast.LENGTH_LONG).show();
                    }
                }
            });
}

 

 

※ verificationId : 해당 변수를 기준으로 파이어베이스 인증을 함.

 

 

 

 

4.  사용자 정보 가져오기 : 로그인한 사용자의 프로필 정보를 가져올 수 있습니다.

FirebaseAuth.getInstance()
                .signInWithCredential(credential)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {                                                

                        if (task.isSuccessful()) {
                        	//파이어베이스 사용자 객체를 가지고 옴
                            FirebaseUser user = task.getResult().getUser();

                            Log.d("PhoneNumber FirebaseUser", user.getPhoneNumber());                            

                            finish();
                        } else {
                            Toast.makeText(getApplicationContext(), task.getException().getMessage(), Toast.LENGTH_LONG).show();
                        }
                    }
                });

 

 

 

 

5. 구현동작 확인.

 

 

전화번호 및 인증번호 입력 창

 

 

전화번호 입력 후, 인증번호 클릭하면

reCAPTCHA verification

(파이어베이스 전화번호 인증 장점 : 
로직 진행 과정에서 로봇 체크를 해줌)

 

 

 

task.isSuccessful() //true
user.getPhoneNumber()   //+821122223333

 

로그인 성공하면 다음과 같은 사용자 정보 조회가 됩니다.

 

 

참고)

 

○ 인증이 안 된 경우는 다음과 같은 처리가 됩니다.

 

 

○ 전화번호 형식이 E.164가 아닌 경우 
다음과 같이 오류 처리됩니다.

 

 

 

 

 

2024.08.27 - [스마트웹앱콘텐츠전문가/안드로이드] - 페이스북 로그인 연동

 

페이스북 로그인 연동

페이스북 로그인 연동을 하기 위해서는 사전에 페이스북 개발자 센터에서 애플리케이션 등록을(https://developers.facebook.com/?locale=ko_KR) 먼저 해주어야 합니다. (사전 등록 요약) 키 해시, 패키지

9d4u.tistory.com

 

2024.08.27 - [스마트웹앱콘텐츠전문가/안드로이드] - 카카오 로그인 연동

 

카카오 로그인 연동

카카오 로그인 연동을 하기 위해서는 사전에 카카오 개발자 센터에서 애플리케이션 등록을 먼저 해주어야 합니다. (사전 등록 요약) 패키지명, 마켓URL, 키해시     해당 포스팅은 애플리케

9d4u.tistory.com

 

 

2024.08.27 - [스마트웹앱콘텐츠전문가/안드로이드] - 네이버 로그인 연동(네아로)

 

네이버 로그인 연동(네아로)

네이버 로그인 연동을 하기 위해서는 사전에 네이버 개발자 센터에서 애플리케이션 등록을 먼저 해주어야 합니다. (사전 등록 요약) 다운로드URL, 안드로이드 앱 패키지 이름 입력      해

9d4u.tistory.com

 

2024.08.28 - [스마트웹앱콘텐츠전문가/안드로이드] - 구글 로그인 연동(with 파이어베이스)

 

구글 로그인 연동(with 파이어베이스)

구글 로그인 연동을 하려면사전에 파이어베이스에 프로젝트 생성 및 설정이 되어 있어야 합니다.  해당 포스팅에서는사전 과정을 마친 이후에진행을 합니다.      ○ 안드로이드 환경 : SD

9d4u.tistory.com

 

 

 

 

 

728x90