0

Create a user with Username, email, and password. Then force the user to complete phone number verification before the account is created.

I am designing an app where we would like to make the user sign up by creating a username, password, supply their email address, and then complete phone number verification.

enter image description here

This picture represents the desired flow we would like our user to complete to register their account.

here are our View Controller files:

This is the code for the "Create Account" view, it creates a user in Firebase using email

import UIKit
class CreateAccountVC: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var usernameTextfield: UITextField!
    @IBOutlet weak var passwordTextfield: UITextField!
    @IBOutlet weak var emailTextfield: UITextField!
    @IBOutlet weak var confirmPasswordTextfield: UITextField!
    @IBOutlet weak var createAccountLbl: UILabel!

    @IBOutlet weak var createAccountTextView: UILabel!
    @IBOutlet weak var signupBtn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.hideKeyboardWhenTappedAround()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:UIResponder.keyboardWillHideNotification, object: nil)
        overrideUserInterfaceStyle = .light
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        signupBtn.clipsToBounds = true
        signupBtn.layer.cornerRadius = 15
        signupBtn.addButtonGradient(didType: true)
    }

    @objc func keyboardWillShow(notification:NSNotification){

        let userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)
        var contentInset:UIEdgeInsets = self.scrollView.contentInset
        contentInset.bottom = keyboardFrame.size.height
        scrollView.contentInset = contentInset
    }

    @objc func keyboardWillHide(notification:NSNotification){
        let contentInset:UIEdgeInsets = UIEdgeInsets.zero
        scrollView.contentInset = contentInset
    }
    @IBAction func alreadyHaveAccountBtnPressed(_ sender: Any) {
//        dismiss(animated: true, completion: nil)
//        self.performSegue(withIdentifier: "TypePhoneNumberVC", sender: self)
    }
    @IBAction func signupBtnPressed(_ sender: Any) {
        let username = usernameTextfield.text
        let email = emailTextfield.text
        let password = passwordTextfield.text
        signupBtn.isHidden = true
        AuthorizationService.instance.registerUser(username: username!, email: email!, password: password!) { (success, err) in
            if success{
                AuthorizationService.instance.loginUser(withEmail: email!, andPassword: password!) { (success, err) in
                    if err != nil{
                        return
                    }
                    self.performSegue(withIdentifier: "EnterNumberSegue", sender: self)
                    print("Sign-up successful")
                }
            }else{
                let alertController = UIAlertController(title: "Error", message: err?.localizedDescription, preferredStyle: .alert)
                let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
                alertController.addAction(defaultAction)
                self.present(alertController, animated: true, completion: nil)
                self.signupBtn.isHidden = false
            }

        }
    }
    @IBAction func backBtnPressed(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }
}

These next two demonstrate the implementation of the Phone number verification

import UIKit
import Firebase
import FirebaseAuth


class EnterPhoneNumberVC: UIViewController, UITextFieldDelegate{

    @IBOutlet weak var backButton: UIButton!
    @IBOutlet weak var phoneNumberUITextField: UITextField!
    @IBOutlet weak var getCodeButton: UIButton!

    let userDefaults = UserDefaults.standard

    override func viewDidLoad() {
        super.viewDidLoad()
        phoneNumberUITextField.delegate = self
        let tap = UITapGestureRecognizer(target: self, action: #selector(handle))
        view.addGestureRecognizer(tap)
        overrideUserInterfaceStyle = .light

    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        getCodeButton.clipsToBounds = true
        getCodeButton.layer.cornerRadius = 15
        getCodeButton.addButtonGradient(didType: true)
    }
    @objc func handle(tap: UITapGestureRecognizer){
        view.endEditing(true)
    }
    @IBAction func backButtonPressed(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }

    @IBAction func getCodeButtonPressed(_ sender: Any) {

        guard let phoneNumber = phoneNumberUITextField.text else {return}

        PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationID, error) in
            if error == nil {
                print(verificationID)
                guard let verifyID = verificationID else {return}
                self.userDefaults.set(verifyID, forKey:"verificationID")
                self.userDefaults.synchronize()
                self.performSegue(withIdentifier: "GetCodeSegue", sender: self)
            } else {
                print("unable to confirm the users phone number", error?.localizedDescription)
            }
        }
    }
import UIKit
import Firebase
import FirebaseAuth

class PhoneNumberVerificationVC: UIViewController, UITextFieldDelegate {


    @IBOutlet weak var verifyBtn: UIButton!
    @IBOutlet weak var resendCodeBtn: UIButton!

    @IBOutlet weak var otpCode: UITextField!

    var verificationID: String?
    let userDefaults = UserDefaults.standard

    override func viewDidLoad() {

        super.viewDidLoad()
        overrideUserInterfaceStyle = .light
        let tap = UITapGestureRecognizer(target: self, action: #selector(handle))
        view.addGestureRecognizer(tap)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        verifyBtn.clipsToBounds = true
        verifyBtn.layer.cornerRadius = 15
        verifyBtn.addButtonGradient(didType: true)
    }
    @objc func handle(tap: UITapGestureRecognizer){
        view.endEditing(true)
    }
    @IBAction func backBtnPressed(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }
    @IBAction func verifyBtnPressed(_ sender: Any) {
        guard let optCode = otpCode.text else {return}
        guard let verificationID = userDefaults.string(forKey: "verificationID") else {return}
        let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID, verificationCode: optCode)
        Auth.auth().signInAndRetrieveData(with: credential) { (success, error) in
            if error == nil {
                print(success)
                 self.performSegue(withIdentifier: "VerifiedSegue", sender: self)
                print("The user has successfully logged In and is verified!")
            } else {
                print("Error: Phone number and One time password does not match")
            }
        }
    }
Garrett
  • 319
  • 1
  • 13
  • can you clarify what your question is? in which part you are exactly stuck? Have a look at [1] so that you can refine more your question. [1] https://stackoverflow.com/help/how-to-ask – Antonio Ramirez May 22 '20 at 22:08
  • We do not understand how to update the user profile information once they verify their phone number – Garrett May 23 '20 at 00:57
  • 1
    [This](https://stackoverflow.com/questions/50895856/how-to-merge-emailandpasswordauth-with-phoneauth-in-firebase) has solved a similar problem of mine in the past. – Gius May 23 '20 at 17:25

0 Answers0