From docs:
"Android supports auto-verify and instant device verification. Therefore in that case it doesn't make sense to ask for an sms code as you won't receive one. Also, verificationId will be false in this case. In order to sign the user in you need to check credential.instantVerification, if it's true, skip the SMS Code entry, call your backend server (sorry, it is the only way to succeed with this plugin) and pass the phone number as param to identify the user (via ajax for example, using any endpoint to your backend)."
So, got twice calling method:
window.FirebasePlugin.verifyPhoneNumber()
First manual, by user click and second Android call itself, like was mentioned in docs.
On second times, the param credential.verificationId equal to bool: false.
But i implemented check for type of this param and string only is using further:
if (typeof credential.verificationId === 'string') {
this.verificationId = credential.verificationId;
}
so previous param with type string, is saved and auth is working good.
Maybe i'm something don't understand, but for a what we need server side and custom tokens?
The flow of Firebase Phone Auth is first to verify the phone number (using the OTP) and then to sign-in the user (change the AuthState).
We used to do this using the following algorithm: -
verifyPhoneNumber() to send OTP/Code via SMSsignInWithCredential() with the verificationId and OTP/CodeThe verifyPhoneNumber() uses the following verification callbacks (as per the Firebase docs): -
1.
onVerificationCompleted(PhoneAuthCredential)This method is called in two situations:
- Instant verification: in some cases, the phone number can be instantly verified without needing to send or enter a verification code.
- Auto-retrieval: on some devices, Google Play services can automatically detect the incoming verification SMS and perform verification without user action. (This capability might be unavailable with some carriers.)
2.
onVerificationFailed(FirebaseException)This method is called in response to an invalid verification request, such as a request that specifies an invalid phone number or verification code.
3.
onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken)This method is called after the verification code has been sent by SMS to the provided phone number.
When this method is called, most apps display a UI that prompts the user to type the verification code from the SMS message. (At the same time, auto-verification might be proceeding in the background.) Then, after the user types the verification code, you can use the verification code and the verification ID that was passed to the method to create a PhoneAuthCredential object, which you can in turn use to sign in the user. However, some apps might wait until onCodeAutoRetrievalTimeOut is called before displaying the verification code UI (not recommended).
The case you are facing is the Auto Retrieval case under the onVerificationCompleted() : -
{ verificationId: **some string**, instantVerification: false } from the plugin, which you store in a variable,{ instantVerification: true, verificationId: false } from the Plugin,This method also handles the onCodeSent() case which is the usual case but what we are not handling is the Instant Verification case under onVerificationCompleted().
In this case, the OTP is never sent in the first place, thus no Verification ID. But the user is authenticated at Firebase end.
So, to handle this case we need the custom token for signing in, which I am still figuring out how to implement it using the Firebase Cloud Functions as I am not using any backend other than Firebase.
Also, if you set the timeOutDuration to 0 when calling window.FirebasePlugin.verifyPhoneNumber(), the Auto Retrieval would be disabled and you won't receive the { instantVerification: true, verificationId: false } from the Plugin.
@YaMo97 I don't think that the custom token is necessary at all. You have two options here. Either find a way to pass the credential object that is already given to you by onVerificationCompleted to cordova and use it in the snipped or use some reflection to get the two important pieces that you need. I just wrote a quick hack using reflections to access both the verificationId plus the actual code needed for confirmation (tested and worked):
public void onVerificationCompleted(PhoneAuthCredential credential) {
try {
Field verField = credential.getClass().getDeclaredField("zzfc");
verField.setAccessible(true);
Field codeField = credential.getClass().getDeclaredField("zzfd");
codeField.setAccessible(true);
String verificationId = (String) verField.get(credential);
String code = (String) codeField.get(credential);
// TODO: return verificationId and code to cordova here
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
So we basically get both the verificationId and the required confirm code that would normally be sent via SMS from the credential object that's been passed to onVerificationCompleted.
Then simply:
// if instant verification use the code that we have extracted, otherwise use user input code
var code = credential.instantVerification ? credential.code : inputField.value.toString() ;
// and continue with the rest
var verificationId = credential.verificationId;
var credential = firebase.auth.PhoneAuthProvider.credential(verificationId, code);
and you are done.
@manuelsc I agree with you. I proposed a similar solution for the issue #718
@manuelsc would you mind to post your whole file or provide a PR? I would change the README as soon as we got your nice workaround. As I have absolutely no clue with android development, my approach was kinda hacky and also a security breach, as contacting the server on a public API isn't the real deal.
I also had the same idea as @manuelsc but never got an answer to it until now:
https://github.com/chemerisuk/cordova-plugin-firebase-authentication/issues/23
So this could be the way to go and to prevent issues with instant verification.
@Hirbod I just created a pull request https://github.com/arnesson/cordova-plugin-firebase/pull/861
As mentioned there might be even a better way but I would need feedback from a javascript dev for that.
Fixed via #861. Waiting on changes to the API docs before releasing a new version.
Most helpful comment
@YaMo97 I don't think that the custom token is necessary at all. You have two options here. Either find a way to pass the credential object that is already given to you by onVerificationCompleted to cordova and use it in the snipped or use some reflection to get the two important pieces that you need. I just wrote a quick hack using reflections to access both the verificationId plus the actual code needed for confirmation (tested and worked):
So we basically get both the verificationId and the required confirm code that would normally be sent via SMS from the credential object that's been passed to onVerificationCompleted.
Then simply:
and you are done.