コピペでOK！Firebaseの電話番号認証で既存のアカウントとリンクする方法

最近2段階認証でSMS認証を搭載している企業やサービスも増えましたよね。

今日はそのSMS認証をすごく簡単に実装してこうかなと思います。

って言ってもFirebaseのドキュメントのままですが。。

まぁ、Firebaseを学習し始めてまだそこまで日にちがたっていないひとはそこそこ難しい作業なのでは無いかと思います。

なぜなら、GoogleReCPTCHAと言うものが出てくるからです。

一度も触れたことが無い方は、おそらくなんだこれってなりますよね。。。

でも安心してください！

この記事を見れば簡単かつスピーディーにSMS認証を実装できます。

なので、ぜひ肩の力を抜いてご覧ください！

#はじめに#

まず初めに、Firebaseのsign-in-methodで電話番号によるサインインを有効にしてください。

その際に、テスト番号を以下のように登録してください

|テスト番号||
|---|---|
|電話番号|634-555-3434|
|認証番号|123456|

自分の携帯で試すのも良いのですが、SMSメッセージを送信する際、SMSメッセージを受け取る側に料金が発生します。なので、ローカル環境で試すときはこのテスト番号を用いて認証を行うようにしましょう！

それでは早速実装していきましょう！！！

#電話番号を入力、およびリキャプチャ認証の設置#

まずはユーザーに電話番号を入力してもらうinputを作りましょう！

また、SMS認証を行うには国によって定められている国コードを指定しなければなりません。

先ほど登録した``634-555-3434``の国コードは``+1``なのですが、日本は``+81``となっています。

なので、ローカル環境と本番環境で**環境変数**として定義してあげましょう！

環境変数の指定方法は下記の記事に書いてあるので是非ご覧ください！

[初心者必見！固定値（キー、URLなど）は.envファイルに書いて再利用しよう！！](https://qiita.com/akki-memo/items/c33348cfce315548ac6b)

そしたら、以下を参考に電話番号を入力する欄を作りましょう！

```phoneAuthenticationInput.vue
<template>
  <div class="phone-authentication-input">
    <form>
      <h3>認証コードの送信</h3>
      <p>本人確認のためSMSで認証コードを送信します。</p>
      <b-field
        label="電話番号"
        message="番号を入力する際はハイフン（-）は含めずにご入力ください。また、海外の電話番号は使用することはできませんのでご了承ください。"
      >
        <b-input v-model="phoneNumber" type="tel" placeholder="0901234567" autocomplete="tel" maxlength="11"> </b-input>
      </b-field>
      <b-button
        id="send-code-button"
        type="is-success"
        :native-type="button"
        style="padding: 30px 0; width: 100%"
        @click="sendPhoneCode"
      >
        <b-icon
          pack="fas"
          icon="mobile-alt"
          size="medium"
          style="margin-right: 0.5rem; margin-bottom: 0.25rem; vertical-align: middle"
        ></b-icon>
        認証コードを送信する
      </b-button>
      <p>※SMS送信時に料金が発生致しますのでご了承ください。</p>
    </form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      countryCode: process.env.VUE_APP_COUNTRY_CODE,
      phoneNumber: '',
      recaptchaVerifier: null
    }
  },
  mounted() {
    this.recaptchaVerifier = new this.$firebase.auth.RecaptchaVerifier('send-code-button', {
      size: 'invisible'
    })
  },
  methods: {
    async sendPhoneCode() {
      if (!this.phoneNumber) {
        alert('携帯電話の番号を入力してください')
      }
      const formattedPhpneNumber = this.countryCode + this.phoneNumber
      try {
        const confirmationResult = await this.$auth.signInWithPhoneNumber(formattedPhpneNumber, this.recaptchaVerifier)
        window.sessionStorage('result', confirmationResult)
        this.$router.push('confirm')
      } catch {
        alert('入力内容に誤りがございます')
      }
    }
  }
}
</script>
```

##Buefyのすゝめ##

``b-button``やら``b-input``というのはCSSフレームワークの**Buefy**というものです。

Buefyは本当におススメです！

これだけの設定で画像のようなレイアウトができます！

興味のある方は、以下の記事をご覧ください

・[初心者必見！サイト制作は楽してなんぼ。CSSフレームワークBuefyの紹介！！](https://qiita.com/akki-memo/items/278ff2982961274955c4)

##ReCPTCHAの設置##

``mounted``の関数に注目して下さい。

```
mounted() {
    this.recaptchaVerifier = new this.$firebase.auth.RecaptchaVerifier('send-code-button', {
      size: 'invisible'
    })
  },
```

これでidが``send-code-button``であるところに（今回はボタン）ReCPTCHAの設置を行っています。

そもそもReCPTCHAってなに？？？って思っている方もいると思うので軽く説明をします。

どこかしらのサイトで会員登録をしたり何か購入したりするときに「信号機の画像を選んでください」とかわかりずらい文字を入力するときってないですか？

それがGoogleReCPTCHAです！！

要するに人間かどうかを判別しているんです。

もっと分かりやすく言うと、BOTなどの機械じゃないかを判別。

近年、このGoogleReCPTCHAは文字入力。画像選択を必要としない**V3**がリリースされました。

文字入力、画像選択をしなくても**人間らしい動き**をしているかどうかを全て自動でやってくれます。

``size: 'invisible'``はそのV3を使っています。

今回で言うと、人間らしい動きをしていればSMSで認証コードを送信できるわけです。

ReCPTCHAの説明はここまでにしておいて、これで入力した電話番号にSMSで認証コードを送れます！

##結果の保持##

```
const confirmationResult = await this.$auth.signInWithPhoneNumber(formattedPhpneNumber, this.recaptchaVerifier)
window.sessionStorage('result', confirmationResult)
```

ReCPTCHAの認証結果はこの後使うのでどこかに保存していてください。

今回は例として``window.sessionStorage``を使用しています。

``window.sessionStorage``でなくても全然大丈夫です！

#認証コードが正しいかの判断#

さて、次は認証コードが正しいかの判断を行います。

ここで、認証コードって入力するときに一文字ずつ入力しますよね？

めっちゃ便利なパッケージがあります。

その名も**vue-fake-input**

興味のある方は[こちら]()の記事をご覧ください。

面倒くさいという方は``input``だけでも大丈夫です！

そしたら、下記のコードを参考に認証を行ってみましょう！

```phoneAuthenticationConfirm.vue
<template>
  <div class="phone-authentication-confirm">
    <form>
      <h3>認証コードの確認</h3>
      <p>ご入力いただいた電話番号に送信した6桁の認証コードをご確認ください</p>
      <b-field label="認証コード" message="番号を入力する際は半角数字、ハイフン（-）は含めずにご入力ください。">
        <VueFakeInput v-model="authenticationCode" :length="6" :font-size="50" input-color="#31bce6" font-color="#000">
        </VueFakeInput>
      </b-field>
      <b-button
        id="send-code-button"
        type="is-success"
        :native-type="button"
        style="padding: 30px 0; width: 100%"
        @click="confirmPhoneCode"
      >
        認証コードを確認する
      </b-button>
    </form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      authenticationCode: '',
      confirmationResult: window.sessionStorage.getItme('result')
    }
  },
  methods: {
    confirmPhoneCode() {
      if (!this.authenticationCode) {
        alert('認証コードを入力してください')
        return
      }
      this.isLoading = true
      const user = this.$auth.currentUser
      const credential = this.$firebase.auth.PhoneAuthProvider.credential(
        this.confirmationResult.verificationId,
        this.authenticationCode
      )
      if (user) {
        user
          .linkWithCredential(credential)
          .then(async (user) => {
            // 処理の実行
          })
          .catch(() => {
            // エラーの処理
          })
    }
  }
}
</script>
```

ユーザーに``input``で認証コードを入力してもらいましょう！

このようにして電話番号認証を行うことができます！

GoogleReCPTCHAを触れたことが無い方は少しイメージがわきにくいと思います。

でも諦めずに頑張りましょう！

以上、「コピペでOK！Firebaseの電話番号認証で既存のアカウントとリンクする方法」でした！

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

あと、最近「ココナラ」で環境構築のお手伝いをするサービスを始めました。

気になる方はぜひ一度ご相談ください！

Thank you for reading