Nuxt3とLaravelSanctumでCookie認証する方法
いつもご利用ありがとうございます。
この記事には広告が掲載されており、その広告費によって運営しています。
Nuxt3 と LaravelSanctum で Cookie 認証する方法についてまとめました。
この記事では、全て書くと逆にわかりづらくなると思っているため
- ログイン認証のみ
- 今回設定したところにフォーカス
- 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>
ログインページの解説
- ログインしていないユーザーしか見られないページ
definePageMeta({
middleware: "guest",
})
- 認証にはこの $sanctumAuth を使う
const { $sanctumAuth } = useNuxtApp()
- ログインするための関数
この関数が動けばログインできます。
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 の謎のエラーが一番詰まりました。
誰かの参考になればと思います。
このブログは広告のクリックによって支えられています。
参考になったという方はぜひ、ぜひ、ぜひぜひぜひともよろしくお願いします!
それでは!
人気記事