首页 > 解决方案 > 使用 Firebase 电子邮件验证链接登录

问题描述

我正在使用Firebase. 我已经配置了所有东西并发送了验证链接。

问题是当我点击验证链接时,它会打开我的应用程序,我会在AppDelegate方法中获得链接。但由于某种原因,我无法使用此链接登录。这是我的代码

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
        if let DeepLinkUrl = dynamiclink?.url?.absoluteString {
            if DeepLinkUrl.contains("verifyEmail") {
                if Auth.auth().isSignIn(withEmailLink: DeepLinkUrl) {
                    Auth.auth().signIn(withEmail: SBUserSetting.getVerificationEmail() ?? "", link: DeepLinkUrl ) { (user, error) in
                        print("user", user)
                        print("error", error)
                    }
                }
            }
        }
    }
    return handled
}

Auth.auth().isSignIn()总是返回false

你知道我在做什么错吗?

标签: iosswiftfirebasefirebase-authenticationemail-verification

解决方案


如果您想使用无密码登录(此https://firebase.google.com/docs/auth/ios/email-link-auth#verify_link_and_sign_in),则不能使用从 url 到 DynamicLink 的转换。您只需要像这样将原始 url 传递给您的方法。

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if let webpageUrl = userActivity.webpageURL {
        if Auth.auth().isSignIn(withEmailLink: webpageUrl.absoluteString) {

            // Saved email locally before, where you send verification, so you don't need to ask the user for it again
            // if they open the link on the same device.
            if let emailToVerify = UserDefaults.standard.string(forKey: "Email") {
                Auth.auth().signIn(withEmail: emailToVerify, link: webpageUrl.absoluteString) { (user, error) in
                    if let error = error as NSError? {
                        print(error.localizedDescription)
                    } else {
                        // User is logged in
                    }
                }
            }
        }
    }
    return true
}

但是如果你想使用方法sendEmailVerification你需要这个:

func sendEmailVerification() {
    let actionCodeSettings = ActionCodeSettings()
    actionCodeSettings.url = URL(string: "https://yourdomain.com")
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleId) // Budle identifier of your application

    Auth.auth().currentUser?.sendEmailVerification(with: actionCodeSettings, completion: { error in
        if let error = error as NSError? {
            print(error.localizedDescription)
        } else {
            // inform user about sending verification email
        }
    })
}

然后您可以使用 DynamicLink 类处理到达的电子邮件,如下所示:

func handleDynamicLink(_ url: URL?) -> Bool {
    guard let url = url else { return false }
    // Here don't know, which method will work, so I handle both for sure :-)

    if !DynamicLinks.dynamicLinks().handleUniversalLink(url, completion: { dynamicLink, error in
        if let dynamicLink = dynamicLink {
            if let oobCode = dynamicLink.url?.getQueryString(parameter: "oobCode") {
                Auth.auth().applyActionCode(oobCode) { error in
                    if let error = error as NSError? {
                        print(error.localizedDescription)
                    } else {
                        // Email was successfully verified
                    }
                }
            }
        } else {
            // Handle error
        }
    }) {
        if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
            if let oobCode = dynamicLink.url?.getQueryString(parameter: "oobCode") {
                Auth.auth().applyActionCode(oobCode) { error in
                    if let error = error as NSError? {
                        print(error.localizedDescription)
                    } else {
                        // Email was successfully verified
                    }
                }
            }
        } else {
            // handle error
        }
    }
    return false
}

这是我自己的 url 扩展方法getQueryString,用于将组件与 url 分开。

extension URL {

    func getQueryString(parameter: String) -> String? {
        if let urlComponents = URLComponents(string: self.absoluteString) {
            return urlComponents.queryItems?.filter({ item in item.name == parameter }).first?.value
        }
        return nil
    }
}

推荐阅读