Firebase User re-authentication initialising error - ios

When any user wants to update his/her password from app, i want to update that password of same FCM user and for that i have tried below code which define in official doc.
here is the screenshot of that
Here is my code
func authenticateAndUpdateFCMUserPassword(strNewPassword: String) {
let user = Auth.auth().currentUser
var credential: AuthCredential
// Prompt the user to re-provide their sign-in credentials
user?.reauthenticate(with: credential) { error in
if let error = error {
// An error happened.
} else {
// User re-authenticated.
}
}
Auth.auth().currentUser?.updatePassword(to: strNewPassword) { (error) in
if error != nil {
print("Error occur while updating password")
}
else {
print("Password Updated Successfully")
}
}
}
But in above code i'm facing below error at user?.reauthenticate line
Cannot convert value of type '(_) -> ()' to expected argument type
'AuthDataResultCallback?' (aka 'Optional<(Optional,
Optional) -> ()>')
so i re write that by below code
user?.reauthenticate(with: credential, completion: { (dataResult, errorr) in
if errorr != nil {
// An error happened.
} else {
// User re-authenticated.
}
})
but in above code i'm facing below error
Variable 'credential' used before being initialized
credential is defined only once and never used before this
will anyone please let me know what i'm doing wrong?

When I set my credential variable as below, the error went away for me:
var credential: AuthCredential = EmailAuthProvider.credential(withEmail: email, password: password)
This answer helped me: https://stackoverflow.com/a/52160137/9625899

Related

What if I have currentUser == nil in firebase while reauthenticateWithCredential iOS Swift

Sometimes we get Auth.auth().currentUser as nil (May be when session for that login expires).
My main question is:
What is the reason behind currentUser being nil.
If the curentUser is nil what if I call the reauthenticateWithCredential method on it?
Do reAuthenticate method fills the session again and start providing values in the currentUser?
Below is the code to reAuthenticate user.
func authenticateUser()
{
let credential = EmailAuthProvider.credential(withEmail: myEmail, password: myPassword)
Auth.auth().currentUser?.reauthenticate(with: credential, completion: { (dataResult, error) in
if(error == nil){
print("Email login success")
completionHandler(true)
}else{
print("Email login failed - " + error.debugDescription)
completionHandler(false)
}
})
}
Any HELP will be Appreciated,
Many Thanks!!
Dinal J

How to solve the problem with Firebase listener, which open everywhere?

I have some simple App, which have auth.
nearest code check if you already entered:
func signingManager(){
Auth.auth().addStateDidChangeListener { [weak self] (auth, user) in
guard let self = self else {return}
if user != nil {
self.showNextVC()
print("You are already entered")
}
}
}
It's works when you first open the app and if you entered func "showNextVC" will open next VC.
In the same time i have login button with code :
#IBAction func logInTapped(_ sender: UIButton) {
guard let email = emailTextField.text, let password = passwordTextField.text, email != "", password != "" else {
displayWarningLabel(withText: "info is incorrect")
return
}
Auth.auth().signIn(withEmail: email, password: password, completion: { [weak self] (user, error) in
if error != nil {
self?.displayWarningLabel(withText: "error occured")
return
}
if user != nil {
self?.showNextVC()
print("Congratulations, you have successfully logged in!")
}
self?.displayWarningLabel(withText: "no such user")
}
)}
Now about the problem: if I click the "login" button, the "signingManager ()" method and it's "showNextVC" are triggered first, and only then the "logInTapped" method itself and again "showNextVC".
As a result, I have 2 VCs and two messages:
"You are already entered" and
"Congratulations, you have successfully logged in!"
What am I doing wrong? Thanks!
Since you're listening for for auth state changes, you don't need to handle the self?.showNextVC() in the completion callback for signIn(withEmail:, password:). That code should only be present in the callback for addStateDidChangeListener.
Alternatively, you can:
Use the addStateDidChangeListener to initially detect whether the user is signed-in already.
Inside the callback for the state change:
Remove the listener by calling removeAuthStateDidChangeListener
Start the explicit sign-in flow, and call signIn(withEmail:, password:) like you're doing now.

Update Phone Number in Firebase Authentication - Swift

Is there a way to update the phone number in firebase auth? The thing is if the user entered a wrong number in registration then can I update the old number to new one then send the verification code in that new number? How can I achieve this?
There is a method on the User object called updatePhoneNumber, which seems to be what you want.
The documentation doesn't mention anything about what this does to the verification status, although I'd assume it indeed will require the new number to be verified too. Give it a try, and let me know if that isn't the case.
On the screen where the user has to enter their phone number:
var verificationId: String?
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumberTextField.text!, uiDelegate: nil) { (verificationID, error) in
if let error = error { return }
self.verificationId = verificationID else { return }
}
On the screen where the user has to enter the sms verification code:
guard let safeVerificationId = self.verificationId else { return }
let credential = PhoneAuthProvider.provider().credential(withVerificationID: safeVerificationId, verificationCode: smsTextField.text!)
Auth.auth().currentUser?.updatePhoneNumber(credential, completion: { (error) in
if let error = error { return }
})
You're welcome
Auth.auth().currentUser?.updatePhoneNumber(credential, completion: { (error) in
if error == nil {
print("succes")
}
})

iOS link two firebase accounts error

I'm trying to link two firebase accounts
a phone account ( signed in ) to Anonymous account ( prevUser )
this is my code
func verifyCode() {
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: self.verificationID,
verificationCode: phoneCode.text!)
let prevUser = Auth.auth().currentUser!
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
print("1 something went wrong : ", error.localizedDescription)
return
}
print("the user ID is : " , user!.uid)
prevUser.link(with: credential, completion: { (user, error) in
if let error = error {
print("something went wrong : ", error.localizedDescription)
return
}
})
}
}
I keep getting the same error always
something went wrong : The SMS code has expired. Please re-send the verification
code to try again.
thanks in advance
There are 2 issues here:
You are signing in with the phone auth credential first and then linking to the same credential which contains the same underlying SMS code which is a one time code. This will always fail with the error you are getting since the Firebase Auth backend can only use the code once (it immediately expires the first time it is used).
Even if the code is usable more than once, you can't have more than one user with the same phone credential. You first sign in one user with that credential and then try to link it to another user. This will always fail with an error that the credential already exists on another account.
Step 1: You can verify the phone number by providing phone number string and in completion you will be returned a verificationID and error if any.
func verifyPhoneNumber(withPhoneNo phoneNo:String, completion: #escaping (_ error: Error?, _ verificationID: String?)->Void) {
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNo) { (verificationID, error) in
if let error = error {
print(error.localizedDescription)
completion(error, verificationID)
} else {
print(verificationID ?? "no id provided")
completion(nil, verificationID)
}
}
}
Step 2: Linking Phone Number to the current User by providing the current user, 6digit verification code, verificationID obtained from the previous function.
In completion you will be returned with an error if any.
func linkPhoneNumber(withUser user: User, verificationCode: String, verificationID id: String, completion: #escaping (_ error: Error?)-> Void) {
let credential = PhoneAuthProvider.provider().credential(withVerificationID: id, verificationCode: verificationCode)
user.link(with: credential) { (user, error) in
if let error = error {
print(error.localizedDescription)
completion(error)
} else {
print(user!.uid)
completion(nil)
}
}
}

Invalid API Key supplied using Firebase

I'm using Firebase Auth to allow users to sign up using Facebook. I have taken all the steps from here to implement sign up including adding GoogleService-Info.plist to my project.
I get the Facebook permission screen all fine but when the app hits
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
this error is returned: An invalid API Key was supplied in the request.
Can anyone help me with this please?
Thanks
Here is my function code to log in using Facebook.
#IBAction func signUpWithFacebook() {
let fbLogin = FBSDKLoginManager()
fbLogin.logInWithReadPermissions(["email"], fromViewController:self, handler: {
(result, error) -> Void in
if ((error) != nil) {
print("Process error")
} else if (result.isCancelled) {
print("Cancelled");
} else {
print("Logged in");
let accessToken = FBSDKAccessToken.currentAccessToken().tokenString
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)
print(FBSDKAccessToken.currentAccessToken().tokenString)
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
// ...
if let user = user{
print(user.displayName)
}
else{
if let error = error {
print(error.localizedDescription)
}
}
}
}
})
}
Solved it, for anyone that needs the solution in the future.
Sometimes API_KEY is missing from the GoogleService-Info.plist, this needs to be added.
The API Key can be found from Google API Console https://console.developers.google.com/
You can solve this by Downloading again the "GoogleService-Info.plist" file, under the Project Setting section on Firebase Console.
Ensure that the API_KEY is set on the new "GoogleService-Info.plist".

Resources