iOS link two firebase accounts error - ios

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)
}
}
}

Related

Error "Amplify.AuthError error 2" thrown during the sign in flow on iOS with amplify-swift 1.15.1

During the sign in flow in iOS, for few users the Authentication module of the amplify-swift library throws the error The operation couldn't be completed. (Amplify.AuthError error 2). I have searched in the amplify-swift repository for possible solutions but couldn't find any. The version of Amplify pod used in code is 1.15.1.
func nativeLogin(
email: String?, password: String?, completion: #escaping (Result<Authstate, Error>) -> Void
) {
let isAlreadySignedIn = AWSMobileClient.default().isSignedIn
if isAlreadySignedIn {
// Do signout and then sign in
let options = AuthSignOutRequest.Options(globalSignOut: true)
Amplify.Auth.signOut(options: options) {
result in
DispatchQueue.main.async {
if case .success = result {
// completion(.success(.logout))
guard let email = email,
let password = password
else {
self.response(
completion, .failure(AuthError.passwordValidationError("Missing Email/Password")))
return
}
// log event
self.signIn(email: email, password: password, completion: completion)
} else if case .failure(let error) = result {
// log event
completion(.failure(error))
}
}
}
} else {
self.signIn(email: email, password: password, completion: completion)
}
}
The reason that the signOut method is invoked before actually signing in is to ensure that last logged in user is signed out first.
Can anyone explain where am I going wrong? Or has this error been already fixed in the latest version (2.2.1) of the amplify-swift library?

AWS Cognito "confirmSignUp" is going in error code

I am using Cognito login and signup. If I am confirming OTP Code it is giving me an error.
An error occurred while registering a user AuthError: Username/client id combination not found.
Recovery suggestion: Make sure that the user is present in the backend
Caused by:
userNotFound
func confirmSignUp(for username: String, with confirmationCode: String) {
_ = Amplify.Auth.confirmSignUp(for: username, confirmationCode: confirmationCode) { result in
switch result {
case .success(_):
print("Confirm signUp succeeded")
DispatchQueue.main.async {
self.checkOTP(otp:self.storeOTP)
}
case .failure(let error):
print("An error occurred while registering a user \(error)")
DispatchQueue.main.async {
self.alert(title: "", message: "OTP not match")
}
}
}
}

Firebase User re-authentication initialising error

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

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")
}
})

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