在 Expo 中使用第三方短信提供商进行 Firebase 电话登录

问题描述

我正在考虑使用第 3 方 SMS 提供商在 Expo 中使用 firebase 电话登录,因为即使在设置 const attemptInvisibLeverification = true; 后,我也无法在 Android 上使用 this code 可靠地禁用 Recaptcha。

因此,我计划在使用 firebase 创建用户的同时使用 3rd 方 SMS 提供商(例如 Twilio)发送 SMS。这样我就可以绕过使用 Recaptcha。如果您发现这有什么问题,请告知我该如何解决

// <project_root>/functions/index.js

const functions = require('firebase-functions');
const admin = require('firebase-admin');

/*
  set environment variables via terminal
  $ firebase functions:config:set twilio.account=<accountSid> twilio.token=<authToken> twilio.from=<your from number>
*/
const config = functions.config();
const twilio = require('twilio')(config.twilio.account,config.twilio.token);

/*
  Now you need to download a private cert (service-account.json)
  https://firebase.google.com/docs/admin/setup#add_firebase_to_your_app
  and add add it to your /functions directory (don't forget to .gitignore it)
*/
const serviceAccount = require('./service-account.json');
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),databaseURL: 'https://<your-project-id>.firebaseio.com',});

// Looks for user by phone number. If found (new log in),sends
// verfication. If not found (new sign up),creates new user and
// sends verification
exports.logInWithPhoneNumber = functions.https.onRequest((req,res) => {
  const { phone } = req.body;
  admin
    .auth()
    .getUserByPhoneNumber(phone)
    .then(userRecord => sendSMsverification(res,userRecord.uid,phone))
    .catch(error => {
      switch (error.code) {
        case 'auth/user-not-found':
          return createuser();
        default:
          return sendError(error);
      }
    });

  const createuser = () => {
    admin
      .auth()
      .createuser({
        phoneNumber: phone,})
      .then(({ uid }) => sendSMsverification(res,uid,phone))
      .catch(sendError);
  };

  const sendError = error => res.status(422).send(error);

  const sendSMsverification = (res,phone) => {
    const code = Math.floor(Math.random() * 899999 + 100000);
    const expiration = Date.Now() + 2 * 60000; // Expires in 2 minutes
    const verification = { code,expiration,valid: true };
    const setUser = message => {
      admin
        .firestore()
        .collection('users')
        .doc(uid)
        .set({ verification })
        .then(() => res.send({ success: true }))
        .catch(sendError);
    };
    twilio.messages
      .create({
        body: `Your family code is ${code}`,to: phone,from: config.twilio.from,})
      .then(setUser)
      .catch(sendError);
  };
});

exports.verifyToken = functions.https.onRequest((req,res) => {
  // Validate code and expiration time,ensuring that code hasn't been used before.
  // If matches,create custom auth token and then invalidate code
  const { code,phone } = req.body;
  const sendError = error => res.status(422).send({ error: error.message });

  admin
    .auth()
    .getUserByPhoneNumber(phone)
    .then(userRecord => {
      return admin
        .firestore()
        .collection('users')
        .doc(userRecord.uid)
        .get();
    })
    .then(doc => {
      if (!doc.exists) {
        return Promise.reject(new Error('custom/uid-not-found'));
      }

      const timeNow = Date.Now();
      const { verification } = doc.data();
      let error = null;

      if (verification.code !== parseInt(code,10)) {
        error = 'custom/code-does-not-match';
      } else if (!verification.valid) {
        error = 'custom/code-already-used';
      } else if (timeNow > verification.expiration) {
        error = 'custom/code-expired';
      }

      if (error) {
        return Promise.reject(new Error(error));
      }

      doc.ref.update({ 'verification.valid': false });
      return Promise.resolve(doc.id);
    })
    .then(uid => admin.auth().createCustomToken(uid))
    .then(token => res.send({ token }))
    .catch(sendError);
});

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)