🔥 Firebase OTP (Sign In with Phone) using Webviewer

UPDATED 2025-04

There have been several requests for this in the past year, but I have not seen a solution. Here, then, is one method to allow a user to sign in to Firebase (or if you want, to just authenticate their phone number).

The method uses an html page and javascript, which allows for the use of a recaptcha in order to generate the verification code and send an SMS. I understand that Firebase allows for 10,000 free SMS per month (needs confirming under current requirements)

I am not sure for how long Firebase will continue to provide version 8 SDK links in the current format, because it is heavily pushing its tree-shaking version 9, but for now, this will work for our App Inventor apps.

I have put together a simple app that loads the html; the user enters their phone number, with + sign and country code, then the user completes the recaptcha, then the device receives an SMS with the verification code. The user copies and pastes the code to the html page, and sends the code. Once verified, the user is signed in and firebase returns the userData which includes the UID, the refreshToken and the accessToken, these can then be used to manage a users future access.

Security concerns
Authentication using only a phone number, while convenient, is less secure than the other available methods, because possession of a phone number can be easily transferred between users. Also, on devices with multiple user profiles, any user that can receive SMS messages can sign in to an account using the device's phone number.

If you use phone number based sign-in in your app, you should offer it alongside more secure sign-in methods, and inform users of the security tradeoffs of using phone number sign-in.

Updated version 2025-04:

A total re-write of the html and javascript, and hopefully we have a working solution.

Guidance - do not ignore this! :

  1. The html file MUST be hosted on a https:// file server, for the recaptcha to work correctly.

  2. I believe the webviewextra extension is required to modify the webviewer in order for it to behave correctly (it may work without, try it and see).

Files:

  1. The html file, remove the .txt from the end of the filename, after downloading.
    newfbotp.html.txt (4.3 KB)

    • You will need to add your own firebase config details to this file
    • This html file needs to be placed on an https:// file server
    • This html file should work anywhere you run its url: computer browser, mobile browser
  2. An example aia
    newFBOTP.aia (28.0 KB)

    • You will need to enter your html file url in the correct place in the blocks

image

  1. Screenshots

Tested with fictional and real phone numbers

Enjoy!

First Version July 2022 - either not working or not working reliably...

I found the solution on medium.com here:

Firebase Phone Authentication

and modified the html/css/code to interact with App Inventor (webviewstring)

BLOCKS

SCREENS

HTML
(you need to add your own Firebase project's firebaseConfig information)

<!DOCTYPE html>
<!--https://medium.com/front-end-weekly/firebase-phone-authentication-web-tutorial-2019-29f5f5c97839-->
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>OTP</title>
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
  </head>
  <body>
	  
    <div id="holder"  style="max-width:240px;margin: auto;">
		<div id="done"></div>
    <h2>OTP Sign Up</h2>
    <!-- Add two inputs for "phoneNumber" and "code" -->
    <!-- Add two buttons to submit the inputs -->
    Phone Number:<br>
    <input type="tel" id="phoneNumber" class="w3-input w3-border w3-round-large" style="width:200px" /><br>
    <button id="sign-in-button" onclick="submitPhoneNumberAuth()" class="w3-btn w3-ripple w3-blue w3-round-large" style="width:200px">
      SIGN IN WITH PHONE
    </button><br><br><br>

    <!-- Add a container for reCaptcha -->
    <div id="recaptcha-container"></div><br><br>

    OTP Code:<br>
    <input type="text" id="code" class="w3-input w3-border w3-round-large" style="width:200px" /><br>
    <button id="confirm-code" onclick="submitPhoneNumberAuthCode()" class="w3-btn w3-ripple w3-blue w3-round-large" style="width:200px">
      ENTER CODE
    </button>
    <p id="notes" style="max-width:200px;word-wrap: break-word;">1. Enter phone number with + and country code, then click Sign In with Phone<br>2. Complete the recaptcha 3. Get the OTP code from your SMS and type/paste it in, then click Enter Code</p>
    </div>
    <!-- Add the latest firebase dependecies from CDN -->
    <script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-auth.js"></script>

    <script>
      // Place your config here
      var firebaseConfig = {
        apiKey: "",
        authDomain: "",
        databaseURL: "",
        projectId: "",
        storageBucket: "",
        messagingSenderId: "",
        appId: ""
      };

      firebase.initializeApp(firebaseConfig);

      // Create a Recaptcha verifier instance globally
      // Calls submitPhoneNumberAuth() when the captcha is verified
      window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
        "recaptcha-container",
        {
          size: "invisible",
          callback: function(response) {
            submitPhoneNumberAuth();
          }
        }
      );

      // This function runs when the 'sign-in-button' is clicked
      // Takes the value from the 'phoneNumber' input and sends SMS to that phone number
      function submitPhoneNumberAuth() {
        var phoneNumber = document.getElementById("phoneNumber").value;
        var appVerifier = window.recaptchaVerifier;
        firebase
          .auth()
          .signInWithPhoneNumber(phoneNumber, appVerifier)
          .then(function(confirmationResult) {
            window.confirmationResult = confirmationResult;
          })
          .catch(function(error) {
            console.log(error);
          });
      }

      // This function runs when the 'confirm-code' button is clicked
      // Takes the value from the 'code' input and submits the code to verify the phone number
      // Return a user object if the authentication was successful, and auth is complete
      function submitPhoneNumberAuthCode() {
        var code = document.getElementById("code").value;
        confirmationResult
          .confirm(code)
          .then(function(result) {
            var user = result.user;
            //console.log(user);
            document.getElementById("done").innerHTML = "OTP completed";
            window.AppInventor.setWebViewString(JSON.stringify(user));
          })
          .catch(function(error) {
            console.log(error);
            document.getElementById("done").innerHTML = error;
          });
      }

      //This function runs everytime the auth state changes. Use to verify if the user is logged in
      firebase.auth().onAuthStateChanged(function(user) {
        if (user) {
          console.log("USER LOGGED IN");
        } else {
          // No user is signed in.
          console.log("USER NOT LOGGED IN");
        }
      });
    </script>
  </body>
</html>

Note this guide has been updated, a small change to the html, exchanging the word normal for invisible in the recaptchaVerifier section.

12 Likes

I've tried it and it works. Please help me how to get OTP automatically without having to enter a phone number like this?

If there is a method/extension that can get the phone number from the device, you could use that to automate further, edit the html to run the phone number across with webviewstring.

where can i add the code after adding my firebase data?
and which link will be added in the blocks to refer to the link?

What code?
What firebase data ?
Which link are you referring to ?

that code

<!DOCTYPE html>
<!--https://medium.com/front-end-weekly/firebase-phone-authentication-web-tutorial-2019-29f5f5c97839-->
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>OTP</title>
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
  </head>
  <body>
	  
    <div id="holder"  style="max-width:240px;margin: auto;">
		<div id="done"></div>
    <h2>OTP Sign Up</h2>
    <!-- Add two inputs for "phoneNumber" and "code" -->
    <!-- Add two buttons to submit the inputs -->
    Phone Number:<br>
    <input type="tel" id="phoneNumber" class="w3-input w3-border w3-round-large" style="width:200px" /><br>
    <button id="sign-in-button" onclick="submitPhoneNumberAuth()" class="w3-btn w3-ripple w3-blue w3-round-large" style="width:200px">
      SIGN IN WITH PHONE
    </button><br><br><br>

    <!-- Add a container for reCaptcha -->
    <div id="recaptcha-container"></div><br><br>

    OTP Code:<br>
    <input type="text" id="code" class="w3-input w3-border w3-round-large" style="width:200px" /><br>
    <button id="confirm-code" onclick="submitPhoneNumberAuthCode()" class="w3-btn w3-ripple w3-blue w3-round-large" style="width:200px">
      ENTER CODE
    </button>
    <p id="notes" style="max-width:200px;word-wrap: break-word;">1. Enter phone number with + and country code, then click Sign In with Phone<br>2. Complete the recaptcha 3. Get the OTP code from your SMS and type/paste it in, then click Enter Code</p>
    </div>
    <!-- Add the latest firebase dependecies from CDN -->
    <script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-auth.js"></script>

    <script>
      // Place your config here
      var firebaseConfig = {
        apiKey: "AIzaSyDGDOzXPI0wqU0iiRRZiHPlfv8O9U5DBZg",
  authDomain: "doctor-booking-4ec79.firebaseapp.com",
  databaseURL: "https://doctor-booking-4ec79-default-rtdb.firebaseio.com",
  projectId: "doctor-booking-4ec79",
  storageBucket: "doctor-booking-4ec79.firebasestorage.app",
  messagingSenderId: "864477148847",
  appId: "1:864477148847:web:5653b4b6d923edbe7e065a",
  measurementId: "G-2WV5EL9C1K"
      };

      firebase.initializeApp(firebaseConfig);

      // Create a Recaptcha verifier instance globally
      // Calls submitPhoneNumberAuth() when the captcha is verified
      window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
        "recaptcha-container",
        {
          size: "invisible",
          callback: function(response) {
            submitPhoneNumberAuth();
          }
        }
      );

      // This function runs when the 'sign-in-button' is clicked
      // Takes the value from the 'phoneNumber' input and sends SMS to that phone number
      function submitPhoneNumberAuth() {
        var phoneNumber = document.getElementById("phoneNumber").value;
        var appVerifier = window.recaptchaVerifier;
        firebase
          .auth()
          .signInWithPhoneNumber(phoneNumber, appVerifier)
          .then(function(confirmationResult) {
            window.confirmationResult = confirmationResult;
          })
          .catch(function(error) {
            console.log(error);
          });
      }

      // This function runs when the 'confirm-code' button is clicked
      // Takes the value from the 'code' input and submits the code to verify the phone number
      // Return a user object if the authentication was successful, and auth is complete
      function submitPhoneNumberAuthCode() {
        var code = document.getElementById("code").value;
        confirmationResult
          .confirm(code)
          .then(function(result) {
            var user = result.user;
            //console.log(user);
            document.getElementById("done").innerHTML = "OTP completed";
            window.AppInventor.setWebViewString(JSON.stringify(user));
          })
          .catch(function(error) {
            console.log(error);
            document.getElementById("done").innerHTML = error;
          });
      }

      //This function runs everytime the auth state changes. Use to verify if the user is logged in
      firebase.auth().onAuthStateChanged(function(user) {
        if (user) {
          console.log("USER LOGGED IN");
        } else {
          // No user is signed in.
          console.log("USER NOT LOGGED IN");
        }
      });
    </script>
  </body>
</html>

and the link will be added to the blocks above to view the phone verification on the app

You place your html file in the app assets (media folder)

Use http://localhost/yourhtmlfile.html to open the file in a webviewer

it worked but still didnt receive the verification code on the phone

did you try it lately to make sure that is the firebase still free or no longer free?

Not sure what is going on, the test with the demo number works OK so it seems the script is still working (but the demo doesn't actually send an sms.)

Firebase appears to have locked me out now, due to live testing, so will have to come back to this later.

1 Like

Figured it out.

Tested the html (loaded onto server) in Chrome on my device and it worked!

Seems newer restrictions (unknown to me) now prevent the native webviewer working by itself.

Add the webviewextra extension, and it should then work. On first test I had to press "SIGN IN WITH PHONE" twice to get the recaptcha to come up.

Lets check what is missing in my blocks and data


index.txt (4.6 KB)


image

Look at my blocks above.

I generally set the webviewer to webviewextra in the Screen.Initialise block

Then in the button event set the url. You are not setting the url ?

The questions are:

"Are you getting an SMS ?"

"Are you entering the otp provided in the SMS into the web page?"

"is this creating a user in your firebase console authenticated users page?"

lets test that sample file i created please to help me to figure the issue out

I have removed your firebase config and your aia (which contains your firebase config), you should not post all of that here.

Your aia file looks OK.

Have you tested with a dummy number ? (this will not send an sms but will test everything else)

image

Have you tested with a real number ?

i added my number

and tested it in the app but didnt work
did you test a real number in my aia file?

No, of course not.

Do not add your own number in the test area, this will not work.

Use a number like the one provided by default.

After entering the phone number in the app, you enter the otp (verification code)
This should create a new user.

To test your own phone number, enter it in the app, do the recaptcha, wait for the sms with the otp

This is a tested number added in the site not real


It showed the data like that so is it working well but I didn't receive an sms in my real number

Tonight, for me, the test number works OK, but a real number does not, not even in the mobile Chrome.

I will need to go over the javascript again, against the guidance from Firebase.

Update 2025-04

There have been some changes to how Firebase operates:

  • html and javascript completely overhauled to get this thing working reliably
  • requirement to host the html page on an https:// server
  • works best when using the webviewextra extension along with the webviewer

See the first post for more details and downloads.