DEV Community

Discussion on: To the Stars with Quasar & Firebase - Email Authentication

Collapse
 
engineervix profile image
Victor Miti

Thanks @adamkpurdy for this excellent and well written series. It has been very helpful for me! I'm trying to add the phone sign-in option and I'm facing some challenges. Here's how I did it:

1. Create a phone.js file in the services/firebase directory, with the following content:

import firebase from 'firebase/app'
import 'firebase/auth'

/**
 * https://firebase.google.com/docs/reference/js/firebase.auth.Auth.html#signinwithphonenumber
 *
 * @param {String} phoneNumber - A Valid phone number
 * @param {String} applicationVerifier - For abuse prevention
 *
 * @return {Promise} ConfirmationResult
 */
export const authenticateWithPhone = async (phoneNumber, applicationVerifier) => {
  return firebase.auth().signInWithPhoneNumber(phoneNumber, applicationVerifier)
}

Enter fullscreen mode Exit fullscreen mode

2. Add the following to services/firebase/base.js

/**
 * firebase.auth.RecaptchaVerifier
 * https://firebase.google.com/docs/reference/js/firebase.auth.RecaptchaVerifier
 */
export const RecaptchaVerifier = (container, params) => {
  return new firebase.auth.RecaptchaVerifier(container, params)
}
Enter fullscreen mode Exit fullscreen mode

3. Update services/firebase/index.js

import * as base from './base.js'
import * as email from './email.js'
import * as phone from './phone.js'

// export default Object.assign({}, base, email, phone)
Enter fullscreen mode Exit fullscreen mode

4. Add the following to store/auth/actions.js

export const authenticateUser = async function ($root, payload) {
  const $fb = this.$fb
  const { phoneNumber, applicationVerifier } = payload
  return $fb.authenticateWithPhone(phoneNumber, applicationVerifier)
}
Enter fullscreen mode Exit fullscreen mode

Now, In my Signup.vue file, I have a <div id="recaptcha-container"></div> in the <template> section, and the <script> section looks like this

import { mapActions } from "vuex";
import { VueTelInput } from "vue-tel-input";
import "vue-tel-input/dist/vue-tel-input.css";
export default {
  name: "Signup",
  data() {
    return {
      phone: "",
      applicationVerifier: "",
      otp: ""
    };
  },
  methods: {
    ...mapActions("auth", ["authenticateUser"]),
    onSubmit() {
      const { phone, applicationVerifier } = this;
      this.$refs.phoneAuthForm.validate().then(async success => {
        if (success) {
          // do something;
          try {
            await this.authenticateUser({ phone, applicationVerifier });
            this.$router.push({ path: "/" });
          } catch (err) {
            console.error(err);
            this.$q.notify({
              message: `An error has occured: ${err}`,
              color: "negative"
            });
          } finally {
            this.$q.loading.hide();
          }
        }
      });
    },
    initReCaptcha() {
      window.recaptchaVerifier = this.$fb.RecaptchaVerifier(
        "recaptcha-container",
        {
          size: "invisible",
          // eslint-disable-next-line no-unused-vars
          callback: response => {
            // reCAPTCHA solved, allow signInWithPhoneNumber.
            // this.onSubmit();
          }
        }
      );
      this.applicationVerifier = window.recaptchaVerifier;
    }
  },
  created: function() {
    this.initReCaptcha();
  },
  components: {
    VueTelInput
  }
};
Enter fullscreen mode Exit fullscreen mode

However, when I run this, I get the following error in the browser console: Error in created hook: "Error: reCAPTCHA container is either not found or already contains inner elements!"

Any advice on how I can fix this?

Here's a screenshot:

screenshot

Collapse
 
adamkpurdy profile image
Adam Purdy

Hi Victor. I used phone auth a while back on another project. I did a few things differently with success by using the mounted lifecycle method to assign the reCaptcha to the Vue instance.

mounted () {
    this.recaptchaVerifier = this.$fb.recaptcha('phoneNumberSubmit')
  }
Enter fullscreen mode Exit fullscreen mode

Also, based on your code it looks like your passing only a single argument in your authenticateUser call. Where your function signature is set up for two arguments. Try removing your object data structure and just pass the two arguments.

I did a couple of other things differently, but that might be what's holding you up. I have plans on releasing a phone auth article in the future once Quasar v2 gets out of beta. If you have any other problems feel free to come and find me in the Quasar discord. #firebase => @adam (EN/US)