Kritim Yantra
Jun 08, 2025
In this blog, we'll walk through setting up Laravel 12 with Passport API Authentication and integrating it with a Vue.js frontend. This guide is beginner-friendly, so even if you're new to Laravel APIs or Vue.js, you'll be able to follow along easily.
Before we begin, ensure you have:
composer create-project laravel/laravel laravel-passport-vue
)Laravel 12 introduces a new way to set up APIs using the api:install
command.
Run:
composer create-project laravel/laravel laravel-passport-vue
cd laravel-passport-vue
Update your .env
file with database credentials.
api:install
(Installs Sanctum by Default)Laravel 12 simplifies API setup:
php artisan api:install
This will:
routes/api.php
But since we want Passport (for OAuth2), we'll modify this.
Since we need Passport instead of Sanctum, we'll install it manually.
Run:
composer require laravel/passport
php artisan migrate
php artisan passport:install
This generates OAuth2 encryption keys and creates oauth_clients
in the database.
AuthServiceProvider
Open app/Providers/AuthServiceProvider.php
and update:
use Laravel\Passport\Passport;
public function boot(): void
{
Passport::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30));
Passport::personalAccessTokensExpireIn(now()->addMonths(6));
}
config/auth.php
Set the API guard to use Passport:
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Open routes/api.php
and add:
use App\Http\Controllers\AuthController;
use Illuminate\Support\Facades\Route;
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
// Protected routes (require auth)
Route::middleware('auth:api')->group(function () {
Route::get('/user', [AuthController::class, 'user']);
Route::post('/logout', [AuthController::class, 'logout']);
});
AuthController
Run:
php artisan make:controller AuthController
Update app/Http/Controllers/AuthController.php
:
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
public function register(Request $request)
{
$request->validate([
'name' => 'required|string',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = $user->createToken('authToken')->accessToken;
return response()->json(['token' => $token], 201);
}
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (!Auth::attempt($request->only('email', 'password'))) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
$user = Auth::user();
$token = $user->createToken('authToken')->accessToken;
return response()->json(['token' => $token]);
}
public function user(Request $request)
{
return response()->json($request->user());
}
public function logout(Request $request)
{
$request->user()->token()->revoke();
return response()->json(['message' => 'Logged out']);
}
We’ll use Vue 3 with axios for API calls.
Run:
npm install vue@next axios
npm install --save-dev @vitejs/plugin-vue
vite.config.js
Update:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel(['resources/js/app.js']),
vue(),
],
});
Create resources/js/App.vue
:
<template>
<div>
<h1>Laravel Passport + Vue.js Auth</h1>
<div v-if="!user">
<input v-model="form.email" placeholder="Email" />
<input v-model="form.password" placeholder="Password" type="password" />
<button @click="login">Login</button>
<button @click="register">Register</button>
</div>
<div v-else>
<p>Welcome, {{ user.name }}!</p>
<button @click="logout">Logout</button>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
form: {
email: '',
password: '',
},
user: null,
};
},
mounted() {
this.getUser();
},
methods: {
async login() {
try {
const res = await axios.post('/api/login', this.form);
localStorage.setItem('token', res.data.token);
await this.getUser();
} catch (err) {
alert(err.response.data.error || 'Login failed');
}
},
async register() {
try {
const res = await axios.post('/api/register', {
...this.form,
password_confirmation: this.form.password,
});
localStorage.setItem('token', res.data.token);
await this.getUser();
} catch (err) {
alert(err.response.data.message || 'Registration failed');
}
},
async getUser() {
try {
const token = localStorage.getItem('token');
if (!token) return;
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
const res = await axios.get('/api/user');
this.user = res.data;
} catch (err) {
localStorage.removeItem('token');
}
},
async logout() {
try {
await axios.post('/api/logout');
localStorage.removeItem('token');
this.user = null;
} catch (err) {
alert('Logout failed');
}
},
},
};
</script>
resources/js/app.js
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
welcome.blade.php
)Replace with:
<!DOCTYPE html>
<html>
<head>
<title>Laravel + Vue + Passport</title>
@vite(['resources/js/app.js'])
</head>
<body>
<div id="app"></div>
</body>
</html>
php artisan serve
npm run dev
http://localhost:8000
and test:You’ve successfully set up:
✅ Laravel 12 API with Passport Auth
✅ Vue.js 3 Frontend Integration
✅ Token-based Authentication
This setup is perfect for SPAs (Single Page Applications) and mobile apps.
Happy Coding! 😊
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google