テックブログ

  1. Nuxt
  2. 612 view

NuxtでJWT認証を導入する

はじめに

本記事ではNuxt.jsのアプリケーションにAuth Moduleを使ってJWT認証を導入する方法を説明します。

作るもの

ソースコード

ソースコードはこちら

バックエンドの準備

こちらにJWT認証のためのモックサーバを用意しました。起動手順は以下の通りです。(Node.js、npmが入っていることが前提です。)

git clone https://github.com/windii-legend/express-jwt-mock.git
cd express-jwt-mock
npm install
sudo node index.js

http://localhost:8080/でサーバが立ち上がります。

このモックサーバは以下の2つのエンドポイントを持ちます

/api/authenticate

  • リクエストBodyの例
{
    "name": "tanaka",
    "password": "password"
}
  • レスポンス
{
    "token": "XXXXXXXXXXXXX"
}

/api/me

HeaderにBearer XXXXXXXXX(トークン)を付与すると以下のようなレスポンスが返ります。

  • レスポンス
{
    "id": 1,
    "name": "tanaka",
    "nickname": "田中太郎"
}

プロジェクトを作成する

Vue Cliの準備

すでにお済みの方は飛ばしてください。まだの人は以下のコマンドを実行しましょう。

npm install -g @vue/cli
# OR
yarn global add @vue/cli
npm install -g @vue/cli-init
# OR
yarn global add @vue/cli-init

スターターテンプレートで始める

vue init nuxt-community/starter-template nuxt-jwt-example
cd nuxt-jwt-example
npm install
npm run dev

以下のような画面が立ち上がれば成功です!

*エラーが出る場合はこちらが参考になるかもしれません。

Nuxt.jsのモジュールをインストールする

npm install --save @nuxtjs/axios @nuxtjs/auth @nuxtjs/vuetify

簡単に各ライブラリの説明をします(すでにご存知の方は飛ばしてください!)

Axios

AxiosはJavaScript環境で用いられるPromiseベースのHTTPクライアントです。今回はログイン認証やプロフィール情報取得のHTTPリクエストを送るために使用します。

Nuxt Auth Module

Nuxtで認証を簡単に導入するためのモジュールです。今回はJWT認証のために使いますが、OAuth2に対応し、様々なProviderに対応しているので大体の認証はこれでいけるのではと思います。 ドキュメントはこちら

Vuetify

VuetifyとはVueでマテリアルデザインを使うときに便利なライブラリです。React、Angularのマテリアルデザイン用ライブラリと比べてもかなり綺麗で使いやすい印象です。(一押し)

各モジュールの設定

インストールが終わったらnuxt.config.jsに各モジュールの設定をして行きます。

まずは以下を追加しましょう。

modules: [
  '@nuxtjs/axios',
  '@nuxtjs/auth',
  '@nuxtjs/vuetify',
],

次にモジュールをセットアップします。nuxt.config.jsに以下を追加します。

axios: {
  baseURL: 'http://localhost:8080/api'
},
auth: {
  strategies: {
    local: {
      endpoints: {
        login: { url: 'authenticate', method: 'post', propertyName: 'token' },
        user: { url: 'me', method: 'get',propertyName: ''},
        logout: false
      }
    }
  }
},
vuetify: {
  theme: {
    primary: '#3f51b5',
    secondary: '#b0bec5',
    accent: '#8c9eff',
    error: '#b71c1c'
  }
},

store/にindex.jsがないと怒られるので、追加して置きましょう。(からでOKです)
ひとまず立ち上がるか確認してみます。

npm run dev

レイアウトを作る

本記事の内容でレイアウトをこだわりすぎても仕方ありませんが、Vuetifyならサクッといい感じにレイアウトできるので少しだけお付き合いください。

layouts/default.vueを以下のようにします。

layouts/default.vue

<template>
<v-app>
  <v-toolbar dark fixed app>
    <v-toolbar-title>Nuxt Jwt Auth</v-toolbar-title>
    <v-spacer></v-spacer>
    <v-toolbar-items class="hidden-sm-and-down">
      <v-btn flat to="/profile">プロフィール</v-btn>
      <v-btn flat>ログアウト</v-btn>
      <v-btn flat to="/login">ログイン</v-btn>
    </v-toolbar-items>
  </v-toolbar>
  <v-content>
    <v-container fluid fill-height>
      <nuxt/>
    </v-container>
  </v-content>
</v-app>
</template>

<style>
</style>

同様に
pages/login.vueを作成して以下のようにします。

pages/login.vue

<template>
<v-container>
<v-form>
  <v-card>
    <v-alert
      :value="error"
      type="error"
    >
      IDとパスワードの組みが正しくありません
    </v-alert>
    <v-card-title primary-title>
      <h3 class="headline mb-0">ログイン</h3>
    </v-card-title>
    <v-card-text>
      <v-text-field 
        v-model="name"
        label="ユーザID"
        required
      />
      <v-text-field
        v-model="password"
        label="パスワード"
        required
      />
    </v-card-text>

    <v-btn dark>ログイン</v-btn>
  </v-card>
</v-form>
</v-container>
</template>

<script>
export default {
  data() {
    return {
      name: '',
      password: '',
      error: false
    }
  },
}
</script>

<style>
</style>

プロフィールページも作りましょう。
pages/profile.vueを以下のようにしましょう。

pages/profile.vue

<template>
  <div>
    <h1>こんにちは、テストさん!!</h1>
  </div>
</template>

<script>

export default {
}
</script>

<style>
</style>

これでレイアウトは終わりです!それでは認証ロジックを構築して行きましょう!

ログイン処理の実装

ログインボタンを押したときに実行されるメソッドを追加します。

methods: {
  async submit () {
    try {
      await this.$auth.loginWith('local', {
        data: {
          name: this.name,
          password: this.password
        }
      })
      this.$router.push('/profile')
    } catch (e) {
      this.error = true
    }
  }
}

ログインボタンを押したときに追加したメソッドを実行できるように以下のように修正しましょう。

<v-btn dark @click="submit">ログイン</v-btn>

これで正しいユーザIDとパスワードを入れるとプロフィールに飛べます。(tanaka,passwordで入れます)

プロフィールの実装

それでは、次にプロフィールです。

pages/profile.vueに以下の記述を追加します。

computed: {
   loggedInUser () {
     return this.$auth.user
   },
}

テンプレート側で

<h1>こんにちは、{{ loggedInUser.nickname }}さん!!</h1>

のようにするとログインユーザの名前が表示されます。

ツールバーの設定

現在の状態ですと右側にプロフィール、ログイン、ログアウト全てが表示されてしまっているのでログイン状態に応じて切り替えましょう。ついでにログアウト機能もつけます。

まずはログイン状態を判定するcomputed propertyとログアウト処理のためにlogout()メソッドを追加します。

layouts/default.vue

computed: {
  isAuthenticated () {
    return this.$auth.loggedIn
  },
},
methods: {
  async logout() {
    await this.$auth.logout();
  },
},

テンプレート側ではisAuthenticatedの値に応じてボタンを出し分けます。またログアウトボタンが押されたときlogout()メソッドが実行されるように設定します。

<v-btn flat to="/profile" v-if="isAuthenticated">プロフィール</v-btn>
<v-btn flat v-if="isAuthenticated" @click="logout">ログアウト</v-btn>
<v-btn flat to="/login" v-if="!isAuthenticated">ログイン</v-btn>

以上で基本的な機能は実装完了です。最後にMiddlewareの設定をして行きましょう。

Middlewareの設定

基本的な認証処理の実装は完了しましたが、一つ問題があります。例えばログインしていない状態で/profileにアクセスしてみてください。以下のような画面が出ます。

通常のアプリケーションではログインしていない状態でユーザがプロフィール画面などにアクセスしたときリダイレクト処理をします。この機能を実装するためにNuxtではMiddlewareという仕組みがあります。それでは早速設定して行きましょう。

pages/profile.vueに以下の記述を追加してください。

pages/profile.vue

export default {
  middleware: 'auth',//追加
  computed: {
    loggedInUser () {
      return this.$auth.user
    },
  }
}

たったこれだけの設定で先ほどのリダイレクト処理ができてしまいます。ちなみにauthミドルウェアはNuxt Auth Moduleによって提供されています。

また、ログイン済みのユーザが/loginにアクセスした時も同様に/profileにリダイレクトしましょう。このようなミドルウェアはNuxt Auth Moduleによって提供されていないようなので自作しましょう。

middleware/guest.jsというファイルを作って以下のように記述します。

export default function ({ store, redirect }) {
  if (store.state.auth.loggedIn) {
    return redirect('/profile')
  }
}

pages/login.vueに先ほどのようにMiddlewareを追加しましょう。

middleware: 'guest',

これでリダイレクトされるようになります。

以上で完了です。お疲れ様でした!

Nuxt Auth Moduleは色々な機能があるので一度ドキュメントを読むのをお勧めします!ドキュメントはこちら

Nuxtの最近記事

  1. Nuxt.js+Firebaseでデプロイまでの流れ【簡単5分】

  2. NuxtでOAuth認証を導入する

  3. Vuetifyチュートリアル。CSSを書かないマテリアルデザイン

  4. Nuxt入門〜create-nuxt-appでお手軽開発

  5. NuxtでJWT認証を導入する

関連記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。