如何使用Firebase的'verifyPhoneNumber()'来确认电话#的所有权而不使用#进行登录?

问题描述 投票:0回答:2

我在项目中使用react-native-firebase v5.6。

目标:在注册流程中,我让用户输入了他们的电话号码,然后我向该电话号码发送了OTP。我希望能够将用户输入的代码与从Firebase发送的代码进行比较,以便能够将条目授予注册的后续步骤。

问题:用户获得了SMS OTP和所有内容,但是phoneAuthSnapshot返回的firebase.auth().verifyPhoneNumber(number).on('state_changed', (phoneAuthSnapshot => {})对象没有为firebase发送的代码提供值,因此没有什么可与用户输入的代码进行比较。但是,verificationId属性有一个值。这是上述方法返回的对象:

'Verification code sent', { 
  verificationId: 'AM5PThBmFvPRB6x_tySDSCBG-6tezCCm0Niwm2ohmtmYktNJALCkj11vpwyou3QGTg_lT4lkKme8UvMGhtDO5rfMM7U9SNq7duQ41T8TeJupuEkxWOelgUiKf_iGSjnodFv9Jee8gvHc50XeAJ3z7wj0_BRSg_gwlN6sumL1rXJQ6AdZwzvGetebXhZMb2gGVQ9J7_JZykCwREEPB-vC0lQcUVdSMBjtig',
  code: null,
  error: null,
  state: 'sent' 
}

这是我在屏幕上的实现:

firebase
  .firestore()
  .collection('users')
  .where('phoneNumber', '==', this.state.phoneNumber)
  .get()
  .then((querySnapshot) => {
    if (querySnapshot.empty === true) {
      // change status
      this.setState({ status: 'Sending confirmation code...' });
      // send confirmation OTP
      firebase.auth().verifyPhoneNumber(this.state.phoneNumber).on(
        'state_changed',
        (phoneAuthSnapshot) => {
          switch (phoneAuthSnapshot.state) {
            case firebase.auth.PhoneAuthState.CODE_SENT:
              console.log('Verification code sent', phoneAuthSnapshot);
              this.setState({ status: 'Confirmation code sent.', confirmationCode: phoneAuthSnapshot.code });

              break;
            case firebase.auth.PhoneAuthState.ERROR:
              console.log('Verification error: ' + JSON.stringify(phoneAuthSnapshot));
              this.setState({ status: 'Error sending code.', processing: false });
              break;
          }
        },
        (error) => {
          console.log('Error verifying phone number: ' + error);
        }
      );
    }
  })
  .catch((error) => {
    // there was an error
    console.log('Error during firebase operation: ' + JSON.stringify(error));
  });

如何获取从Firebase发送的代码以进行比较?

firebase firebase-authentication react-native-firebase
2个回答
1
投票

Firebase firebase.auth.PhoneAuthProvider不会为您提供要比较的代码,您必须使用verificationId来验证用户输入的verificationCode。 firebase文档中有一个使用firebase.auth.PhoneAuthProvider.credential的基本示例,然后尝试通过firebase.auth().signInWithCredential(phoneCredential)使用这些凭据登录:

firebase
  .firestore()
  .collection('users')
  .where('phoneNumber', '==', this.state.phoneNumber)
  .get()
  .then((querySnapshot) => {
    if (querySnapshot.empty === true) {
      // change status
      this.setState({ status: 'Sending confirmation code...' });
      // send confirmation OTP
      firebase.auth().verifyPhoneNumber(this.state.phoneNumber).on(
        'state_changed',
        (phoneAuthSnapshot) => {
          switch (phoneAuthSnapshot.state) {
            case firebase.auth.PhoneAuthState.CODE_SENT:
              console.log('Verification code sent', phoneAuthSnapshot);
              // this.setState({ status: 'Confirmation code sent.', confirmationCode: phoneAuthSnapshot.code });

              // Prompt the user the enter the verification code they get and save it to state
              const userVerificationCodeInput = this.state.userVerificationCode;
              const phoneCredentials = firebase.auth.PhoneAuthProvider.credential(
                phoneAuthSnapshot.verificationId, 
                userVerificationCodeInput
              );

              // Try to sign in with the phone credentials
              firebase.auth().signInWithCredential(phoneCredentials)
                .then(userCredentials => {
                  // Sign in successfull
                  // Use userCredentials.user and userCredentials.additionalUserInfo 
                })
                .catch(error => {
                  // Check error code to see the reason
                  // Expect something like:
                  // auth/invalid-verification-code
                  // auth/invalid-verification-id
                });

              break;
            case firebase.auth.PhoneAuthState.ERROR:
              console.log('Verification error: ' + JSON.stringify(phoneAuthSnapshot));
              this.setState({ status: 'Error sending code.', processing: false });
              break;
          }
        },
        (error) => {
          console.log('Error verifying phone number: ' + error);
        }
      );
    }
  })
  .catch((error) => {
    // there was an error
    console.log('Error during firebase operation: ' + JSON.stringify(error));
  });

0
投票

@christos-lytrastheir answer中一样,验证码不会公开给您的应用程序。

出于安全原因完成此操作,因为向设备本身提供用于out of band authentication的代码将使知识渊博的用户只需将代码从内存中取出并进行身份验证,就好像他们可以访问该电话号码一样。

一般的操作流程是:

  1. 获取要验证的电话号码
  2. 将该数字与verifyPhoneNumber()一起使用,并缓存返回的验证ID
  3. 提示用户输入代码(或自动获取代码)
  4. 使用firebase.auth.PhoneAuthProvider.credential(id, code)将ID和用户输入作为凭证捆绑在一起>
  5. [尝试使用该凭据登录firebase.auth.PhoneAuthProvider.credential(id, code)
  6. 在源代码中,您还使用firebase.auth().signInWithCredential(credential)方法的firebase.auth().signInWithCredential(credential)侦听器。但是,此方法还支持使用Promises的on(event, observer, errorCb, successCb),它允许您链接到Firebase查询。如下所示。

发送验证码:

verifyPhoneNumber(phoneNumber)

处理用户来源的验证码:

listening to results

API参考:

  • [firebase .firestore() .collection('users') .where('phoneNumber', '==', this.state.phoneNumber) .get() .then((querySnapshot) => { if (!querySnapshot.empty) { // User found with this phone number. throw new Error('already-exists'); } // change status this.setState({ status: 'Sending confirmation code...' }); // send confirmation OTP return firebase.auth().verifyPhoneNumber(this.state.phoneNumber) }) .then((phoneAuthSnapshot) => { // verification sent this.setState({ status: 'Confirmation code sent.', verificationId: phoneAuthSnapshot.verificationId, showCodeInput: true // shows input field such as react-native-confirmation-code-field }); }) .catch((error) => { // there was an error let newStatus; if (error.message === 'already-exists') { newStatus = 'Sorry, this phone number is already in use.'; } else { // Other internal error // see https://firebase.google.com/docs/reference/js/firebase.firestore.html#firestore-error-code // see https://firebase.google.com/docs/reference/js/firebase.auth.PhoneAuthProvider#verify-phone-number // probably 'unavailable' or 'deadline-exceeded' for loss of connection while querying users newStatus = 'Failed to send verification code.'; console.log('Unexpected error during firebase operation: ' + JSON.stringify(error)); } this.setState({ status: newStatus, processing: false }); }); -codeInputSubmitted(code) { const { verificationId } = this.state; const credential = firebase.auth.PhoneAuthProvider.credential( verificationId, code ); // To verify phone number without interfering with the existing user // who is signed in, we offload the verification to a worker app. let fbWorkerApp = firebase.apps.find(app => app.name === 'auth-worker') || firebase.initializeApp(firebase.app().options, 'auth-worker'); fbWorkerAuth = fbWorkerApp.auth(); fbWorkerAuth.setPersistence(firebase.auth.Auth.Persistence.NONE); // disables caching of account credentials fbWorkerAuth.signInWithCredential(credential) .then((userCredential) => { // userCredential.additionalUserInfo.isNewUser may be present // userCredential.credential can be used to link to an existing user account // successful this.setState({ status: 'Phone number verified!', verificationId: null, showCodeInput: false, user: userCredential.user; }); return fbWorkerAuth.signOut().catch(err => console.error('Ignored sign out error: ', err); }) .catch((err) => { // failed let userErrorMessage; if (error.code === 'auth/invalid-verification-code') { userErrorMessage = 'Sorry, that code was incorrect.' } else if (error.code === 'auth/user-disabled') { userErrorMessage = 'Sorry, this phone number has been blocked.'; } else { // other internal error // see https://firebase.google.com/docs/reference/js/firebase.auth.Auth.html#sign-inwith-credential userErrorMessage = 'Sorry, we couldn\'t verify that phone number at the moment. ' + 'Please try again later. ' + '\n\nIf the issue persists, please contact support.' } this.setState({ codeInputErrorMessage: userErrorMessage }); }) } verifyPhoneNumber()
  • [React Native-Firebase
  • [PhoneAuthProvider.credential(id, code)-FirebasesignInWithCredential()
  • 建议的代码输入组件:

© www.soinside.com 2019 - 2024. All rights reserved.