Nuxt.js+Expressで簡単にTwitter認証
Tags: nuxt, vue, express, twitter
Published: 2018-08-16 03:08:17

---
title: Nuxt.js+Expressで簡単にTwitter認証
published: true
description: 
tags: nuxt,vue,express,twitter
canonical_url: https://crieit.net/posts/Nuxt-js-Express-Twitter
---

Nuxt.jsとExpressでアプリケーションを作成する場合のTwitter認証でのログインを試してみました。Node.jsでのTwitter認証はPassportというライブラリを使用すると非常に簡単でした。細かく検証はしていませんがSSR（サーバーサイドレンダリング）の場合でも問題ないと思われます。

このあたりで作ったプロジェクトをベースにして試しています。

[Nuxt.js+Expressでとにかく簡単にORM](https://crieit.net/posts/Nuxt-js-Express-ORM)

* Nuxt.js v1.4.2
* Passport-twitter v1.0.4

## インストール

何はともあれまずはインストールします。Passport本体とTwitter用の拡張です。

基本的なところは公式のマニュアル通りですので、よくわからなくなった場合やバージョンが違う場合はそちらを参考にしてください。

[Documentation: Twitter](http://www.passportjs.org/docs/twitter/)

```sh
yarn add passport passport-twitter
```

## 初期設定

### Passportの設定

まずはplugins/passport.jsとして初期化スクリプトを作成します。`TWITTER_CONSUMER_KEY`等は環境変数として指定しておいてください。（dotenv等を使うと便利です）

下記はSequelizeでユーザーデータとして保存する場合のサンプルも入れています。

```javascript
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の処理を指定するようなので下記のようにしてルーティング設定全体を関数化して読み込む形にしました。

```javascript
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で読み込んでアプリケーションに組み込みます。

```javascript
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

```javascript
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`が使われることが多い気がします。

あとはもう下記のようにゆるふわな感じで適当にログインしているか判断できます。

```html
    <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アカウントのログインなども公式のドキュメントに書かれています。