beta

Vue.js + Firebase AuthでログインsignInWithRedirectでログインフローを作る

Vue.js + Firebase AuthでログインsignInWithRedirectでログインフローを作ろうとしたら、リダイレクト後の処理ができなくてハマったので対策まとめです。

公開日:2019年8月6日

ダメだったパターン

ネットでよく例で出ているやつです。

<template>
  <div class="">
    <button  @click="googleLogin">Google ログイン</button>      
  </div>
</template>

<script>
import firebase from 'firebase/app'

export default {
  created () {
  },
  mounted () {
  },
  methods: {
    googleLogin: function() {
      const provider = new firebase.auth.GoogleAuthProvider()

      firebase.auth().signInWithRedirect(provider)
    }
  }
}
</script>

このパターンだと、FirebaseAuthのログイン画面に遷移して、そのまま戻ってきたら無反応になります。

以下、いろいろ試したみたことも残しておきます。

ページを読むごとに判定する

ログイン出来ているかは、

firebase.auth().onAuthStateChanged

で判定するのですが、一回一回サーバーに読み行っているようで、beforeCreateなどでonAuthStateChangedを判定すると、Google認証から戻ってくると、元のログインボタンが表示されたままのページが表示され、裏ではログイン判定をしてリダイレクトする、というとても気持ち悪い感じになりました。

これではユーザーが混乱してしまいますね。

isLoadingなどのフラグを立ててみた

isLoadingなどのフラグを用意して、Goolge認証ページに行く前にローディングに切り替えてみました。

やってみると、firebase.auth().signInWithRedirect()からリダイレクトで戻ってくると、新規でページを読み込んでいるので(ページリフレッシュ)、フラグが元に戻ってしまい、うまく出来ませんでした。

  • isLoading => true
  • firebase.auth().signInWithRedirect()
  • ページ再読み込み -> isLoading => falseに戻る
  • 画面にはログインボタンが出てきたまま

という感じです。

うまくいったやり方

ということで、お手上げか!と思ったのですが、router-viewでローディング画面に入ってしまえばいいのか?と思って、試してみたところ、これが正解でした。

流れとしては、

  • サインインページ(/signin)でGoogleログインボタンを押す
  • Googleページへリダイレクト(firebase.auth().signInWithRedirect())する。裏側ではサインイン中ページ(/signin/loading)へrouter.pushする(router.goではダメ)
  • 認証する
  • サインイン中ページ(/signin/loading)に戻ってくる
  • サインイン中ページ(/signin/loading)で、firebase.auth().onAuthStateChangedでログイン判定をして、任意のページにrouter.pushする

という感じです。

具体的に各ファイルを見ていきます。main.jsでfirebaseの設定が出来ている前提です。

設定などは、こちらの記事がわかりやすいです。

router.js

signinの部分だけ抜粋です。

{
  path: "/signin",
  component: () => import( './views/Signin.vue'),
  children: [
    {
      path: '',
      name: "signin",
      component: () => import( './views/SigninTop.vue'),
    },
    {
      path: 'loading',
      component: () => import( './views/SigninLoading.vue'),
    },
  ]
}

Signin.vueコンポーネントの中で、子ルートをrouter-viewで切り替えてます。

Signin.vue

ログイン画面の親コンポーネントです。大事なのはrouter-viewくらいです。

<template>
  <section class="container">
    <h1>サインイン</h1>
    <transition>
      <router-view/>
    </transition>
  </section>
</template>

SigninTop.vue

Googleログインボタンと実行とGoogleログイン画面への遷移、そして背後ではログインローディングページへの遷移をします。

<template>
  <div class="">
    <button @click="googleLogin">Google ログイン</button>
  </div>
</template>

<script>
import firebase from 'firebase/app'

export default {
  created () {
  },
  mounted () {
  },
  methods: {
    googleLogin: function() {
      const provider = new firebase.auth.GoogleAuthProvider()

      firebase.auth().signInWithRedirect(provider)
      this.$router.push('loading')
    }
  }
}
</script>

SigninLoading.vue

Googleログイン画面から戻ってきたら、ログインが完了しているかをチェックして、結果によってリダイレクトするだけのページです。

<template>
  <div class="">
    <p>サインインしています...</p>
  </div>
</template>

<script>
import firebase from 'firebase/app'

export default {
  created () {
  },
  computed: {
  },
  mounted () {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        console.log('login!!');
        this.$router.push('/mypage')
      }else{
        this.$router.push('/signin')
      }
    })
  },
  methods: {
  }
}
</script>

この一連の流れで、それっぽいログイン画面ができました。


きっと、もっと良いやり方があると思うのですが、簡単にそれっぽいFirebase AuthのGoogleログイン画面ができました。

ネットの記事が「とりあえずやってみた」系が多く、実際の画面遷移なども含めて考えられた記事が少なかったので、ノートにしてみました。

ご参考になれば幸いです!!

Author

Koji Kadoma
Member of codit.work

新着ノート

新着コード