-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
[REQUIRED] Step 1: Describe your environment
- Xcode version: Version 12.4 (12D4e)
- Firebase SDK version: 7.8.1
- Installation method:
CocoaPods - Firebase Component: Auth
[REQUIRED] Step 2: Describe the problem
Steps to reproduce:
Hello. I'm an iOS developer.
We are using Firebase Auth for new app development. We use the email link authentication method. We are trying to register for multi-factor authentication by phone number after the email link authentication.
The signIn(withEmail:link:completion:) used in this email link login returns the following error when re-logging in after multi-factor registration. (It is expected that the secondFactorRequired error will be returned.)
Error Domain=FIRAuthErrorDomain Code=17999 "An internal error has occurred, print and inspect the error details for more information." UserInfo={FIRAuthErrorUserInfoNameKey=ERROR_INTERNAL_ERROR, NSLocalizedDescription=An internal error has occurred, print and inspect the error details for more information., NSUnderlyingError=0x283de8d80 {Error Domain=FIRAuthInternalErrorDomain Code=3 "(null)" UserInfo={FIRAuthErrorUserInfoDeserializedResponseKey={
code = 400;
message = "INVALID_GRANT_TYPE";
status = "INVALID_ARGUMENT";
}}}}
I would like to know how to avoid this error.
I have tested it several times and found out a few things. If I disable multifactor registration in the user console of the ID platform, I can log in again. I have also confirmed that I can log in after multifactor registration using methods other than email link log-in (ex. signIn(withEmail:password:completion:) ). I have confirmed that this problem does not occur in web SDK.
reference
- https://firebase.google.com/docs/auth/ios/email-link-auth?authuser=0#completing_sign-in_in_an_ios_mobile_app
- https://cloud.google.com/identity-platform/docs/ios/mfa
- https://firebase.google.com/docs/reference/swift/firebaseauth/api/reference/Classes/Auth#signinwithemail🔗completion:
Relevant Code:
func signIn(email: String, link: SignInLink) -> AnyPublisher<SignInResult, RepositoryError> {
return Future<SignInResult, RepositoryError> { (promise) in
auth.signIn(withEmail: email, link: link.rawValue) { result, error in
if let error = error as NSError? {
if error.code == AuthErrorCode.secondFactorRequired.rawValue,
let resolver = error.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as? MultiFactorResolver,
let multiFactorInfo = resolver.hints.first as? PhoneMultiFactorInfo {
promise(.success(.needVerifyingMFA(resolver: resolver, phoneMultiFactorInfo: multiFactorInfo))) // I'm expecting to get into this line.
} else {
promise(.failure(.init(firebaseAuthCommonError: error))) // But it actually goes in a line here.
return
}
}
guard let user = result?.user else {
promise(.failure(.init(SignInError.noUser)))
return
}
guard user.multiFactor.enrolledFactors.isEmpty else {
promise(.failure(.init(SignInError.mfaError)))
return
}
promise(.success(.needEnrollingMFA))
}
}
.eraseToAnyPublisher()
}