Nuxt.jsとExpressでアプリケーションを作成する場合のTwitter認証でのログインを試してみました。Node.jsでのTwitter認証はPassportというライブラリを使用すると非常に簡単でした。細かく検証はしていませんがSSR(サーバーサイドレンダリング)の場合でも問題ないと思われます。
このあたりで作ったプロジェクトをベースにして試しています。
- Nuxt.js v1.4.2
 - Passport-twitter v1.0.4
 
インストール
何はともあれまずはインストールします。Passport本体とTwitter用の拡張です。
基本的なところは公式のマニュアル通りですので、よくわからなくなった場合やバージョンが違う場合はそちらを参考にしてください。
yarn add passport passport-twitter
初期設定
Passportの設定
まずはplugins/passport.jsとして初期化スクリプトを作成します。TWITTER_CONSUMER_KEY等は環境変数として指定しておいてください。(dotenv等を使うと便利です)
下記はSequelizeでユーザーデータとして保存する場合のサンプルも入れています。
var passport = require("passport"),
  TwitterStrategy = require("passport-twitter").Strategy;
module.exports = function(app) {
  const models = app.get("models");
  const User = models.User;
  passport.use(
    new TwitterStrategy(
      {
        consumerKey: process.env.TWITTER_CONSUMER_KEY,
        consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
        callbackURL: `${process.env.APP_URL}/auth/twitter/callback`,
        includeEmail: true // メールアドレスが必要な場合
      },
      async function(token, tokenSecret, profile, done) {
        let user = await User.findOne({
          where: { twitter_id: profile.id }
        });
        if (!user) {
          user = User.build({
            unique_id: profile.username,
            name: profile.displayName,
            email: profile.emails[0].value,
            location: profile._json.location,
            bio: profile._json.description,
            url: profile._json.url,
            image: profile.photos[0].value,
            twitter_id: profile.id,
            twitter_token: token,
            twitter_secret: tokenSecret
          });
          await user.save();
        }
        done(null, user.get({ plain: true }));
      }
    )
  );
  passport.serializeUser(function(user, done) {
    done(null, user);
  });
  passport.deserializeUser(function(user, done) {
    done(null, user);
  });
  return passport;
};
認証用ルーティング
認証用のルーティングを作成します。今回はroutes/auth.jsとしてファイルを分けました。アクションにそのままPassportの処理を指定するようなので下記のようにしてルーティング設定全体を関数化して読み込む形にしました。
const { Router } = require("express");
module.exports = function(app, passport) {
  const router = Router();
  router.get("/twitter", passport.authenticate("twitter"));
  router.get(
    "/twitter/callback",
    passport.authenticate("twitter", {
      successRedirect: "/",
      failureRedirect: "/"
    })
  );
  app.use("/auth", router);
};
アプリケーションに組み込み
これらをserver/index.jsで読み込んでアプリケーションに組み込みます。
const passport = require("../plugins/passport")(app);
app.use(
  session({
    secret: "your secret"
  })
);
app.use(passport.initialize());
app.use(passport.session());
require("../routes/auth")(app, passport);
基本的な部分はこれで完了です。あとは実際に動かしていくための処理を入れていきます。
Nuxt.jsと連携させる
PassportでのログインはExpress側のセッションに保存しているだけのため、これをNuxt.js側にも渡します。アプリケーション全体に絡むことのため、Storeを使ってNuxt.js上のどこからでもアクセスできるようにします。Nuxt.jsの場合は下記のように適当にファイルを一つ追加するだけで簡単にStoreが利用できます。
store/index.js
export const state = () => ({
  authUser: null
});
export const mutations = {
  setUser(state, authUser) {
    state.authUser = authUser;
  }
};
export const actions = {
  nuxtServerInit({ commit }, { req }) {
    if (req.session.passport && req.session.passport.user) {
      commit("setUser", req.session.passport.user);
    }
  }
};
Storeの場合setUserでなくSET_USERが使われることが多い気がします。
あとはもう下記のようにゆるふわな感じで適当にログインしているか判断できます。
    <div v-if="$store.state.authUser">
      <img :src="$store.state.authUser.image">
    </div>
    <span v-if="!$store.state.authUser">
      <a href="/auth/twitter">ログイン</a>
    </span>
スクリプト側でもthis.$store.state.authUserみたいな感じで利用できます。
まとめ
荒い感じの書き方も一部あるかもしれませんが、とりあえず非常に簡単にTwitterログインを行ってNuxt.jsと連携させることができました。また動きのおかしいところなどあれば随時追記していきます。
他にもGoogleアカウントのログインなども公式のドキュメントに書かれています。
    
Top comments (0)