angular / angularfire

Angular + Firebase = ❤️
https://firebaseopensource.com/projects/angular/angularfire2
MIT License
7.69k stars 2.19k forks source link

Runtime Error: Firebase Phone Verification with Ionic or Cordova Never Works #1782

Closed ghost closed 6 years ago

ghost commented 6 years ago

Version info

Angular: ionic-angular 3.9.2

AngularFire: 5.0.0-rc.11

Other (e.g. Ionic/Cordova, Node, browser, operating system):

(Cordova CLI) : 8.0.0

ionic (Ionic CLI) : 3.20.0

Android SDK Tools : 25.2.5 ios-deploy : 1.9.1 ios-sim : 5.0.8 Node : v8.11.3 npm : 6.1.0 OS : macOS High Sierra Xcode : Xcode 9.4

How to reproduce these conditions

Git Repo : https://github.com/freelancersunil/firebase-phone-auth-ionic3-otp

Steps to set up and reproduce Component HTML File:

<div id="recaptcha-container"></div>

  <ion-item>
    <ion-label stacked>Phone Number</ion-label>
    <ion-input type="number" [(ngModel)]="phoneNumber"></ion-input>
  </ion-item>

  <button ion-button id="sign-in-button" (click)="signIn(phoneNumber)">
    Sign In
  </button>

TS file:

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';

import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';

/**
 * Generated class for the LoginPage page.
 *
 * See https://ionicframework.com/docs/components/#navigation for more info on
 * Ionic pages and navigation.
 */

@IonicPage()
@Component({
  selector: 'page-login',
  templateUrl: 'login.html',
})
export class LoginPage {

  constructor(public navCtrl: NavController, public navParams: NavParams, public afAuth: AngularFireAuth) {
  }

  afterViewInit() {
    this.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
  }

  signIn(phoneNumber: any, appVerifier: any) {
    this.afAuth.auth.signInWithPhoneNumber(phoneNumber, appVerifier)
      .then((confirmationResult) => {
        // SMS sent. Prompt user to type the code from the message, then sign the
        // user in with confirmationResult.confirm(code).
           let prompt = this.alertCtrl.create({
        title: 'Enter the Confirmation code',
        inputs: [{ name: 'confirmationCode', placeholder: 'Confirmation Code' }],
        buttons: [
          { text: 'Cancel',
            handler: data => { console.log('Cancel clicked'); }
          },
          { text: 'Send',
            handler: data => {
              confirmationResult.confirm(data.confirmationCode)
                .then(function (result) {
                  // User signed in successfully.
                  console.log(result.user);
                  // ...
                }).catch(function (error) {
                  // User couldn't sign in (bad verification code?)
                  // ...
                });
            }
          } 
        ]
      });
      prompt.present();
        console.log(confirmationResult);
      }).catch((error) => {
        // Error; SMS not sent
        // ...
      });
  }

}

Debug output

Runtime Error:
signInWithPhoneNumber failed: Second argument "applicationVerifier" must be an implementation of firebase.auth.ApplicationVerifier.

Typescript Error
Property 'recaptchaVerifier' does not exist on type 'LoginPage'.
ghost commented 6 years ago

@team (AngularFire2) / (Firebase) is this true about Ionic or Cordova for Firebase phone Auth ?

https://stackoverflow.com/questions/44081040/ionic2-authentication-firebase

ghost commented 6 years ago

@davideast May I please request the team to comment on this one, please, anyone?

ceekem commented 6 years ago

hi @Freelancersunil, you should have this

ionViewDidLoad() { this.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container'); }

after the constructor and also declare

public recaptchaVerifier:firebase.auth.RecaptchaVerifier;

before the constructor. hope this helps

ahmedjsdev commented 6 years ago

Hi @freelancersunil ,, if you working with ionic, you should go to native implementation of firebase phone authentication

ionic cordova plugin add cordova-plugin-firebase npm install --save @ionic-native/firebase After Installation import { Firebase } from '@ionic-native/firebase'; and provide it in providers array in app.module.ts

login.html `

<ion-list>

    <ion-item>
        <ion-label stacked>Phone Number</ion-label>
        <ion-input type="number" [(ngModel)]="phoneNumber"></ion-input>
        <ion-input type="text" [(ngModel)]="code" placeholder="eg:123456" *ngIf="showCodeInput"></ion-input>
    </ion-item>

    <ion-item>
        <button full ion-button (click)="signInWithPhoneNumber(phoneNumber)" *ngIf="!showCodeInput" icon-left>Login with Number</button>
        <button full ion-button (click)="verify()" *ngIf="showCodeInput">Verify Code</button>
    </ion-item>

</ion-list>

`

login.ts

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import * as firebase from 'firebase'
import { Firebase } from '@ionic-native/firebase';

@IonicPage({
  name: "login"
})

@Component({
  selector: 'page-login',
  templateUrl: 'login.html',
})
export class LoginPage {
  verificationId: any;
  code = '';
  showCodeInput = false;
  constructor(public navCtrl: NavController, public navParams: NavParams, private FireBase: Firebase) { }

  PhoneLoginNative(phoneNumber) {
    console.log(phoneNumber);
    this.FireBase.verifyPhoneNumber(`+${phoneNumber}`, 60)
      .then((credential) => {
        console.log(credential);
        this.verificationId = credential.verificationId;
        this.showCodeInput = true;
      }).catch((error) => console.error(error));
  }

  verify() {
    let signInCredential = firebase.auth.PhoneAuthProvider.credential(this.verificationId, this.code);
    firebase.auth().signInWithCredential(signInCredential).then((success) => {
      console.log(success);
    })
  }

}

I Hope This Will Help You ^^

jeroScript commented 4 years ago

the problem is that the firebase auth sms service will only send messages when the app is in production mode (uploaded to the store). But to be able to test the methods from test mode, it is adding a test number in the white list of firebase.

my code in de the service is the next:

    sendSmsVerification(phoneNumber): Promise <firebase.auth.UserCredential> {
        return new Promise((resolve, reject) => {
            firebase.auth().useDeviceLanguage();
            var verificationId;
            var code;
            const timeOutDuration = 60;
            const tell = '+54' + phoneNumber;
            this.FireBase.verifyPhoneNumber(tell, timeOutDuration).then(async (credential) => {
                // alert(credential.instantVerification);
                if (credential.verificationId) {
                    console.log("Android credential: ", credential);
                    verificationId = credential.verificationId;
                } else {
                    console.log("iOS credential: ", credential);
                    verificationId = credential;
                }
                if (credential.instantVerification) {
                    code = credential.code;
                    this.verifySms(verificationId, code)
                    .then( resp => {
                        resolve(resp);
                    })
                    .catch( err => {
                        reject(err);
                    });
                } else {
                    let prompt = await this.alertCtrl.create({
                        backdropDismiss: false,
                        header: 'Ingrese el codigo de confirmación del SMS.',
                        inputs: [{ name: 'confirmationCode', placeholder: 'Código de confirmación' }],
                        buttons: [
                            { text: 'Cancelar',
                            handler: data => { 
                                console.log('Cancel clicked');
                                resolve(data);
                            }
                            },
                            { text: 'Verificar',
                            handler: data => {
                                code = data.confirmationCode; 
                                this.verifySms(verificationId,code)
                                .then( resp => {
                                    resolve(resp);
                                })
                                .catch( err => {
                                    reject(err);
                                });                            
                              }
                            }
                        ]
                    });
                    prompt.present();
                }
            }).catch(error => {
                console.log('Error! Catch SMSVerificacion', error);
                reject(error);
            });
        })
    }


    verifySms(verificationId, code): Promise <any> {
        console.log('parametros de verifySms ', verificationId +' ', code);
        const signInCredential = firebase.auth.PhoneAuthProvider.credential(verificationId,code);
        return firebase.auth().signInAndRetrieveDataWithCredential(signInCredential);
    }
DrDaxter commented 3 years ago

did Someone find any other way? I was unable to use "ionic cordova plugin add cordova-plugin-firebase" due android@0.0.9 is not supported