5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Firebaseの電話番号認証の代わりにAuthyを使う

Last updated at Posted at 2020-01-03

こちらの記事でFirebaseの電話番号認証を使用してみましたが、SMSの送信に関してどうにも不安定なので、代替策としてTwilioのAuthyを使ってみます。

Firebase Authenticationでのユーザー管理は別に実装するとして、SMSの送信・トークンの認証までをCloud Functions上で簡単に動作確認してみました。
なお、Cloud Functionsで外部APIを叩くため、FirebaseプロジェクトはFlameプラン($25/月)かBlazeプラン(従量制)である必要があります。

ソースコードやスクリーンショットはExpo・ReactNativeでのアプリ開発を想定していますが、本質的な部分はなんでも共通なはずなので、画面の構築に関するコードは省略しています。

AuthyのAPI Keyを取得

Twilioのアカウント、プロジェクトを作成後、開発者ページの左のメニューからAuthyを選択し、プロジェクトに導入します。
最初は500円の無料枠があり、一回SMSを送るたびに10円前後減っていきます。
Twilio_Console_-_Authy_Dashboard.jpg
この後チュートリアルのようなページになりますが、APIキーがコピーできた段階で中断してOKです。

Cloud Functionsに関数を追加

AuthyのAPIを使うためのパッケージはいくつかあり、
公式のドキュメントではauthyが使われているのですが、
Cloud FunctionsのPromiseチェーンで扱いやすいためauthy-clientを使用してみます。

$ cd functions
$ npm install --save authy-client
functions/index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const AuthyClient = require("authy-client").Client;

admin.initializeApp();
const db = admin.firestore();
const authy = new AuthyClient({ key: "ここに APIキー" });

Cloud Functionsのセットアップについては省略します。
まずFirestoreを扱うための準備と、authy-clientにAPIキーを渡してAuthyクライアントを初期化します。

SMS送信・DBに保存する関数

verifyPhoneNumber関数を追加します。国コード、メールアドレス、電話番号からAuthyにユーザーを追加して、AuthyでのユーザーIDを含めてFirestoreのmembersコレクションにユーザー情報を保存します。
クライアント側にはmemberドキュメントのIDを返して、あとから認証コードと照らし合わせるためのIDとして使います。

functions/index.js
exports.verifyPhoneNumber = functions.https.onCall(
  ({ countryCode, email, phoneNumber }) => {
    return authy
      .registerUser({
        countryCode,
        email,
        phone: phoneNumber
      })
      .then(response => {
        return response.user.id;
      })
      .then(authyId => {
        return Promise.all([
          db.collection("members").add({
            authyId,
            email,
            countryCode,
            phoneNumber,
            phoneNumberVerification: false,
            createdAt: admin.firestore.Timestamp.now()
          }),
          authy.requestSms({ authyId })
        ]);
      })
      .then(([docRef]) => {
        return docRef.id;
      });
  }
);

認証コードと照らし合わせる関数

クライアント側からはmemberドキュメントのIDと、SMSで送られてきた認証コードを渡して、functionsでこれを照らし合わせます。
認証が成功したら、memberドキュメントのphoneNumberVerificationフラグをtrueにするなど、適宜処理します。

functions/index.js
exports.verifyPhoneNumberToken = functions.https.onCall(({ id, token }) => {
  const docRef = db.collection("members").doc(id);
  return docRef
    .get()
    .then(docSnapshot => {
      return authy.verifyToken({
        authyId: docSnapshot.data().authyId,
        token
      });
    })
    .then(() => {
      return docRef.update({
        phoneNumberVerification: true
      });
    })
    .then(() => {
      return docRef.get();
    });
});

クライアント側の処理

このように電話番号を入力する画面を用意し、

PNGイメージ 12.png

Cloud Functionsの関数(verifyPhoneNumber)を叩きます。countryCodeemailはひとまず固定で。
関数から返ってきたIDはstateに保持しておきます。

App.js
verifyPhoneNumber = async values => {
  const { phoneNumber } = values;
  try {
    const {
      data: verificationId
    } = await firebase.functions().httpsCallable("verifyPhoneNumber")({
      countryCode: "81",
      phoneNumber,
      email: "test@test.com"
    });
    console.log("verificationId", verificationId);
    this.setState({ verificationId });
  } catch (e) {
    console.log(e);
  }
};

Authy APIが無事に通ったら、入力した電話番号にSMSが届くはずです。画像のauth-testの部分はTwilioで設定したAuthyのプロジェクト名が入ります。
PNGイメージ.png

stateにverificationIdがセットされたら認証コードの入力欄を表示するようにします。

PNGイメージ.png

あとは、再びCloud Functionsの関数(verifyPhoneNumberToken)を叩き、入力された認証コードを照らし合わせます。

App.js
verifyPhoneNumberToken = async values => {
  const { verificationId } = this.state;
  const { verificationCode } = values;
  try {
    const { data: member } = await firebase
      .functions()
      .httpsCallable("verifyPhoneNumberToken")({
      id: verificationId,
      token: verificationCode
    });
    console.log(member);
    Alert.alert("成功", "認証が完了しました");
  } catch (e) {
    console.log(e);
  }
};

Firestoreにmemberドキュメントが追加されており、phoneNumberVerificationフラグがtrueになっているのが確認できました。

Test_Project_–_Database_–_Firebase_console.jpg
5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?