In this section we will install & setup laravel 9 sanctum authentication with nuxt js. Nuxt JS provides automatic performance optimization, routing, component imports, and options for server-side rendering (SSR) or static site generation (SSG). If you’ve ever used Gatsby for React, modules are similar to plugins.
Setup Laravel 9 Sanctum Authentication
Create laravel project
composer create-project Laravel/laravel laravel-backend
Setup your .env file
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=database_user_name
DB_PASSWORD=database_password
Install Laravel Breeze
composer require laravel/breeze --dev
Install laravel breeze api command to create Sanctum auth.
php artisan breeze:install api
After install breeze api, you can see .env file two url for backend and frontend. You can change url in production, for local leave it.
.env
APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:3000
run project and leave it.
php artisan serve
Note: Open two terminal one for run laravel application & second to create nuxtjs project and run.
Setup Nuxt js Sanctum Authentication
Create nuxt js app
Using NPM:
npm init nuxt-app frontend
Using Yarn:
yarn create nuxt-app frontend
Then choose your project requirements.
Install Nuxtjs Auth
using yarn:
yarn add --exact @nuxtjs/auth-next
yarn add @nuxtjs/axios
using npm:
npm install --save-exact @nuxtjs/auth-next
npm install @nuxtjs/axios
Import Nuxt JS laravel Sanctum in nuxt.config.js
nuxt.config.js
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'frontend',
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/tailwindcss
'@nuxtjs/tailwindcss',
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
'@nuxtjs/axios',
'@nuxtjs/auth-next'
],
auth: {
strategies: {
laravelSanctum: {
provider: 'laravel/sanctum',
url: 'http://localhost:8000',
endpoints: {
login: {
url: '/login'
}
}
},
}
},
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
// Workaround to avoid enforcing hard-coded localhost:3000: https://github.com/nuxt-community/axios-module/issues/308
baseURL: 'http://localhost:8000',
credentials: true
},
router: {
middleware: ['auth']
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
Next, you need to create login.vue , register.vue and layouts folder add default.vue file.
Create default.vue and navbar with nuxt js link like login, register and logout.
default.vue
<template>
<div>
<nav class="container flex justify-around py-8 mx-auto bg-white">
<div>
<h3 class="text-2xl font-medium text-blue-500">LOGO</h3>
</div>
<div class="flex space-x-8">
<NuxtLink to="/">Home</NuxtLink>
<NuxtLink to="/login" v-if="!$auth.loggedIn">Login</NuxtLink>
<NuxtLink to="/register" v-if="!$auth.loggedIn">Register</NuxtLink>
<div v-if="$auth.loggedIn">
<button
type="button"
@click="logout"
>
Logout
</button>
</div>
</div>
</nav>
<Nuxt />
</div>
</template>
<script>
export default {
middleware: "auth",
methods: {
async logout() {
this.$nuxt.$loading.start();
this.$auth.logout();
this.$nuxt.$loading.finish();
this.$router.push("/login");
},
},
};
</script>
pages/register.vue
<template>
<div
class="relative flex flex-col justify-center min-h-screen overflow-hidden"
>
<div class="w-full p-6 m-auto bg-white rounded shadow-lg lg:max-w-md">
<h1 class="text-3xl font-semibold text-center text-purple-700">
Sign Up
</h1>
<form class="mt-6" ref="registerform" @submit.prevent="register">
<div>
<label for="name" class="block text-sm text-gray-800">name</label>
<input
v-model="form.name"
name="name"
type="text"
class="block w-full px-4 py-2 mt-2 text-purple-700 bg-white border rounded-md focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
/>
</div>
<div>
<label for="email" class="block text-sm text-gray-800">Email</label>
<input
v-model="form.email"
name="email"
type="email"
class="block w-full px-4 py-2 mt-2 text-purple-700 bg-white border rounded-md focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
/>
</div>
<div class="mt-4">
<div>
<label for="password" class="block text-sm text-gray-800"
>Password</label
>
<input
v-model="form.password"
name="password"
type="password"
class="block w-full px-4 py-2 mt-2 text-purple-700 bg-white border rounded-md focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
/>
</div>
<div>
<label for="password" class="block text-sm text-gray-800"
>Password Confirmation</label
>
<input
v-model="form.password_confirmation"
name="password_confirmation"
type="password"
class="block w-full px-4 py-2 mt-2 text-purple-700 bg-white border rounded-md focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
/>
</div>
<div class="mt-6">
<button
type="submit"
class="w-full px-4 py-2 tracking-wide text-white transition-colors duration-200 transform bg-purple-700 rounded-md hover:bg-purple-600 focus:outline-none focus:bg-purple-600"
>
Submit
</button>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
export default {
auth: "guest",
data() {
return {
form: {
name: null,
email: null,
password: null,
password_confirmation: null
},
errors: []
}
},
mounted() {
this.$axios.$get("/sanctum/csrf-cookie");
},
methods: {
register() {
try {
this.$axios.post("/register", this.form).then((res) => {
this.$auth.loginWith("laravelSanctum", { data: this.form });
this.$router.push({
path: "/",
});
});
} catch (err) {
console.log(err);
}
},
},
};
</script>
pages/login.vue
<template>
<div
class="relative flex flex-col justify-center min-h-screen overflow-hidden"
>
<div class="w-full p-6 m-auto bg-white rounded shadow-lg lg:max-w-md">
<h1 class="text-3xl font-semibold text-center text-purple-700">
Sign In
</h1>
<form class="mt-6" @submit.prevent="login">
<div>
<label for="email" class="block text-sm text-gray-800">Email</label>
<input
v-model="form.email"
name="email"
type="email"
class="block w-full px-4 py-2 mt-2 text-purple-700 bg-white border rounded-md focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
/>
</div>
<div class="mt-4">
<div>
<label for="password" class="block text-sm text-gray-800"
>Password</label
>
<input
v-model="form.password"
name="password"
type="password"
class="block w-full px-4 py-2 mt-2 text-purple-700 bg-white border rounded-md focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
/>
</div>
<div class="mt-6">
<button
type="submit"
class="w-full px-4 py-2 tracking-wide text-white transition-colors duration-200 transform bg-purple-700 rounded-md hover:bg-purple-600 focus:outline-none focus:bg-purple-600"
>
Login
</button>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
export default {
auth: "guest",
data() {
return {
form: {
email: null,
password: null,
},
};
},
mounted() {
this.$axios.$get("/sanctum/csrf-cookie");
},
methods: {
async login() {
this.$nuxt.$loading.start();
try {
await this.$auth.loginWith("laravelSanctum", { data: this.form });
this.$router.push({
path: "/",
});
} catch (err) {
console.log(err);
}
this.$nuxt.$loading.finish();
},
},
};
</script>
pages/index.vue
<template>
<div>
<div class="flex items-center justify-center h-screen">
<div class="max-w-xl p-5 shadow">
<div v-if="!$auth.loggedIn">
<h3>Home</h3>
</div>
<div v-if="$auth.loggedIn">
<div>Name:{{ $auth.user.name }}</div>
<div>Name:{{ $auth.user.email }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "IndexPage",
};
</script>
Run the server
npm run dev
Read Also
Laravel 9 Add Simple Sidebar with Tailwind CSS Example
How to Use Carousel Slider in Laravel 9 Example
Laravel 9 Posts with Tags Many to Many Relationships Example
Laravel 9 Insert Category in Posts CRUD Example
How to Use Ckeditor 5 in Laravel 9 Vite with Tailwind CSS
Laravel 9 Simple Image Upload in Ckeditor 5 Example
Laravel 9 Flash Message Timeout and Hide Message Example
Install & Setup Markdown Editor in Laravel 9
Nuxt 3 Data Fetching Using Laravel 9 Api Example
Laravel 9 Image Upload with Preview using Tailwind CSS & Alpine JS
Laravel 9 with Tailwind CSS Form Validation Example
Laravel 9 Backend Api Connect with Vue 3 Using Axios Example
Laravel 9 Authentication with Next js Example
Laravel 9 Simple Search with Pagination Example
Laravel 9 Install Setup TALL(Tailwind, Alpinejs, Livewire) Admin Panel
How to Fix and Clean Code Style in laravel 9
Laravel 9 Image File Upload Example
3 Way to Create Slug in Laravel 9 without Package
How to Add Dark Mode in Laravel 9 with Tailwind CSS