deprecated된 firebase dynamic link 없이 Firebase email link authentication 구현하기 - 1

DoDoBest

·

2024. 9. 11. 23:51

사진: Unsplash 의 JJ Ying

 

 

 

2025년 8월 25일부터 Firebase dynamic Link(FDL)가 deprecated 되어 사용할 수 없게 됩니다. Deprecation 문서에 따르면 신규 프로젝트 생성자는 FDL을 사용할 수 없고, Firebase email link authentication에 한해서 고객센터에 문의하면 FDL을 사용할 수 있다고 합니다. (문서와 다르게 신규 프로젝트도 Firebase Console에서 Run 탭 하위의 Dynamic Links에서 사용할 수 있습니다.)

 

 

따라서 migration 가이드에 따라 firebase hosting과 App Link를 이용해 Firebase email authentication을 구현해보겠습니다.

 

Hosting 구현 ( App Hosting 아닙니다 )

 

Hosting 카테고리에서 get started를 누릅니다.

 

 

 

NodeJS 설치

Node.js(LTS)를 설치합니다.

 

https://nodejs.org/en/

 

Node.js — Run JavaScript Everywhere

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

이후 커멘드 창을 열고, 아래 명령어를 실행합니다.

npm install -g firebase-tools

 

 

Firebase 계정, 프로젝트 설정

 

아래 명령어를 입력하고 Firebase 구글 계정을 연결합니다.

firebase logn

 

 

 

 

firebase 프로젝트를 생성할 경로로 이동한 후, 아래 명령어를 입력합니다.

firebase init

 

이후 y를 누르고 Hosting을 선택한 후 진행합니다.

 

 

 

Use an existing project를 선택한 후, hosting을 설정할 프로젝트를 선택합니다.

 

 

 

directory 이름으로 build를 입력합니다.

 

 

email link authentication을 구현하는 과정에서 필요하지 않기 때문에 single-page app, automatic build 모두 N을 입력합니다.

 

 

Configuration file 생성

App Link를 안전하게 사용하기 위한 설정 파일을 생성합니다.

In order to use App Links, you must host a configuration file that helps establish a secure association between the domain used in your links and your app. For App Links, this is the assetlinks.json file.

 

프로젝트 하위에 .well-known 폴더를 생성합니다.

 

 

 

assetlinks.json 파일을 생성합니다.

 

아래와 같은 값을 입력합니다. 그대로 입력하면 안 되고, target 하위의 값은 수정해야 합니다.

 

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.bestapp.zipbab",
    "sha256_cert_fingerprints":
      ["SHA-256 값"]
  }
}]

 

namespace : 이름을 지정합니다.

package_name : app build.gradle에 있는 패키지 이름을 지정합니다.

 

 

sha256_cert_fingerprints : Google Play Console - 설정 - 앱 서명에서 SHA-256 인증서 지문을 사용합니다.

 

 

아직 프로젝트를 배포하지 않았다면, Users 폴더 하위에서 .android 폴더의 debug.keystore를 이용하면 SHA 256 값을 추출할 수 있다고 합니다.

 

 

Android App Link assitant를 이용해도 SHA-256 값을 생성할 수 있습니다.

https://developer.android.com/studio/write/app-link-indexing

 

Android App Links 추가  |  Android Studio  |  Android Developers

Android App Links는 Android 앱의 특정 콘텐츠로 사용자를 바로 안내하는 HTTP URL입니다.

developer.android.com

 

SHA-256 값은 Firebase Project settings에도 추가해줍니다.

 

 

 

다음으로 root 프로젝트 하위에 있는 firebase.json에 headers를 추가합니다.

{
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "headers": [
      {
        "source": "/.well-known/assetlinks.json",
        "headers": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ]
      }
    ]
  }
}

 

 

변경사항을 반영하기 위해 커멘트 창에서 아래 명령어를 입력합니다.

 

firebase deploy

 

 

 

브라우저에서 호스팅 주소가 정상적으로 동작하는지 확인합니다.

 

https://Xxx.web.app/.well-known/assetlinks.json

 

 

Firebase Authentication 활성화

 

Authentication - Sign-in method 탭에서 Email provider를 활성화 합니다.

 

 

Templates 탭으로 이동한 후, 인증 메일 형태를 변경합니다.

무료 요금제인 Spark는 기본 템플릿만 사용 가능하고, 변경하기 위해서는 Blaze로 업그레이드 해야 합니다.

저는 Spark를 사용하기 때문에 하단에 Template language를 변경해서 인증 이메일이 한국어로 발송되도록만 설정했습니다.

 

 

 

Android Email Authentication code 구현

 

이제 인증 메일을 발송하기 위한 코드를 작성하겠습니다.

 

의존성 추가

 

toml에 firebase auth, play service auth 의존성을 추가합니다.

 

[versions]
firebaseBom = "33.0.0"
playServiceAuth = "21.2.0"

[libraries]
firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" }
firebase-firebase-auth = { group = "com.google.firebase", name = "firebase-auth" }

gms-play-service-auth = { group = "com.google.android.gms", name = "play-services-auth", version.ref = "playServiceAuth" }

 

 

Auth를 사용할 모듈 build gradle에 의존성을 추가합니다.

 

...

dependencies {
    // Import the Firebase BoM
    implementation(platform(libs.firebase.bom))
    implementation(libs.firebase.firebase.auth)

    implementation(libs.gms.play.service.auth)
}

 

발송 코드 작성

 

인증 메일을 발송하는 코드 입니다.

인증 메일을 발송하기 위해서는 사용자 메일이 Firebase Authentication Users 풀에 등록되어야 합니다. 그래서 유저를 먼저 등록했으며, 등록에 성공한 경우 인증 메일을 발송했습니다.

이미 가입된 사용자가 다른 이메일로 변경하는 경우도 처리했습니다.

 

suspend fun sendCodeToEmail(email: String, password: String): VerifyStateEntity {
    val user = Firebase.auth.currentUser

    if (user == null) {
        return try {
        	// 사용자가 입력한 메일로 User를 생성한다.
            val isSuccess =
                Firebase.auth.createUserWithEmailAndPassword(email, password).doneSuccessful()
            if (isSuccess) {
            	// 사용자 생성에 성공하면 인증 메일을 보낸다.
                val sendEmailResult =
                    Firebase.auth.currentUser?.sendEmailVerification()?.doneSuccessful()
                        ?: false
                if (sendEmailResult) {
                    VerifyStateEntity.Success
                } else {
                    VerifyStateEntity.FailAtSendVerificationEmail
                }
            } else {
                VerifyStateEntity.Fail
            }
        } catch (e: FirebaseAuthUserCollisionException) { // 이미 가입된 사용자인 경우
            VerifyStateEntity.AlreadyUsedEmail
        } catch (e: FirebaseAuthWeakPasswordException) { // 비밀번호가 6자리보다 짭은 경우
            VerifyStateEntity.PasswordTooShort
        }
    } else { // 이미 등록된 계정에서 이메일을 변경하는 경우
        if (user.email == email) { // 현재 등록된 메일과 동일한 메일을 입력한 경우
            return VerifyStateEntity.AlreadyUsedEmail
        }
        try {
        	// 새로운 메일로 인증 메일을 보낸다.
            val isSuccess = user.verifyBeforeUpdateEmail(email).doneSuccessful()
            return if (isSuccess) {
                VerifyStateEntity.Success
            } else {
                VerifyStateEntity.Fail
            }
        } catch (_: FirebaseAuthInvalidUserException) {
            resetAuthState()
            return VerifyStateEntity.Fail
        } catch (_: FirebaseAuthRecentLoginRequiredException) { // https://firebase.google.com/docs/auth/android/manage-users?hl=en#re-authenticate_a_user
            // 로그인한지 시간이 많이 경과된 경우, 이메일을 변경하기 위해서는 로그인 상태를 갱신해야 합니다.
            val credential = EmailAuthProvider.getCredential(user.email ?: "", password)

            // 재인증 이후에도 실패할 경우 Server 단에서 처리하도록 Fail을 리턴했습니다.
            return try {
                user.reauthenticate(credential).await()
                val isSuccess = user.verifyBeforeUpdateEmail(email).doneSuccessful()
                if (isSuccess) {
                    VerifyStateEntity.Success
                } else {
                    VerifyStateEntity.Fail
                }
            } catch (_: Exception) {
                VerifyStateEntity.Fail
            }
        }
    }
}

fun resetAuthState() {
    Firebase.auth.signOut()
}

sealed interface VerifyStateEntity {

    data object Success : VerifyStateEntity
    data object AlreadyUsedEmail : VerifyStateEntity
    data object FailAtSendVerificationEmail : VerifyStateEntity
    data object Fail : VerifyStateEntity
    data object PasswordTooShort : VerifyStateEntity
}

 

다른 예제와 다른 점은 ActionCodeSettings를 지정하지 않는 것 입니다. ActionCodeSettings를 sendEmailVerification의 파라미터로 전달하면 Firebase Dynamic Link를 사용하게 됩니다.

지금까지 설정한 코드는 FDL이 아닌 Hosting을 이용한 방식이기 때문에 Runtime에 아래와 같은 Exception이 발생합니다.

The provided dynamic link domain is not configured or authorized for the current project

 

private val actionCodeSettings: ActionCodeSettings = actionCodeSettings {
    url = BuildConfig.FIREBASE_HOSTING_LINK
    handleCodeInApp = true
    setAndroidPackageName(
        "com.bestapp.zipbab",
        true,
        "10"
    )
}

 

 

 

 

코드를 실행하면 인증 메일을 확인할 수 있습니다.

 

 

 

 

 

마무리

 

다음 글에서는 Flow를 이용해 이메일의 인증 여부를 observing 하는 것과 인증 메일을 클릭했을 때, 설치된 앱 화면으로 돌아오도록 설정하는 코드를 살펴보겠습니다.

 

https://dodobest.tistory.com/121

 

deprecated된 firebase dynamic link 없이 Firebase email link authentication 구현하기 - 2

이전 글https://dodobest.tistory.com/120 deprecated된 firebase dynamic link 없이 Firebase email link authentication 구현하기 - 12025년 8월 25일부터 Firebase dynamic Link(FDL)가 deprecated 되어 사용할 수 없게 됩니다. Deprecation

dodobest.tistory.com