Firebase Auth 전화번호 회원가입

Henry Lee·2022년 1월 17일
0

Firebase Auth에서 제공하는 전화번호 인증해보기

1. 사전작업

우선 Firebase Auth 전화번호 인증은, Slient Push Notification을 이용해 토큰을 보내기 때문에 Push Notification을 사용하는 것과 동일하다.

따라서 아래의 준비가 필요하다.

  • 유료 애플 개발자 계정
  • Xcode Project Setup
  • Apple Developer Member Center Identifier

유료 애플 개발자 계정

  • 앞서 말했지만, 유료 애플 개발자 계정을 필요로 한다.

Xcode Project Setup

  • Push Notification을 받는 것이기 때문에 Xcode 설정이 필요하다.
  • Project - Target - Signing & Capabilites - Push Notifications

Apple Developer Member Center Identifier

인증토큰은 Firebase project에 등록해야할 토큰으로 아래 과정을 통해서 만들 수 있다.

Developer Apple의 Member Center로 이동 후, Keys탭으로 간다.

적당히 알아볼 만한 이름을 작성하고, APNs를 체크 한 후 Continue - Register

그다음 Download가 나오는데

경고문을 찬찬히 읽어보면, 보안을 위해 다운로드 후에는 서버에서 해당 키를 삭제한다고 한다. 그러니까 다운받은 그것이 유일본이기 때문에 잃어버리지 않도록 안전한 곳에 보관해야 한다.

키를 다운받아 보면 AuthKey_ABCDEFGH~ 이런식으로 되어있는데 언더바 뒤의 알파벳,숫자 조합이 바로 키 아이디가 된다.

이제 디바이스 토큰, 인증 토큰(키), 그리고 하나 더 필요한 것은 TeamID인데 이것은 화면 우측 상단 계정에 이름 아래에 있다.

위 토큰을 이제 Firebase에 넣어주면 된다.

해당 내용은 파이어베이스 전화번호 인증 문서 참고

Firebase 인증 문서

2. 프로젝트

파이어베이스에 프로젝트에 앱을 등록했으면, 이제 프로젝트에 작성할 일만 남았다.

우선 본인은 SwiftUI로 했는데 SwiftUI 처음 진입하면 AppDelegate가 없다.

다음과 같이 작성해준다. (프로젝트명App.swift)

import SwiftUI
import Firebase

class AppDelegate: NSObject, UIApplicationDelegate {
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    
    FirebaseApp.configure()
    return true
  }
  
  func application(_ application: UIApplication,
                   didReceiveRemoteNotification notification: [AnyHashable : Any],
                   fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

  }
}

@main
struct FirebasePhoneAuthPracticeApp: App {
  @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
  
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }

노티피케이션의 기본적인 플로우는 아래와 같다.

  1. application(_:didFinishLaunchingWithOptions:) 에서 registerForRemoteNotifications를 통해 APN으로 디바이스 토큰을 전송한다
  2. APN은 앱에 디바이스 토큰을 반환하고 이때 application(_:didRegisterForRemoteNotificationsWithDeviceToken:) 호출하거나 토큰 등록에 실패했을 시 application(_:didFailToRegisterForRemoteNotificationsWithError:) 를 호출하여 알린다.
  3. 디바이스는 토큰을 binary 또는 hexadecimal 포맷으로 provider(서버)로 토큰을 보낸다. provider가 이제 토큰을 추적하기 시작한다.
  4. provider가 notification 요청을 다수의 토큰과 함께 APNs로 보낸다.
  5. 마지막으로 APNs가 notification을 유효한 토큰이 제공된 각 디바이스에 알림을 보낸다.

그런데 Firebase 전화번호 Auth는 Slient Push Notification이기 때문에 application(_:didFinishLaunchingWithOptions:) 는 FirebaseApp초기화 때문에 필요하고 나머지는 필요하지 않다.

따라서 Slient Push를 이용하기 위한 사전 작업이 따로 필요하다.

Background Modes

Slient Push Notification은 사용자에게 보이지 않는 기능이고 백그라운드에서 동작한다. 따라서 Sining & Capabilites에 Background Modes를 추가하고 거기서 Remote Notifications을 체크 한다.

App Delegate

func application(
  _ application: UIApplication,
  didReceiveRemoteNotification userInfo: [AnyHashable: Any],
  fetchCompletionHandler completionHandler:
  @escaping (UIBackgroundFetchResult) -> Void
) {
  ...
}

application(_:didReceiveRemoteNotification:fetchCompletionHandler) 델리게이트 메서드가 있어야 한다. 해당 코드는 이미 작성했으므로 Slient Push Notification을 사용할 준비가 되었다.

또 Slient Push Notification은 유저에게 알람이 발생하지 않으므로 알람에 대한 동의를 받을 필요가 없다.

인증하기

인증하는 작업 플로우는 다음과 같다.

  1. 전화번호를 검증하고 요청한다.
  2. 1번 과정이 성공적으로 진행되면 해당 번호로 인증번호가 온다.
  3. 유저가 작성한 인증번호가, 실제로 서버에서 보낸 인증번호가 일치하는 작업을 한다.
  4. 3번이 성공적일 경우 로그인 루틴을 실행한다.

1. 전화번호 검증

func requestVerifyCode() {
    buttonDisabled = true
    let validPhoneNumber = "+82\(phoneNumber)"
    PhoneAuthProvider.provider().verifyPhoneNumber(validPhoneNumber, uiDelegate: nil) { verification, error in
      if let error = error {
        print("error: \(error)")
        buttonDisabled = false
      } else {
        self.verificationId = verification
        withAnimation {
          watingVeryfiId = true
        }
      }
    }
  }

텍스트필드에 입력된 전화번호를 검증하고 Firebase서버에 요청하는 코드로

verifyPhoneNumber(_:uiDelegate:completion:) 메서드를 통해 요청한다.

첫번째 인자에 유저가 입력한 전화번호가 들어가면 된다. 입력은 통상적으로 입력하는 010~ 패턴이면 되는데 앞에 국가코드를 포함해야 한다.

전화번호 검증이 성공했을 때 인증코드가 전화번호로 날아오게 된다.

2. 인증번호 검증

func verifyLogin() {
    isVerifying = true
    let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationId ?? "", verificationCode: userVerify)
    Auth.auth().signIn(with: credential) { (success, error) in
      if let error = error {
        print("error: \(error.localizedDescription)")
        
      } else {
        print("success")
        showMainView = true
      }
      isVerifying = false
    }
  }

이제 유저가 받은 인증코드를 다른 텍스트필드에 입력하고, 1에서 받은 인증코드와 비교하는 메서드를 작성한다.

credential(withVerificationID:verificationCode) 메소드에 첫번째 인자는 verifyPhoneNumber메서드로 받은 인증코드, 그리고 두번째 인자에는 유저가 입력한 인증코드가 된다. 두 개가 일치하게 되면 인증이 성공하는 것이다.

기본 코드만 작성 한 것으로 토큰 관리나, 로그인 상태 관리 등은 꼭 별도로 해야한다!

전체 코드 보기

profile
iOS Dev, Coffee in my bloodstream

0개의 댓글