We all know that feeling. You don’t have a concrete idea about the solution you are looking for and you want to see a quick answer for your question. So, check the short answer below:
Short answer to your question
Long answer to your question
To implement a resend SMS feature on my ReactJS app, I went through this documentation. And I realised that there wasn’t any resend SMS support by Firebase.auth. Interestingly, there was no blog or stackoverflow ticket discussing the issue either. Then, I assumed that the developers, who came across with the same problem, silently implemented a resend SMS feature by simply re-initialising the whole process on their web applications. Therefore, I decided to break this silence by writing this post and helping future developers (and maybe even future self 🙂 ).
Assume that your application shows two components to the user. First component will receive the phone number from the user and after the SMS is sent, the second component will demand the user to type in the verification code.
Your first component should run following methods in order:
- Initialize recaptcha
- window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(…);
- Sign in with given phone number
- auth.signInWithPhoneNumber(phoneNumber, appVerifier);
- Reset or even remove recaptcha
Above is a rough sequence of the operations that you should follow and I believe you already know how these work.
When your application moves to the second component, you may wish to use the existing implementation (the functions in the first component) by passing the functions as arguments in React. However, this approach creates some trouble for the RecaptchaVerifier, because you already used the recaptcha session to send the first SMS and if your user attempts to send the SMS again, you will need a new recaptcha session. Plus, you will also need a recaptcha container in your second component as well. Recaptcha container is the place that grecaptcha-badge will be loaded in an iframe. In order to avoid these conflicts, I have implemented the same set of methods in the second component as well. And to prevent any other potential conflicts, I created a separate recaptcha-container with a new id.
First component’s container:
<div id=”recaptcha-container” />
Second component’s container:
<div id=”recaptcha-container-resend” />
So that, the user may resend SMS verification several times more as long as RecaptchaVerifier does not believe that the user is a robot 🙂
Always use forms
See the screenshot below from my web application. The user interface is in Norwegian 🇳🇴 🙂
We basically have one text box for the phone number and a submit button. So, this has to be implemented as a form, right? The picture below shows a simplified JSX code for this form:
A good practice is to place the recaptcha-container at the bottom of the form. So that, there will be no confusing accessibility issues for the blind people. Also, we initialise the sign in process via this.handleSubmit call. This approach provides an advantage for desktop users, because handleSubmit will allow triggering the recaptcha check by pressing [ENTER] button while the focus is on phoneNumberInput element (<input … />). As a result of these benefits, always use forms while implementing Firebase SMS Verification interface.
Watch out for unknown error states
PhoneAuthProvider gives you a list of error codes, but there is no documentation for all errors. (See documentation here.) One of these obscure errors is auth/code-expired. This error is triggered when the user enters the wrong SMS code three consecutive times.
Recaptcha window is not responsive
This is another unfortunate case with Firebase Recaptcha services. Captcha pictures presented inside the iframe have fixed width and critical recaptcha buttons become invisible and non-scrollable for the users with very small mobile screens (such as iPhone5). To fix this issue, I recommend using some media query on grecaptcha-badge CSS class. See the code below:
The result is not perfect, but it keeps the iPhone 5 users in the game.
Use libphonenumber-js for formatting
If you’d like to format the phone number inside the text box (<input className=”phoneNumberInput” … />), libphonenumber-js is a great utility. You can apply required country code settings by simply adding 3 lines of code into your application. You can learn more about AsYouType formatter by the URL below:
Credits to my colleague Iva Ivanova 👩🔧 on this final tip.
That’s all folks! See you next time with another challenge!
Sercan Leylek / OSLO