In this section we will create laravel rest api auth with passport and frontend we will using vue 3 composition api.
Tool Use
Laravel 9
Laravel Passport
Tailwind CSS
Vue 3 Composition Api
Vite Tool
Vue 3 Axios
Vue Router
Create Laravel Project
Install fresh laravel app and connect to mysql database.
composer create-project --prefer-dist laravel/laravel laravel-api
Install & Setup Passport
Install Passport via the Composer package manager:
composer require laravel/passport
Migrate database
php artisan migrate
Install passport client secret key
php artisan passport:install
Setup passport HasApiTokens traits in user modal,
app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
// use Laravel\Sanctum\HasApiTokens;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Next, you should call the Passport::routes method within the boot method of your App\Providers\AuthServiceProvider.
app/Providers/AuthServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
if (! $this->app->routesAreCached()) {
Passport::routes();
}
}
}
Next, you need to set api driver for passport.
config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Create Api Controller & Routes
Run below command to create controller within api folder.
php artisan make:controller Api/AuthController
app/Http/Controllers/Api/AuthController.php
<?php
namespace App\Http\Controllers\Api;
use App\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Validation\Rules;
class AuthController extends Controller
{
public function login(Request $request)
{
if (auth()->attempt($request->all())) {
return response([
'user' => auth()->user(),
'access_token' => auth()->user()->createToken('authToken')->accessToken
], Response::HTTP_OK);
}
return response([
'message' => 'This User does not exist'
], Response::HTTP_UNAUTHORIZED);
}
public function register(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password)
]);
return response($user, Response::HTTP_CREATED);
}
}
routes/api.php
<?php
use App\Http\Controllers\Api\AuthController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::post('login', [AuthController::class, 'login']);
Route::post('register', [AuthController::class, 'register']);
Run laravel server and leave it.
php artisan serve
Install & Setup Vue 3 Composition Api Authentication with Laravel Rest Api
Create vue 3 project.
npm init vue@latest
Select your requirements.
Vue.js - The Progressive JavaScript Framework
✔ Project name: … frontend
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
Scaffolding project in /vue-project/frontend...
Done. Now run:
cd frontend
npm install
npm run dev
Install axios
run below command to install vue-axios
npm i vue-axios
Install Tailwind CSS in Vue 3
How to Install Tailwind CSS in Vue 3
or
Set Axios Path in vue 3
Setup Api path in main.js using axios.
src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './index.css'
import axios from 'axios'
axios.defaults.baseURL = 'http://localhost:8000/api/';
axios.defaults.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`;
const app = createApp(App)
app.use(router)
app.mount('#app')
Create vue 3 route file
src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Login from '../views/auth/Login.vue'
import Register from '../views/auth/Register.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/register',
name: 'register',
component: Register
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue')
}
]
})
export default router
Setup vue 3 App file
Create Navbar file and add route link.
src/components/Navbar.vue
<template>
<nav class="container flex justify-around py-8 mx-auto bg-white border">
<div>
<h3 class="text-2xl font-medium text-blue-500">LOGO</h3>
</div>
<div class="flex items-center space-x-8">
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
<RouterLink to="/login">Login</RouterLink>
<RouterLink to="/register">Register</RouterLink>
<button @click="Logout">Logout</button>
</div>
</nav>
</template>
<script>
import { useRouter } from 'vue-router';
export default {
setup() {
const router = useRouter();
const Logout = () => {
localStorage.clear();
router.push({ path: '/login' });
};
return { Logout };
},
};
</script>
src/App.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router';
import Navbar from '@/components/Navbar.vue';
</script>
<template>
<div>
<Navbar />
</div>
<RouterView />
</template>
Setup Authentication with Vue 3 Composition Api
src/views/auth/Register.vue
<script>
import { ref } from 'vue';
import axios from 'axios';
import { useRouter } from 'vue-router';
export default {
name: 'Register',
setup() {
const name = ref('');
const email = ref('');
const password = ref('');
const password_confirmation = ref('');
const router = useRouter();
const validation = ref([]);
const submit = async () => {
await axios
.post('/register', {
name: name.value,
email: email.value,
password: password.value,
password_confirmation: password_confirmation.value,
})
.then(() => {
router.push({ path: '/login' });
})
.catch((error) => {
validation.value = error.response.data;
});
};
return {
name,
email,
password,
password_confirmation,
submit,
validation,
};
},
};
</script>
<template>
<div class="relative flex flex-col items-center justify-center min-h-screen">
<span class="px-2 py-2 mb-4 text-red-600 rounded shadow">
{{ validation.message }}
</span>
<div class="w-full p-6 shadow bg-gray-50 lg:max-w-md">
<h1 class="text-3xl font-semibold text-center text-purple-700">LOGO</h1>
<form class="space-y-4" @submit.prevent="submit">
<div>
<label for="name" class="block text-sm text-gray-800">Name</label>
<input
v-model="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="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>
<label for="password" class="block text-sm text-gray-800"
>Password</label
>
<input
v-model="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 Confirm</label
>
<input
v-model="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>
<button
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"
>
Create Account
</button>
</div>
</form>
<p class="mt-8 text-xs font-light text-center text-gray-700">
Don't have an account?
<RouterLink
to="/login"
class="font-medium text-purple-600 hover:underline"
>Login</RouterLink
>
>
</p>
</div>
</div>
</template>
src/views/auth/Login.vue
<script>
import { ref } from 'vue';
import axios from 'axios';
import { useRouter } from 'vue-router';
export default {
name: 'Login',
setup() {
const email = ref('');
const password = ref('');
const router = useRouter();
const submit = async () => {
const response = await axios.post('/login', {
email: email.value,
password: password.value,
});
localStorage.setItem('token', response.data.token);
await router.push({ path: '/' });
};
return {
email,
password,
submit,
};
},
};
</script>
<template>
<div class="relative flex flex-col items-center justify-center min-h-screen">
<div class="w-full p-6 shadow bg-gray-50 lg:max-w-md">
<h1 class="text-3xl font-semibold text-center text-purple-700">LOGO</h1>
<form class="space-y-4" @submit.prevent="submit">
<div>
<label for="email" class="block text-sm text-gray-800">Email</label>
<input
type="email"
name="email"
v-model="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>
<label for="password" class="block text-sm text-gray-800"
>Password</label
>
<input
type="password"
name="password"
v-model="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>
<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>
</form>
<p class="mt-8 text-xs font-light text-center text-gray-700">
Don't have an account?
<RouterLink
to="/register"
class="font-medium text-purple-600 hover:underline"
>Register</RouterLink
>
</p>
</div>
</div>
</template>
Run vue 3 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 Sanctum Authentication with Nuxt 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