Help us understand the problem. What is going on with this article?

Firebase authで電話番号(SMS)認証を行う方法 (Web)

More than 1 year has passed since last update.

概要

認証にFirebase authを使っているWebサービスで、アカウントに対して電話番号認証をさせ認証情報をリンクさせる仕組みを導入します。

動機

Webサービスにおいて一人にたくさんのアカウントを作られることを防ぎたいというのは割とよくあるケースだと思います。

このときに使える方法のひとつが電話番号(SMS)認証です。SMSで4桁とか6桁の数字を送ってユーザーに入力させるアレです。
メールアドレスとちがい電話番号は無料でいくらでも作るということはできないので、アカウントの開通に電話番号の確認を要求するようにすることは有効な手段です。

ちなみにFirebase authでは電話番号をログイン情報に使うこともできますが、今回はログインはあくまでGoogleやGithubなどOAuthを使い、電話番号認証は既存のアカウントに紐付ける方法についてです。

リポジトリ

https://github.com/k5trismegistus/firebase-auth-sms-2fa-demo

今回作成したデモアプリはこのリポジトリにあります。

さくっと動かすためにNuxt.jsを使っています。

流れ

Firebase authで既存アカウントに対して電話番号認証を行う際の流れは次のようになります。

  1. ユーザーに電話番号を紐付ける対象のアカウントでログインしてもらう
  2. ユーザーに電話番号を入力させる
  3. 入力された電話番号に確認コードを送信する
  4. 2の時点で払い出されるトークンと、SMSを受け取ったユーザーが入力する確認コードを使って認証を行う
  5. 得られた認証情報をアカウントとリンクさせる

実装

1については詳細を省略します。

2. ユーザーに電話番号を入力させる & 3. 入力された電話番号に確認コードを送信する

これは意外に思ったのですが、電話番号認証はポップアップなりリダイレクトなりでGoogleの用意したUIを使うのではありませんでした。電話番号や確認コードの入力フォームは自分で用意する必要があります。

ユーザーに確認コードを送信すると、その確認コード送信に対応するトークンが払い出されます。
確認コードを入力してもらったときに、このトークンもあわせて必要になりますので、どこかに保存しておく必要があります。

サンプルコードでは、Vue.jsコンポーネントのdataに格納しています。
(confirmationResultに入っている)

async sendSmsVerification() {
    try {
        const confirmationResult = await firebase.auth().signInWithPhoneNumber(this.phoneNumber, this.recaptchaVerifier)
        this.confirmationResult = confirmationResult
        this.waitingVerify = true
    } catch(error) {
        console.error(error)
    }
},

4. 2の時点で払い出されるトークンと、SMSを受け取ったユーザーが入力する確認コードを使って認証を行う & 5. 得られた認証情報をアカウントとリンクさせる

さきほどの電話番号のとき同様にユーザーに確認コードを入力してもらうフォームも自分で作成する必要があります。
そのフォームに確認コードを入れてもらったら、さきほど保存したトークンと一緒にFirebaseに送信すると、電話番号の認証情報が得られます。

この認証情報をFirebaseのユーザーオブジェクトに生えているlinkAndRetrieveDataWithCredentialメソッドに渡すと、既存のアカウント情報に電話番号認証情報がリンクされます。

async confirmVerification() {
    const credential = firebase.auth.PhoneAuthProvider.credential(this.confirmationResult.verificationId, this.verificationCode)
    const userCred = await this.user.linkAndRetrieveDataWithCredential(credential)
    this.auth.phoneNumber = userCred.user.phoneNumber
}

電話番号認証が終わると、Firebase authのコンソールが次のような表示になっているはずです。

Screenshot from 2018-11-28 22-21-31.png

Googleアカウントと電話番号が紐付けられました。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away