LoginSignup
12
14

More than 3 years have passed since last update.

Vue.jsとfirebaseを使ってTwitter認証してみた【ユーザー名・プロフ写真の取得と表示・ログイン状態維持の方法も併せて】

Last updated at Posted at 2019-09-25

はじめに

個人開発をしようと思い、フロントにVue.js、バックエンドにGoを使うことに決めました。

よくある組み合わせですね。

制作物のテーマはTwitterを活用するものになる?予定なので、ログイン機能もTwitter認証を用いてログインする形式を採用することにしました。
認証にあたりfirebaseを用いると簡単に認証ができるということなので、今回活用してみることにしました。

結果として、「認証」だけなら簡単でした。(恐らく記事を探せば認証に関してはすぐ見つかると思います。)

ユーザー名とプロフ写真のURLの取得、ログイン状態の維持に関してはあまり記事がなく、3日間くらい悩みました。
同じように悩む人がいると思うので(私が雑魚なだけ?)、備忘録兼同じことをやりたい人の為に、ここに載せておきます。

準備するもの

firebaseからTwitter認証できるように、TwitterAPIを入力する項目があります。
そのため、あらかじめTwitterAPIを取得していないといけません。
API取得に関してはここでは紹介いたしませんので、別途個人で取得をお願いいたします。

またVuexとvue-routerも使うので、入れていない人は追加をお願いします。

実際の画面

①signinボタンをクリックする

②Twitter連携のポップアップが表示される


③連携アプリを認証し、ホーム画面へ
Twitterのユーザー名・プロフィール写真も表示される

Twitter認証方法

ログイン

下記の通り、Signinボタンを押すとクリックイベントに応じて、signinメソッドが実行されます。
signinメソッドのfunction()以降がログインに関わる部分です。

firebaseのDocsにあるTwitter認証のリファレンスとこちらの記事を参考に、ここの処理を作成しました。

今回はユーザー名・プロフ写真が欲しいので、ログインユーザーのユーザー名とプロフ写真のURLを取得し、格納するcurrentUserプロパティを用意します。

currentUserの情報は全画面共通で使いたい(例えばQiitaは、どの画面に飛んでも自分のTwitterのプロフ写真が載ってますよね?)ので、store.jsにcommitして送ります。

後半のエラー処理に関してはよく分からなかったので、とりあえず書いただけです。あまり参考にしないで下さい…。

components/signin.vue
<template>
  <div class="signin">
    <h2>Sign in</h2>
    <button @click="signin">Signin</button>
  </div>
</template>

<script>
import firebase from "firebase";

export default {
  name: "Signin",
  methods: {
    signin: function() {
      var provider = new firebase.auth.TwitterAuthProvider();
      firebase
        .auth()
        .signInWithPopup(provider)
        .then(
          result => {
            var token = result.credential.token;
            var secret = result.credential.secret;
            var user = result.user;
            if (user) {
              const currentUser = { // ←こいつ必要
                displayName: user.displayName,
                photoURL: user.photoURL
              };
              this.$store.commit("setUser", currentUser); // currentUserをstore.jsに渡す
              this.$router.push("/");
            } else {
              alert("有効なアカウントではありません");
            }
          },
          err => {
            alert(err.message);
          }
        );
    }
  }
};
</script>
store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  // strictモードは本番環境ではfalseにすること
  strict: true,
  state: {
    user: {
      displayName: "",
      photoURL: ""
    }

  },
  getters: {
    getURL(state) { // ←こいつは後半に使う処理なので覚えておいてください
    return state.user.photoURL
    }
  },
  mutations: {
    setUser(state, currentUser) { // commitされるとmutationsのsetUserが実行される
      state.user.displayName = currentUser.displayName // ここでユーザー名をstateにセットできる
      state.user.photoURL = currentUser.photoURL // 同様に写真URLをセットする
    }
  },
  actions: {

  }
})

ログイン状態の維持

ログイン状態の維持にはfirebase.auth().onAuthStateChanged()を使います。
ここら辺に関してはまだ詳しくないので、うまく説明することができないのです。すみません。

ただ見てもらえれば分かる通り、ログイン状態であるかどうかの判別をここでしています。

ログイン状態であればstore.jsに、上記同様currentUserを引数にしてcommitします。
維持というよりは更新と言った方が正確かもしれません。

画面が変わるごとに最新の状態に更新しているの、最新の状態に保つ=維持ともいえるということなのでしょうね。

main.js
// 認証状態を確認
// Vueのインスタンス化
const app = () => {
  firebase.auth().onAuthStateChanged(currentUser => {
    if (currentUser) {
      store.commit("setUser", currentUser)
    } else {
      store.commit("setUser", null)
    }
  }),
    /* eslint-disable */
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')
}
// 関数実行
app()

ユーザー名・プロフ写真の取得

他にも色々なものが下記のコードに入っているのですが、見づらさが増すので必要な部分だけ記載しております。

このコンポーネントで行っていることはいたってシンプルです。

store.jsstateの値を持ってきているだけです。

今回は勉強もかねてmapStatemapGettersを使用しています。

注意する点というか私がハマった点は、
src属性にどうやってstore.jsのuserプロパティのphotoURLを入れるのか
というところです。(Vue.js初心者なのでまったくわかりませんでした...)

components/HelloWorld.vue

<template>
  <div class="hello">
    <h1>Hello</h1>
    <p>{{ user.displayName }}</p> <!--userのdisplayName(あなたのTwitterのユーザー名)を表示します-->
    <img :src="url" /> <!--mapGettersのurl(←名前は何でもいい)をv-bindしたsrc属性に記述してください-->
    <h2>Essential Links</h2>
  </div>
</template>

<script>
import firebase from "firebase";
import { mapState, mapGetters } from "vuex";
export default {
  name: "HelloWorld",
  data() {
    return {
  },
  computed: {
    ...mapState({
      user: state => state.user // stateのuserプロパティを取得する処理にuserという別名を与える
    }),
    ...mapGetters({ url: "getURL" }) // mapGettersのgetURLに別名を与える
  }
};
</script>

まずVueのルールで`<img src={{ user.photoURL }} />`のような記述をすることはできません。

`<img :src={{ user.photoURL }} />のような書き方をしたいところですが、
data`に値がないのでこれもエラーとなります。

結果としてはgetters経由で取得することができたので、今回はこのように処理することが正解なのかもしれないですね。

終わりに

一連の処理については以上となります。

私自身、まだエンジニア歴半年になるかならないかぐらいの素人なので、今回の投稿内容も正確さに欠ける点が多いと思います。
参考の参考程度にしていただくだけでも幸いです。

12
14
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
12
14