繁体   English   中英

Firebase 无密码电子邮件身份验证不会在 iOS 上打开应用程序

[英]Firebase Passwordless Email Authentication doesn't open app on iOS

我正在尝试实现很酷的 Firebase 电子邮件链接登录功能,但失败得很厉害。 我成功设置了发送电子邮件链接。 但是,我无法获得打开该应用程序的电子邮件链接。 它只是打开预览页面,就像它无法打开应用程序一样。

我已经测试了我设置的动态链接,我可以通过它在设备中打开应用程序。 我只是无法获得电子邮件链接来做同样的事情。

我的应用程序中的代码:

func sendFirebaseEmailLink() {

    let actionCodeSettings = ActionCodeSettings.init()

    // userEmail comes from a textField
    let email = userEmail

    actionCodeSettings.url = URL.init(string: String(format: "https://<myappname>.firebaseapp.com/?email=%@", email))
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)

    Auth.auth().sendSignInLink(toEmail: email,
        actionCodeSettings: actionCodeSettings) { error in

        if let error = error {
            print(error.localizedDescription)
            return
        }
        else {
            UserDefaults.standard.set(email, forKey: "Email")
            print("email sent to user")
        }
    }
}

当我说我已成功获得打开应用程序的动态链接时,我的意思是当我在安装了该应用程序的设备上点击我创建的链接 (mylinkname.page.link/emaillogin) 时,它会打开该应用程序。 因此,[这个有用的 Firebase 视频][1] 关于设置动态链接似乎我已经了解了这些细节,问题出在代码上,但我是新手,所以我不确定.

我花了几天时间兜圈子来解决这个问题,并试图解析密集的 Firebase 文档,所以非常感谢任何想法。

我终于弄明白了。 代码很好。 这是一个与动态链接相关的问题。 我在 Firebase 中设置了几个链接,因为我必须一次性创建一个新的 Bundle ID。 当我在 Firebase 中删除旧的时,电子邮件链接开始工作。

它像这样出现在我的应用程序协会网站上,奇怪的是即使我删除了旧链接仍然如此,但至少它现在可以工作了!

{"applinks":{"apps":[],"details":[{"appID":"TEAMID.com.OLDBUNDLEIDENTIFIER.APPNAME","paths":["NOT / /*","/*"] },{"appID":"TEAMID.com.NEWBUNDLEIDENTIFIER.APPNAME","paths":["NOT / / ","/ "]}]}}

更新:我实现无密码电子邮件登录的完整代码如下。 使用文档拼凑起来对我来说很痛苦,所以希望这能为您省去麻烦。

假定您了解 Firebase 设置的基础知识的关键步骤。

1) 使用Firebase 视频教程设置动态链接。

2)视图控制器中的代码:

var userEmail: String?
var link: String?

func sendFirebaseEmailLink() {

    let actionCodeSettings = ActionCodeSettings.init()
    let email = userEmail
    actionCodeSettings.url = URL.init(string: String(format: "https://<myappname>.page.link/emaillogin/?email=%@", email!))
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)

    Auth.auth().sendSignInLink(toEmail: email!,
        actionCodeSettings: actionCodeSettings) { error in

        if let error = error {
            print(error.localizedDescription)
            return
        }
        else {
            UserDefaults.standard.set(email, forKey: "Email")
            print("email sent to user")
        }

        // TODO: Notify user to check email and click the link.
    }
}

// Sign in user after they clicked email link called from AppDelegate
@objc func signInUserAfterEmailLinkClick() {

    // Get link url string from the dynamic link captured in AppDelegate.
    if let link = UserDefaults.standard.value(forKey: "Link") as? String {
        self.link = link
    }

    // Sign user in with the link and email.
    Auth.auth().signIn(withEmail: userEmail!, link: link!) { (result, error) in

        if error == nil && result != nil {

            if (Auth.auth().currentUser?.isEmailVerified)! {
                print("User verified with passwordless email")

                // TODO: Do something after user verified like present a new View Controller

            }
            else {
                print("User NOT verified by passwordless email")

            }
        }
        else {
            print("Error with passwordless email verfification: \(error?.localizedDescription ?? "Strangely, no error avaialble.")")
        }   
    }
}

3) AppDelegate中的代码

// For Passwordless Email Login to Handle Dynamic Link after User Clicks Email Link
func application(_ application: UIApplication, continue userActivity: NSUserActivity,
                 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

    if let incomingURL = userActivity.webpageURL {
        print("Incoming URL is \(incomingURL)")

        // Parse incoming
        let linkHandled = DynamicLinks.dynamicLinks().handleUniversalLink(incomingURL) { (dynamicLink, error) in

            guard error == nil else {
                print("Found an error: \(error!.localizedDescription)")
                return
            }
            if let dynamicLink = dynamicLink {
                self.handleIncomingDynamicLink(dynamicLink)
            }
        }
        if linkHandled {
            return true
        }
        else {
            // Maybe do other things with dynamic links in future?
            return false
        }
    }
    return false
}

// Handles the link and saves it to userDefaults to assist with login.
func handleIncomingDynamicLink(_ dynamicLink: DynamicLink) {
    guard let url = dynamicLink.url else {
        print("My dynamic link object has no url")
        return
    }
    print("Incoming link parameter is \(url.absoluteString)")

    let link = url.absoluteString
    if Auth.auth().isSignIn(withEmailLink: link) {

        // Save link to userDefaults to help finalize login.
        UserDefaults.standard.set(link, forKey: "Link")

        // Send notification to ViewController to push the First Time Login VC
        NotificationCenter.default.post(
            name: Notification.Name("SuccessfulPasswordlessEmailNotification"), object: nil, userInfo: nil)
    }
}

我正在尝试并且无法实现酷炫的Firebase电子邮件链接登录功能。 我已成功设置发送电子邮件链接。 但是,我无法通过电子邮件链接打开该应用程序。 它只是打开预览页面,就像无法打开应用程序一样。

我已经测试了我设置的动态链接,可以在设备中打开该应用程序。 我只是无法获得电子邮件链接来执行相同的操作。

我的应用程式中的程式码:

func sendFirebaseEmailLink() {

    let actionCodeSettings = ActionCodeSettings.init()

    // userEmail comes from a textField
    let email = userEmail

    actionCodeSettings.url = URL.init(string: String(format: "https://<myappname>.firebaseapp.com/?email=%@", email))
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)

    Auth.auth().sendSignInLink(toEmail: email,
        actionCodeSettings: actionCodeSettings) { error in

        if let error = error {
            print(error.localizedDescription)
            return
        }
        else {
            UserDefaults.standard.set(email, forKey: "Email")
            print("email sent to user")
        }
    }
}

当我说我已经成功获得了打开应用程序的动态链接时,我的意思是当我在安装了该应用程序的设备上跟随我创建的链接(mylinkname.page.link/emaillogin)时,它会打开该应用程序。 因此,[此有用的Firebase视频] [1]设置了动态链接,似乎我已正确设置了这些详细信息,而问题出在代码中,但是我对此并不陌生,所以我不确定。

我花了几天时间来解决这个问题,并尝试解析密集的Firebase文档,因此非常感谢任何想法。

对于将 SwiftUI 与 AppDelegate 和 SceneDelegate 文件而不是 UIKit 一起使用的任何人,这是我所做的:

  1. 创建一个函数以将链接发送到用户的电子邮件
func sendSignLink(email: String) async throws {
    
do {
        let actionCodeSettings = ActionCodeSettings()
        actionCodeSettings.url = URL(string: "*enter your Firebase Dynamic link here*")
        actionCodeSettings.handleCodeInApp = true
        actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
        
        try await Auth.auth().sendSignInLink(toEmail: email, actionCodeSettings: actionCodeSettings)
        UserDefaults.standard.set(email, forKey: "email")
    }
    catch {
        throw error
    }
    
}
  1. 在 SceneDelegate 文件中, import FirebaseDynamicLinks并添加以下代码
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
                
        if let incomingURL = userActivity.webpageURL {
            
            print("\n \nIncoming URL is \(incomingURL)")
            
            _ = DynamicLinks.dynamicLinks().handleUniversalLink(incomingURL) { (dynamicLink, error) in
                
                guard error == nil else {
                    print("\n \nError with handling incoming URL: \(error!.localizedDescription)")
                    return
                }
                
                if let dynamicLink = dynamicLink {
                    
                    guard let url = dynamicLink.url else {
                        print("\n \nDynamic link object has no url")
                        return
                    }
                    
                    print("\n \nIncoming link parameter is \(url.absoluteString)")
                    
                    let link = url.absoluteString
                    
                    if Auth.auth().isSignIn(withEmailLink: link) {
                        
                        // Send notification to trigger the rest of the sign in sequence
                        NotificationCenter.default.post(name: Notification.Name("Success"), object: nil, userInfo: ["link": link])
                        
                    } else {
                        
                        // Send error notification
                        NotificationCenter.default.post(name: Notification.Name("Error"), object: nil, userInfo: nil)
                        
                    }
                    
                }
                
            }
        }
    }
  1. 创建一个函数来处理用户单击电子邮件中的链接后的登录
func signInWithEmail(link: String) async throws {
    
    do {
        let email = UserDefaults.standard.value(forKey: "email")
        try await Auth.auth().signIn(withEmail: email, link: link)
    }
    catch {
        throw error
    }
    
}
  1. 在相关视图中,处理发布的通知
struct MyView: View {
    
    var body: some View {
        
        VStack {
            Text("View")
        }
        
        .onReceive(NotificationCenter.default.publisher(for: Notification.Name("Success"))) { notificationInfo in
            
            if let userInfo = notificationInfo.userInfo {
                if let link = userInfo["link"] as? String {
                    Task.init {
                        do {
                            try await signInWithEmail(link: link)
                        } catch {
                            print(error)
                            
                        }
                    }
                }
            }
        }
        
        
        .onReceive(NotificationCenter.default.publisher(for: Notification.Name("Error"))) { _ in
            //do something with error
        }
        
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM