Search code examples
reactjsfirebasefirebase-authenticationphone-number

Firebase: Error (auth/operation-not-allowed) when trying to sign in with phone number in Firebase Web


Below is a simple react phone number authentication in firebase. But it seems to throw an error and only works with the number, which I put in the settings of firebase for testing. I have tried different devices, but all of them seem to give the same error

The error I am getting:

FirebaseError: Firebase: Error (auth/operation-not-allowed).
    at createErrorInternal (assert.ts:136:1)
    at _fail (assert.ts:65:1)
    at _performFetchWithErrorHandling (index.ts:177:1)
    at async _verifyPhoneNumber (phone.ts:239:1)
    at async signInWithPhoneNumber (phone.ts:106:1)

My code (App.js):

function onCaptchVerify() {
    

    if (!window.recaptchaVerifier) {
      window.recaptchaVerifier = new RecaptchaVerifier(
        "recaptcha-container",
        {
          size: "visible",
          callback: (response) => {
            onSignup();
          },
          "expired-callback": () => {},
        },
        auth
      );
    }
  }

  function onSignup() {
    setLoading(true);
    onCaptchVerify();

    const appVerifier = window.recaptchaVerifier;

    const formatPh = "+" + ph;

    signInWithPhoneNumber(auth, formatPh, appVerifier)
      .then((confirmationResult) => {
        window.confirmationResult = confirmationResult;
        setLoading(false);
        setShowOTP(true);
        toast.success("OTP sended successfully!");
      })
      .catch((error) => {
        console.log(error);
        setLoading(false);
      });
  }

  function onOTPVerify() {
    setLoading(true);
    window.confirmationResult
      .confirm(otp)
      .then(async (res) => {
        console.log(res);
        setUser(res.user);
        setLoading(false);
      })
      .catch((err) => {
        console.log(err);
        setLoading(false);
      });
  }

My code (setup.js):

import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: ""
};

const app = initializeApp(firebaseConfig);

const auth = getAuth(app);


export {auth};

There are no in JSX, just buttons that call the functions

I tried public domains and localhost. The domains and localhost are both in authorised domains I have tried with multiple projects and accounts


Solution

  • I figured it out myself

    Firebase does not allow phone authentication from localhost

    1. You need to host the website with your public domain. (Free option - Netlify)
    2. Firebase => Authentication => Settings => Authorized Domains
    3. Click Add Domain
    4. if domain is https://example.com then add 2 domains (www.example.com and example.com)
    5. Try again from the hosted website and it should work

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    UPDATED WORKING CODE:

    Send OTP:

    const [phoneNumber, setPhoneNumber] = useState("");
    const [verificationCode, setVerificationCode] = useState("");
    const [verificationId, setVerificationId] = useState("");
    const recaptchaRef = useRef(null);
    
    const handleSendOtp = () => {
    
            if (recaptchaRef.current) {
                recaptchaRef.current.innerHTML = "<div id='recaptcha-verifier'></div>"
            }
    
            const verifier = new RecaptchaVerifier(auth, "recaptcha-verifier", {
                size: "invisible"
            });
    
            signInWithPhoneNumber(auth, phoneNumber, verifier)
            .then(confirmationResult => {
                setVerificationId(confirmationResult.verificationId);
            })
            .catch(error => {
                console.error("Error Sending OTP", error);
            });
        }
    

    Verify OTP:

        const handleVerifyOTP = () => {
            const credentials = PhoneAuthProvider.credential(verificationId, verificationCode);
            signInWithCredential(auth ,credentials)
            .then(userCredential => {
                console.log("User logged in", userCredential);
                console.log("Your phone number: ", userCredential.user.phoneNumber);
            })
            .catch(error => {
                console.error("huh", error);
            })
        }
    

    Verify OTP:

    import { initializeApp } from "@firebase/app";
    import { getAuth } from "@firebase/auth";
    
    const firebaseConfig = {
      //web config
    };
    
    const app = initializeApp(firebaseConfig);
    export const auth = getAuth(app);
    export default app;
    

    Installed packages:

    @firebase/app : 0.10.5
    @firebase/auth : 1.7.4
    firebase : 10.12.2