Building a Full Authentication System with Laravel 12 and Nuxt 3

Author

Kritim Yantra

May 03, 2025

Building a Full Authentication System with Laravel 12 and Nuxt 3

Authentication is a critical part of modern web applications. In this blog, we'll explore how to build a complete authentication system using Laravel 12 and Nuxt 3. We'll use Laravel Sanctum on the backend to manage API tokens and session-based authentication, and @sidebase/nuxt-auth on the frontend for seamless integration with Nuxt 3.

By the end of this guide, you'll have a working user registration, login, logout, and session-protected setup across Laravel and Nuxt.


🛠 Technologies Used

  • Laravel 12 (Backend)
  • Laravel Sanctum (Authentication)
  • Nuxt 3 (Frontend)
  • @sidebase/nuxt-auth (Nuxt Authentication Module)

Step 1: Set Up Laravel 12 with Sanctum

Install Laravel

composer create-project --prefer-dist laravel/laravel:^12 laravel-auth
cd laravel-auth

Install Sanctum

php artisan install:api
php artisan migrate

Update User Model

Edit app/Models/User.php:

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
    // ...
}

Create Auth Controller

php artisan make:controller AuthController

app/Http/Controllers/AuthController.php

public function register(Request $request) {
    $data = $request->validate([
        'name' => 'required',
        'email' => 'required|email|unique:users',
        'password' => 'required|confirmed',
    ]);
    $user = User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
    ]);
    return ['token' => $user->createToken('auth')->plainTextToken];
}

public function login(Request $request) {
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);
    $user = User::where('email', $credentials['email'])->first();
    if (! $user || ! Hash::check($credentials['password'], $user->password)) {
        throw ValidationException::withMessages(['email' => ['Invalid credentials.']]);
    }
    return ['token' => $user->createToken('auth')->plainTextToken];
}

public function logout(Request $request) {
    $request->user()->currentAccessToken()->delete();
    return response()->noContent();
}

public function user(Request $request) {
    return $request->user();
}

Define API Routes

use App\Http\Controllers\AuthController;

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::post('/logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');
Route::get('/user', [AuthController::class, 'user'])->middleware('auth:sanctum');

Step 2: Set Up Nuxt 3 with @sidebase/nuxt-auth

Create a Nuxt Project

npx nuxi init nuxt-auth
cd nuxt-auth
npm install

Install Auth Module

npm install -D @sidebase/nuxt-auth

Configure Nuxt Auth

Create .env:

NUXT_BASE_URL=http://127.0.0.1:8000

Update nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@sidebase/nuxt-auth'],

  runtimeConfig: {
    baseURL: '/api/auth'
  },

  auth: {
    originEnvKey: 'NUXT_BASE_URL',
    provider: {
      type: 'local',
      endpoints: {
        signIn:    { path: '/login',    method: 'post' },
        signOut:   { path: '/logout',   method: 'post' },
        signUp:    { path: '/register', method: 'post' },
        getSession:{ path: '/user',     method: 'get'  },
      }
    }
  }
})

Step 3: Create Nuxt Pages

Register Page

pages/register.vue

<script setup>
const { signUp } = useAuth();
const form = reactive({ name: '', email: '', password: '', password_confirmation: '' });
const register = async () => await signUp(form);
</script>
<template>
  <form @submit.prevent="register">
    <input v-model="form.name" placeholder="Name" />
    <input v-model="form.email" placeholder="Email" />
    <input v-model="form.password" type="password" placeholder="Password" />
    <input v-model="form.password_confirmation" type="password" placeholder="Confirm Password" />
    <button type="submit">Register</button>
  </form>
</template>

Login Page

pages/login.vue

<script setup>
const { signIn } = useAuth();
const form = reactive({ email: '', password: '' });
const login = async () => await signIn(form);
</script>
<template>
  <form @submit.prevent="login">
    <input v-model="form.email" placeholder="Email" />
    <input v-model="form.password" type="password" placeholder="Password" />
    <button type="submit">Login</button>
  </form>
</template>

Logout & Protected Page

To log out:

<script setup>
const { signOut } = useAuth();
</script>
<template>
  <button @click="signOut()">Logout</button>
</template>

Protect any page using:

<script setup>
definePageMeta({ auth: true })
</script>

✅ Final Testing Checklist

  • Register a user at /register
  • Login at /login
  • Fetch user via /user
  • Logout
  • Protect routes using definePageMeta({ auth: true })

🎉 Conclusion

You now have a working authentication system with Laravel 12 and Nuxt 3 using Sanctum and @sidebase/nuxt-auth. This stack offers simplicity, power, and great developer experience.

Next steps:

  • Add email verification
  • Implement password reset
  • Integrate OAuth with Google/GitHub using Auth.js in Nuxt

Happy coding!

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts