モダンな技術を全く知らないSIer5年目がWebサービスを作ることになったため0から勉強する ~Laravel jwt-auth + Nuxt編~

# はじめに
現在SIer5年目でjavascript(Jqueryのみ)、PHP(フレームワーク無し)を2年ほど、C#(Windowsアプリ)3年ほどやってきました。
色々なご縁があり、個人で最近Webサービスの立ち上げをやることになったのですが何せ本当にWebサービスを立ち上げるための知識がほぼ0に等しいです:sob:

ただ今後のキャリアを考えた時に今のままではいけないと思いチャレンジすることにしました。

まずは最初に技術を習得しないといけないので、学ぶ＆アウトプットするために毎回投稿していこうと思います。
今後身についていこうと思ってるのは下記のような技術です。
**AWS**
**Docker**
**CI/CD環境の構築**
**Laravel**
**Nuxt.js**
今回はLaravel+Nuxtについて学んでいきます。

# 今回学ぶこと
Laravel＋Nuxtでのログイン機能を作成していこうかと思います。
jwt-authを使用してログインを実現してきます。

# 参考サイト
[jwt-auth公式サイト](https://jwt-auth.readthedocs.io/en/develop/)

# 前提
Laravel 5.8
Nuxt　2.5.4 
jwt-auth

このチュートリアルで勉強してみました
[Laravel + NuxtJS認証]（https://www.youtube.com/playlist?list=PLeZmuYT0mSPNmQie2QyoY-3hxQxDZwi22）

環境構築部分は今回、省略します。
詳しくは上記のチュートリアルを確認してください

[Laravel側の実装](https://qiita.com/gemetasu1103/items/cc41e65dff7824a63bef)はこちらを見てください

[最終的なソースコードはこちらになります。](https://github.com/hajime1103/nuxt-laravel-jwt-auth-example)



# Nuxt側の画面構成

画面一覧

|       画面名             |    概要    |    認可    |
|:---------------:|:------------------|:------------------|
| index.vue| ホーム画面 | 誰でもアクセスできる|
| login.vue| ログイン画面 | ログイン済みのユーザはアクセスできないようにする|
| registar.vue| ユーザ登録画面 | ログイン済みのユーザはアクセスできないようにする|
| dashboard.vue| ログイン後アクセスできる画面 | ログイン済みのユーザのみアクセスできる|

各ソースは(github)[]にあげてるので確認してみてください

## 認証機能を実装するためにauth-moduleのインストール

Nuxtではauth-moduleという認証認可を簡単にするモジュールが提供されているので今回はそれを使用する
(公式サイト)[https://auth.nuxtjs.org/]

```bash
npm install @nuxtjs/auth @nuxtjs/axios
```

auth-moduleを有効にするための設定を行う

```nuxt.config.js
 /*
  ** Nuxt.js modules
  */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    // Doc: https://bootstrap-vue.js.org/docs/
    'bootstrap-vue/nuxt',
    // Doc: https://auth.nuxtjs.org/
    '@nuxtjs/auth'
  ],
```

axiosでのリクエスト先の設定を行う

```nuxt.config.js
 /*
  ** Axios module configuration
  */
  axios: {
    // See https://github.com/nuxt-community/axios-module#options
    baseURL: 'http://localhost/api'
  },
```

```nuxt.config.js
  auth:{
    strategies: {
      local: { //自前の認証処理を実行する
        endpoints: {
          login: { //ログインを実行する際のリクエスト設定
            url: 'auth/login', method: 'post', propertyName: 'token'
          },
          user:{ //ログイン済みのユーザ情報取得を実行する際のリクエスト設定
            url: 'me', method: 'get', propertyName: 'data'
          },
          logout: {　//ログアウトを実行する際のリクエスト設定
            url: 'auth/logout', method: 'get'
          },
        },
      },
    },
    redirect: {
      login: '/auth/login', //未ログインユーザが認証が必要な画面にアクセスした際のリダイレクト先
      home: '/' //ログイン後のリダイレクト先
    },
  },
```

# Vuexのの実装

Nuxtでは`store`ディレクトリに`index.js`を追加することで
Vuexを有効にすることができるため
空のindex.jsを追加する

| ファイル名 |    概要    |
|:---------------|:------------------|
| validation.js | バリデーションエラーの情報を扱う |
| auth.js | 認証情報を扱う |


# pluginの構成
プラグインでコンポーネントから指定のVuexのステートから値を参照できるようにする

| ファイル名　　　　　　　　　　　　|    概要      |
|:------------------|:------------------|
| user.js| ユーザ情報をどこのコンポーネントからでもアクセスできるようにする |
| validation.js | バリデーションのエラー情報を扱う |
| auth.js | 認証されていないユーザが認可されていない画面にアクセスした際にリダイレクト処理時にリダイレクト元の画面情報を一緒にわたすようにする |
| axios.js | リクエスト前処理とエラー時の処理を記載し、全てのリクエスト時に処理を実行する |

※auth.jsは[このgithubで使用している](https://gist.github.com/zolotyx/b4e7fda234b3572fb7adaf11391f8eef)のをそのまま流用しています。

# トラブルシューティング

## ユーザ登録時にLaravelAPIで422エラーを返したら強制的にリダイレクトされてしまう件

### 発生したチュートリアル
[#6 - Laravel + NuxtJS authentication: Validation and Logging in](https://www.youtube.com/watch?v=vRyayu8KEIw&list=PLeZmuYT0mSPNmQie2QyoY-3hxQxDZwi22&index=6)

### 現象
登録画面でエラーが発生した際には下記のようにエラー情報を試しに表示する際に強制的にリダイレクトが発生してしまう。

リダイレクトされてしまう画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305479/1cb25560-9e20-29f5-394d-95e36f94e7ff.png)

ホントは出したかった画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305479/1fa928bb-ed11-fa61-35c2-a46da77364cc.png)

### 解決策

[ここに書いてる](https://github.com/nuxt/nuxt.js/issues/5181)通り
axiosにtry/catchを定義してないと強制的にリダイレクトされてしまうらしい
バージョン違いなのかよくわからないけど、動画方はだとリダイレクトされていなかった。

エラー時

```register.vue
async register(){
    await this.$axios.$post('/auth/register', this.form)
    
    this.$auth.login({data: this.form});
    this.$router.push({name: 'index'});
    
}
```

```register.vue
async register(){
    await this.$axios.$post('/auth/register', this.form)
      .then(data => {
        this.$auth.login({data: this.form});
        this.$router.push({name: 'index'});
      })
      .catch(err=> {
        console.log(err);
      });
}
```