Laravel 12 API Authentication with Passport & Vue.js Integration (Beginner-Friendly Guide)

Author

Kritim Yantra

Jun 08, 2025

Laravel 12 API Authentication with Passport & Vue.js Integration (Beginner-Friendly Guide)

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.


Prerequisites

Before we begin, ensure you have:

  • PHP (>= 8.1) & Composer installed
  • Node.js & npm (for Vue.js)
  • Laravel 12 installed (composer create-project laravel/laravel laravel-passport-vue)
  • Basic knowledge of Laravel & Vue.js

Step 1: Install Laravel 12 & Set Up API Routes

Laravel 12 introduces a new way to set up APIs using the api:install command.

1.1 Install Laravel & Configure Database

Run:

composer create-project laravel/laravel laravel-passport-vue
cd laravel-passport-vue

Update your .env file with database credentials.

1.2 Run api:install (Installs Sanctum by Default)

Laravel 12 simplifies API setup:

php artisan api:install

This will:

  • Create routes/api.php
  • Install Laravel Sanctum (default for APIs)
  • Publish Sanctum’s config & migrations

But since we want Passport (for OAuth2), we'll modify this.


Step 2: Install & Configure Laravel Passport

Since we need Passport instead of Sanctum, we'll install it manually.

2.1 Install Passport

Run:

composer require laravel/passport
php artisan migrate
php artisan passport:install

This generates OAuth2 encryption keys and creates oauth_clients in the database.

2.2 Configure Passport in 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));
}

2.3 Update config/auth.php

Set the API guard to use Passport:

'guards' => [
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

Step 3: Create API Authentication Routes

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']);
});

3.1 Create 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']);
}

Step 4: Set Up Vue.js Frontend

We’ll use Vue 3 with axios for API calls.

4.1 Install Vue.js & Axios

Run:

npm install vue@next axios
npm install --save-dev @vitejs/plugin-vue

4.2 Configure 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(),
    ],
});

4.3 Create Vue Components

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>

4.4 Update resources/js/app.js

import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');

4.5 Update Blade File (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>

Step 5: Test the Application

  1. Run Laravel:
    php artisan serve
    
  2. Run Vite for frontend:
    npm run dev
    
  3. Visit http://localhost:8000 and test:
    • Registration
    • Login
    • Logout
    • Protected user data fetch

Conclusion

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.

Hope this helps! 🚀 Let me know if you have any questions.

Happy Coding! 😊

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts