How to Authenticate with Cookies using Nuxt3 and LaravelSanctum
Thank you for your continued support.
This article contains advertisements that help fund our operations.
Table Of Contents
⇨ Click here for the table of contents for Laravel articles
I have summarized how to authenticate with cookies using Nuxt3 and LaravelSanctum.
Since I believe that writing everything in this article would make it more confusing
- Login authentication only
- Focus on the settings made this time
- Using the Nuxt Sanctum Auth package
Environment Tested
Laravel10
Nuxt3
Laravel Configuration
Please handle the DB connection, etc. by yourself.
Enable LaravelSanctum
In the Laravel project, run the command
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
If the config/sanctum.php file is created, it should be OK. Apparently not needed in laravel10.
Do not make any changes to this config file.
Add Middleware in Kernel
Since the routes we will use are written in api.php, add middleware.
In App/Http/Kernel.php, update the 'api' section as follows.
'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,
],
This will make cookies and sessions usable.
Adjust CORS Configuration
config/cors.php
'supports_credentials' => true, // Change from false to true
Reflect the configuration changes using the command
php artisan config:clear
Create Login Controller
php artisan make:controller AuthController
Add a function for logging in to the created AuthController.
Regenerate the session.
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' => 'Login successful']);
}
}
Create Routes
routes/api.php
Route::post('/login', 'App\Http\Controllers\AuthController@login');
// to be used later
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);
});
});
The Laravel configuration is complete.
Nuxt Configuration
Install Nuxt Sanctum Auth
Install with the command. Run the following command in the Nuxt project.
npm i nuxt-sanctum-auth
Update nuxt.config.[js,ts]
Please read the comments in the configuration for explanations.
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
ssr: false, // Since this package does not support SSR
devtools: { enabled: true },
modules: [
"nuxt-sanctum-auth",
// ...
],
nuxtSanctumAuth: {
token: false, // Set to true for token authentication, false for cookie authentication
baseUrl: "http://localhost:8081", // Local server of Laravel
endpoints: {
csrf: "/sanctum/csrf-cookie", // URL to get csrf token from the server. Use this if Laravel's default configuration
login: "/api/login", // URL to POST for login
logout: "/api/logout", // URL to POST for logout, not used in this case
user: "/api/user", // URL to GET user information from the server
},
csrf: {
headerKey: "X-XSRF-TOKEN",
cookieKey: "XSRF-TOKEN",
tokenCookieKey: "nuxt-sanctum-auth-token", // Keep default value
},
redirects: {
home: "/show", // Redirect after login
login: "/login", // Login page
logout: "/", // After logout
},
},
})
Files for Display
- To use routing
app.vue
<template>
<div>
<NuxtPage />
</div>
</template>
- Login page
pages/login.vue
<template>
<div>
<div>
<form>
<dl>
<dt>Email:</dt>
<dd><input id="email" type="string" v-model="email" /></dd>
</dl>
<dl>
<dt><label for="password">Password:</label></dt>
<dd><input id="password" type="password" v-model="password" /></dd>
</dl>
<button type="button" @click="login">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", // Test user email
password: "password", // Test user password
})
}
</script>
<style scoped></style>
You can log in by clicking the login button.
Create the pages folder and files for each page.
- Create a page for after logging in
pages/show.vue
<script setup>
definePageMeta({
middleware: "auth",
})
const { $apiFetch } = useNuxtApp()
const users = ref()
const { user, loggedIn } = useAuth()
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">Post</button>
</div>
</div>
</template>
<style></style>
Explanation of Login Page
- Page accessible only to users who are not logged in
definePageMeta({
middleware: "guest",
})
- Use $sanctumAuth for authentication
const { $sanctumAuth } = useNuxtApp()
- Function to login
This function allows you to log in.
const login = async () => {
await $sanctumAuth.login({
email: "test@test.com", // Test user email
password: "password", // Test user password
})
}
You can log in if the email and password match the test user's.
How to Use After Logging In
Basically, use fetch in JS, and replace it with the unique $apiFetch function of this package to perform both GET and POST operations similarly.
The code in show.vue
const users = ref()
const { $apiFetch } = useNuxtApp()
const post = async () => {
const response = await $apiFetch(`api/posts`, { method: "POST" })
users.value = response.users
}
This part.
By running the post function,
we implement a POST request to fetch user data.
For creating a test user,
refer to Creating a Test User.
Note
At the moment, it seems that this package does not support SSR.
If you try to implement with SSR, the behavior of the page refresh upon F5 became strange.
Server determines login/non-login
→ Identified as non-login
→ Redirect to login page
→ Communicate with the server based on cookies and authenticate
→ Redirect to the logged-in page
This leads to flickering screens and the page returning to the top page upon every refresh.
Docker Configuration (Laravel)
I have posted it on the GitHub page.
Nuxt is running on the local server.
npm -v
10.2.4
I use Volta for node version management.
It's simple and convenient.
Conclusion
That's all. I had the most trouble with a mysterious Docker error.
I hope it proves helpful to someone.
This blog is supported by clicks on advertisements.
If you found it helpful, please, please, please support us by clicking on the ads!
That's all!
Popular Articles
Deploy a PHP7.4 + Laravel6 Project to AWS EC2
Implementing Breadcrumbs in Laravel with laravel-breadcrumbs