ホーム > Laravel > Nuxt3とLaravelSanctumでCookie認証する方法
Laravel

Nuxt3とLaravelSanctumでCookie認証する方法

いつもご利用ありがとうございます。
この記事には広告が掲載されており、その広告費によって運営しています。

⇨ Laravel 記事の目次はこちら

Nuxt3 と LaravelSanctum で Cookie 認証する方法についてまとめました。

この記事では、全て書くと逆にわかりづらくなると思っているため

  1. ログイン認証のみ
  2. 今回設定したところにフォーカス
  3. Nuxt Sanctum Auth というパッケージを利用する

しています。

検証した環境

Laravel10
Nuxt3

Laravel 側の設定

DB の接続等については各自でお願いします。

LaravelSanctum を使えるようにする

Laravel プロジェクトでコマンド

composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

これで config/sanctum.php が作成されれば OK です。ちなみに laravel10 では不要みたいです。

そしてこの config ファイル一切変更しません。

Kernel でミドルウェアを追加する

今回使用するルーティングは api.php に書いていくため、ミドルウェアを追加します。

App/Http/Kernel.php の api の項目を以下のようにします。

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Session\Middleware\StartSession::class,
        ],

これでクッキーやセッションが使えるようになりました。

cors の設定を少し変える

config/cors.php

'supports_credentials' => true, //falseから変更する

コマンドで設定の変更を反映させます

php artisan config:clear

ログイン用のコントローラーを作成

php artisan make:controller AuthController

作成した AuthController に、ログイン用の関数を追加。

セッションを regenerate しています。

use Auth;

public function login(Request $request) {
    $credentials = $request->validate([
        'email' => ['required', 'email'],
        'password' => ['required'],
    ]);

    if (Auth::attempt($credentials)) {
        $request->session()->regenerate();
        return response()->json(['message' => 'ログイン成功']);
    }
}

ルーティングの作成

routes/api.php

Route::post('/login', 'App\Http\Controllers\AuthController@login');

//あとで使います。
Route::group(['middleware' => 'auth:sanctum'], function () {
    Route::get('/user', function (Request $request) {
        $user = $request->user();
        \Log::info($user);
        return $user;
    });
    Route::post('/posts', function (Request $request) {
        $users = User::all();
        return response()->json(compact('users'),200);
     });
});

Laravel の設定は以上です。

Nuxt 側の設定をする

Nuxt Sanctum Auth をインストールする

ドキュメント

コマンドでインストールします。Nuxt プロジェクトで以下のコマンド

npm i nuxt-sanctum-auth

nuxt.config.[js,ts]を変更する

設定の解説についてはコメントアウトを読んでください。

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  ssr: false, //このパッケージは、SSR対応していないので書く
  devtools: { enabled: true },
  modules: [
    "nuxt-sanctum-auth",
    // ...
  ],
  nuxtSanctumAuth: {
    token: false, // token認証ならここをTrueにするが、今回はクッキー認証なのでfalse
    baseUrl: "http://localhost:8081", //Laravel側のローカルサーバー
    endpoints: {
      csrf: "/sanctum/csrf-cookie", //csrf-tokenをサーバーからGETするURL。Laravelの設定がデフォルトならこれ
      login: "/api/login", //ログイン用、サーバーにPOSTするURL。
      logout: "/api/logout", //ログアウト用、サーバーにPOSTするURL。今回は使わない
      user: "/api/user", //ユーザー情報をサーバーからGETするURL
    },
    csrf: {
      headerKey: "X-XSRF-TOKEN",
      cookieKey: "XSRF-TOKEN",
      tokenCookieKey: "nuxt-sanctum-auth-token", //デフォルトならこのままでOK
    },
    redirects: {
      home: "/show", //ログイン後などでリダイレクト
      login: "/login", //ログインページ
      logout: "/", //ログアウト後
    },
  },
})

表示するためのファイル

  • ルーティングを使うため

app.vue

<template>
  <div>
    <NuxtPage />
  </div>
</template>
  • ログインページ

pages/login.vue

<template>
  <div>
    <div>
      <form>
        <dl>
          <dt>メールアドレス:</dt>
          <dd><input id="email" type="string" v-model="email" /></dd>
        </dl>
        <dl>
          <dt><label for="password">パスワード:</label></dt>
          <dd><input id="password" type="password" v-model="password" /></dd>
        </dl>
        <button type="button" @click="login">ログイン</button>
      </form>
    </div>
  </div>
</template>

<script setup>
definePageMeta({
  middleware: "guest",
})
const { $sanctumAuth } = useNuxtApp()
const router = useRouter()
const login = async () => {
  await $sanctumAuth.login({
    email: "test@test.com", // テストユーザーのメールアドレス
    password: "password", // テストユーザーのパスワード
  })
}
</script>

<style scoped></style>

ログインボタン押せばログインできます。

pages というフォルダは各自作成してファイルを作成しました。

  • ログイン後のページも作成。

pages/show.vue

<script setup>
definePageMeta({
  middleware: "auth",
})

const { $apiFetch } = useNuxtApp()
const users = ref()
const { user, loggedIn } = useAuth() // or useState('auth').value

const post = async () => {
  const response = await $apiFetch(`api/posts`, { method: "POST" })
  users.value = response.users
}
</script>

<template>
  <div>
    <div v-for="user in users">{{ user.name }}</div>
    <div>
      <button @click="post">ポスト</button>
    </div>
  </div>
</template>

<style></style>

ログインページの解説

  1. ログインしていないユーザーしか見られないページ
definePageMeta({
  middleware: "guest",
})
  1. 認証にはこの $sanctumAuth を使う
const { $sanctumAuth } = useNuxtApp()
  1. ログインするための関数

この関数が動けばログインできます。

const login = async () => {
  await $sanctumAuth.login({
    email: "test@test.com", // テストユーザーのメールアドレス
    password: "password", // テストユーザーのパスワード
  })
}

email とパスワードがテストユーザーとマッチすれば、これだけでログインできます。

ログイン後どのように使うか

基本的に JS の fetch を、

このパッケージ独特の関数である$apiFetch に置き換えれば、あとは同じように GET も POST もできそうです。

show.vue に書かれているコード

const users = ref()
const { $apiFetch } = useNuxtApp()
const post = async () => {
  const response = await $apiFetch(`api/posts`, { method: "POST" })
  users.value = response.users
}

この部分です。

post という関数が動けば、

users のデータを取得する POST 送信を実装しています。

テストユーザーの作り方については、

テストユーザーの作り方

こちらを参照してください。

注意点

現時点このパッケージを使うと、SSR には対応していないようです。

ちなみに SSR で実装しようとすると、F5 等で画面を更新した挙動が変になりました。

サーバーでログイン・非ログインを判定
→ 非ログインと判定
→ ログイン画面に飛ぶ
→ クッキーを元にサーバーと通信、認証されている
→ ログイン後のページに飛ぶ

つまり画面がチカチカするということと、画面更新するとトップページに毎回戻る感じになってしまいます。

Docker の設定(Laravel)

GitHub ページ に載せてみました。

Nuxt はローカルサーバーで起動してます。

npm -v
10.2.4

node のバージョン管理は volta を使ってます。

これは簡単で便利です。

まとめ

以上です。Docker の謎のエラーが一番詰まりました。

誰かの参考になればと思います。

このブログは広告のクリックによって支えられています。

参考になったという方はぜひ、ぜひ、ぜひぜひぜひともよろしくお願いします!

それでは!

人気記事

PHP7.4 + Laravel6 のプロジェクトを AWS EC2 にデプロイする

【laravel-breadcrumbs】Laravel でパンくずリストを実装する

フィードバックのお願い
この記事のフィードバックがありましたらYoutubeの適当な動画にコメントしていただいたり、お問い合わせからご連絡ください。