Laravelとnuxt/authでSPA認証!ログイン機能を実装しよう!(第2回 フロントエンド編)

Laravel

前回はLaravel Sanctumをインストールし、バックエンド側のAPI認証を実装しました。第2回ではnuxt/authを使用し、NuxtJSで構築したフロントエンドにログイン機能を実装していきます。

スポンサーリンク

nuxt/authのインストール

まずは、nuxt.jsプロジェクトにnuxt/authをインストールしましょう。

npm install --save-exact @nuxtjs/auth-next

nuxt/authは、Nuxt.jsのプロジェクトに認証に関する処理をかんたんに実装することができるモジュールです。第1回で構築したLaravel Sanctumだけではなく、OAuthやLaravel JWT、Laravel Passportなどのさまざまな認証バックエンドと連携させることができます。

既存のNuxt.jsプロジェクトに認証機能を追加したい場合は、上記コマンドでnuxt/authをインストールします。まだプロジェクトを作成していない場合は、次のコマンドでNuxtプロジェクトを作成してからインストールしましょう。

npm init nuxt-app <project-name>

いくつかオプションを問われますが、わからないときはすべてNoneを選択しておけば問題ありません。

APIとの通信に使用するため、nuxt/axiosもインストールしておきましょう。

npm install @nuxtjs/axios

nuxt.config.jsを編集し、nuxt/authとnuxt/axiosをモジュールに追加します。

{
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/auth-next'
  ],
  auth: {

  }
}

ついでにauthセクションも追加しておきました。あとで使います。

スポンサーリンク

nuxt/authのセットアップ

次に、nuxt/authのセットアップを行っていきます。Laravel Sanctumで構築したバックエンドにログインし、保護されたルートにアクセスできるようにしていきます。

ストラテジー(strategy)を作成する

nuxt/authでは、認証に関わる設定をストラテジー(strategy)として設定していきます。

ストラテジーは同時に複数定義することができます。例えば、APIサーバーのほか、OAuthを用いた連携ログインも可能にするなど、複数のログイン方法を用意することも可能となっています。

ここではシンプルに第1回で構築したバックエンド(Laravel Sanctum)にログインするためのストラテジーだけを作成していきます。

nuxt.config.jsのauthセクションにstrategiesというセクションを追加し、任意の名前のストラテジーを作成します。

    auth: {
        strategies: {
            laravelApi: {
                provider: 'laravel/sanctum',
            },
        }
    },

ここでは、“laravelApi”という名前のストラテジーを作成し、プロバイダーにLaravel Sanctumを指定しました。

エンドポイントを設定しよう

バックエンドのベースURLと認証に関わるルートを設定していきます。

    auth: {
        redirect: {
            login: '/auth/login',
        },
        strategies: {
            laravelApi: {
                provider: 'laravel/sanctum',
                url: 'http://localhost:8000',
                // endpoints: {
                //   login: { url: '/api/login', method: 'post' },
                //   logout: { url: '/api/logout', method: 'post' },
                //   user: { url: '/api/user', method: 'get' }
                // }
            },
        }
    },

urlにバックエンドのURLを指定します。ここではLaravelのローカルサーバー(http://localhost:8000)を指定しています。

また、endpointsにログイン・ログアウト・ユーザー情報を取得するためのAPIへのパスを指定しておきます。デフォルトでは以下のように設定されています。

login/login
logout/logout
user/user

今回は、第1回でroutes/web.phpに上記と同じルートを指定しておいたため、endpointsに関する設定は不要です。デフォルトと異なるルートを設定している場合は、endpointsにパスを指定することにより、任意のエンドポイントを使用できます。

リダイレクトの設定

次に、リダイレクトに関わる設定を行います。

nuxt/authを導入すると、認証が必要なページへのアクセスを制限することができます。ログインされていない状態で認証が必要なページへアクセスされた場合、自動的にログインページへリダイレクトさせることができます。

リダイレクト先には任意のページを指定することができます。nuxt.config.jsから設定していきます。

auth: {
    redirect: {
        login: '/auth/login',
    },
    strategies: {
        laravelApi: {
            provider: 'laravel/sanctum',
            url: 'http://localhost:8000',

    }
}, 

authセクションにログインページのパスを指定します。上のサンプルでは、ログインページがpages/auth/login.vueにあるものとして設定してみました。

そして、routerにauthミドルウェアを適用します。

router: {
     mode: "hash",
     base: process.env.BASE_URL,
     middleware: ['auth']
},

routerのミドルウェアへの登録を忘れると、リダイレクトが動作しませんので要注意です。なお、開発環境で一時的にリダイレクトさせないようにしたいときは、ミドルウェアから外してやればOKです。

axiosからAPIへアクセスできるようにする

以上で認証に関するセットアップのほとんどが完了です。ログインやログアウトはすでに可能な状態になっています。

しかし、まだこの状態ではバックエンドのAPIにアクセスすることはできません。ログインが済んでいたとしても、axiosからsanctumでガードされたAPIにアクセスしようとすると、401 Unauthorizedエラーが発生してしまいます。

これはnuxt/authでログインし取得できたCSRFトークンやクッキーなどの資格情報が、axiosからのリクエストに含まれていないことが原因です。

axiosにはcredentialsというオプションがあり、これを有効にすることで資格情報をリクエストと一緒にサーバーへ送ることができます。nuxt.config.jsからオプションを適切に設定することで、正常にAPIへアクセスできるようになります。

axios: {
    baseURL: 'http://localhost:8000',
    credentials: true
},

credentialsを有効にすると、CSRFトークンの取得・更新処理も自動的に行なってくれるようになります。明示的にトークンの更新を行う必要もなくなるので、大変便利なオプションです。

オプションを設定したら、npmの開発サーバーを再起動しておきましょう。

Ctrl+C
$ npm run dev

ログインページをつくって、いざログイン!

さあ、これで準備は万端です。いよいよ実際にログインしてみましょう。

pagesディレクトリにログインページ(pages/auth/login.vue)を作成します。

<template>
    <input type="text" v-model="id" placeholder="id">
    <input type="password" v-model="password" placeholder="パスワード">
    <button @click="login">ログイン</button>
</template>

<script>
    export default {
        auth: false,
        data() {
            return {
                id: null,
                password: null
            }
        },
        methods: {
            login() {
                try {
                    // ログインする
                    const response = await this.$auth
                        .loginWith("laravelApi", {
                            data: {
                                id: this.id,
                                password: this.password
                            }
                        })
                        .then(() => {
                            // ログインに成功したら、/にページ遷移
                            window.alert("ログインしました");
                            this.$router.push("/");
                        });
                    console.log(response);
                } catch (error) {
                    // ログインに失敗したら、コンソールに出力する
                    window.alert("ログイン失敗");
                    console.log(error);
                }
            }
        }
    }
</script>

作成したページはこんな感じです。IDとパスワードを入力し、[ログイン]ボタンをクリックすると、nuxt/authによりログインが施行されるようにしました。

ここではわかりやすくするため、最低限の処理を実装しています。実際の案件では、バリデーションなども適切に実装するようにしましょう。

解説

ログインを施行するには、$auth.loginWithメソッドを使います。

// ログインする
const response = await this.$auth
    .loginWith("laravelApi", {
        data: {
            id: this.id,
            password: this.password
        }
    })
    .then(() => {
        // ログインに成功したら、/にページ遷移
        window.alert("ログインしました");
        this.$router.push("/");
    });

第1引数にストラテジー名(ここではlaravelApi)、第2引数にログインに使用するIDとパスワードを指定します。ログインボタンがクリックされたら実行されるよう、[ログイン]ボタンにclickイベントを設定しておきます。ログインに失敗した場合はcatchで受けて、”ログイン失敗”というアラートを表示させています。

ちなみにauth:falseという部分は、ログインしていなくてもページを表示できるようにするためのものです。デフォルトでは各ページにauth:trueが設定されており、ログインしないとページの表示がされないようになっています。当然ながら、ログインページはログインしていない状態で表示される必要があるため、auth:falseを指定しています。

<script>
    export default {
        auth: false,

ログイン後は/に遷移するようにしていますので、ログイン後に表示されるページ(pages/index.vue)も作成しておきましょう。

<template>
    <h1>ログインしました♪</h1>
</template>

ページを作成したら、さっそくログインしてみてください。うまくいきましたか?

まとめ

いかがでしたでしょうか。

SPA認証を実装しようとすると、本来はCSRFトークンの更新からクッキーに資格情報をセットしたりなど、複雑な処理を実装していく必要がありますが、Laravel Sanctumとnuxt/authを組み合わせると、かんたんにSPA認証を実装することができます。

参考になれば幸いです。

コメント

タイトルとURLをコピーしました