ios - 使用 Firebase 电子邮件验证链接登录

标签 ios swift firebase firebase-authentication email-verification

我正在使用 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

你知道我做错了什么吗?

最佳答案

如果你想使用无密码登录(这个 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
    }
}

关于ios - 使用 Firebase 电子邮件验证链接登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52328136/

相关文章:

ios - 将两种不同类型的对象作为一个函数变量传递

ios - 核心数据 NSFetchedResultsController 一对多用于 swift titleForHeader

ios - 使用AWS iOS SDK由于未捕获的异常'NSInvalidArgumentException'而终止应用程序

swift - 将 ViewController 设置为初始值?

javascript - 为什么 ref.getCollections() 不被识别为函数?

firebase - "Error: Permission denied"运行 firebase init 并选择数据库时

firebase - 在 Firebase 中选择数据

objective-c - 无法使用 MPMoviePlayerController 运行视频文件?

ios - 更改 TextView 文本时保留文本样式

ios - 未调用 SDWebImage 下载图像完成 block