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! 😊
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 19, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google