ホーム > Laravel > How to Authenticate with Cookies using Nuxt3 and LaravelSanctum
Laravel

How to Authenticate with Cookies using Nuxt3 and LaravelSanctum

Thank you for your continued support.
This article contains advertisements that help fund our operations.

⇨ 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

  1. Login authentication only
  2. Focus on the settings made this time
  3. 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

Documentation

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

  1. Page accessible only to users who are not logged in
definePageMeta({
  middleware: "guest",
})
  1. Use $sanctumAuth for authentication
const { $sanctumAuth } = useNuxtApp()
  1. 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

Please Provide Feedback
We would appreciate your feedback on this article. Feel free to leave a comment on any relevant YouTube video or reach out through the contact form. Thank you!