329 lines
7.7 KiB
Markdown
329 lines
7.7 KiB
Markdown
# Authentication Setup Guide
|
|
|
|
This document explains the authentication system that has been set up for your Laravel + Inertia.js + Vue 3 application.
|
|
|
|
## 📦 What Was Installed/Created
|
|
|
|
### Files Created:
|
|
1. **`resources/js/services/authService.ts`** - API service for authentication
|
|
2. **`resources/js/stores/auth.ts`** - Pinia store for auth state management
|
|
3. **`resources/js/middleware/auth.ts`** - Route guards for authentication
|
|
4. **`resources/js/composables/useAuthGuard.ts`** - Composables for protecting routes
|
|
5. **`resources/js/components/LoginExample.vue`** - Example login component
|
|
|
|
### Files Modified:
|
|
- **`resources/js/app.ts`** - Integrated auth guards
|
|
|
|
## 🔧 Setup
|
|
|
|
### Note: Pinia instead of Vuex
|
|
Your project already has **Pinia** installed, which is the official state management solution for Vue 3 (and the successor to Vuex). The setup uses Pinia instead of Vuex as requested.
|
|
|
|
If you specifically need Vuex 4, run:
|
|
```bash
|
|
npm install vuex@4
|
|
```
|
|
|
|
However, Pinia is recommended for Vue 3 projects.
|
|
|
|
## 🚀 Usage
|
|
|
|
### 1. Using the Auth Store
|
|
|
|
The auth store provides all authentication functionality:
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { useAuthStore } from '@/stores/auth';
|
|
|
|
const authStore = useAuthStore();
|
|
|
|
// Login
|
|
async function login() {
|
|
const success = await authStore.login({
|
|
email: 'user@example.com',
|
|
password: 'password',
|
|
remember: true
|
|
});
|
|
|
|
if (success) {
|
|
// Redirect or show success message
|
|
} else {
|
|
console.error(authStore.error);
|
|
}
|
|
}
|
|
|
|
// Logout
|
|
async function logout() {
|
|
await authStore.logout();
|
|
}
|
|
|
|
// Check authentication status
|
|
console.log(authStore.isAuthenticated);
|
|
console.log(authStore.currentUser);
|
|
</script>
|
|
```
|
|
|
|
### 2. Protecting Routes with Composables
|
|
|
|
#### Protect authenticated routes (dashboard, profile, etc.):
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { useAuthGuard } from '@/composables/useAuthGuard';
|
|
|
|
// This will redirect to /login if user is not authenticated
|
|
useAuthGuard();
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<h1>Protected Dashboard</h1>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
#### Protect guest routes (login, register):
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { useGuestGuard } from '@/composables/useAuthGuard';
|
|
|
|
// This will redirect to /dashboard if user is already authenticated
|
|
useGuestGuard();
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<h1>Login Page</h1>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
### 3. Accessing User Data
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { useAuthStore } from '@/stores/auth';
|
|
|
|
const authStore = useAuthStore();
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="authStore.isAuthenticated">
|
|
<p>Welcome, {{ authStore.currentUser?.name }}!</p>
|
|
<p>Email: {{ authStore.currentUser?.email }}</p>
|
|
<button @click="authStore.logout">Logout</button>
|
|
</div>
|
|
<div v-else>
|
|
<p>Please log in</p>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
### 4. Auth Store API
|
|
|
|
The auth store (`useAuthStore()`) provides:
|
|
|
|
**State:**
|
|
- `user` - Current user object or null
|
|
- `token` - Authentication token (if API returns one)
|
|
- `loading` - Loading state
|
|
- `error` - Error message
|
|
|
|
**Getters:**
|
|
- `isAuthenticated` - Boolean indicating if user is logged in
|
|
- `currentUser` - Current user object
|
|
|
|
**Actions:**
|
|
- `login(credentials)` - Login with email and password
|
|
- `logout()` - Logout current user
|
|
- `checkAuth()` - Check if user is authenticated
|
|
- `fetchUser()` - Fetch current user data
|
|
- `clearError()` - Clear error messages
|
|
- `setUser(user)` - Manually set user data
|
|
|
|
## 🔐 API Endpoints
|
|
|
|
The auth service expects these endpoints:
|
|
|
|
### Login
|
|
```
|
|
POST http://localhost:8000/api/auth/login
|
|
Body: {
|
|
"email": "user@example.com",
|
|
"password": "password",
|
|
"remember": true
|
|
}
|
|
|
|
Response: {
|
|
"user": {
|
|
"id": 1,
|
|
"name": "John Doe",
|
|
"email": "user@example.com",
|
|
...
|
|
},
|
|
"token": "optional-auth-token"
|
|
}
|
|
```
|
|
|
|
### Logout
|
|
```
|
|
POST http://localhost:8000/api/auth/logout
|
|
```
|
|
|
|
### Get Current User
|
|
```
|
|
GET http://localhost:8000/api/auth/user
|
|
|
|
Response: {
|
|
"user": {
|
|
"id": 1,
|
|
"name": "John Doe",
|
|
"email": "user@example.com",
|
|
...
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🛠️ Backend Setup (Laravel)
|
|
|
|
You need to create these API routes in Laravel. Here's an example:
|
|
|
|
```php
|
|
// routes/api.php
|
|
use App\Http\Controllers\Auth\ApiAuthController;
|
|
|
|
Route::prefix('auth')->group(function () {
|
|
Route::post('/login', [ApiAuthController::class, 'login']);
|
|
Route::post('/logout', [ApiAuthController::class, 'logout'])->middleware('auth:sanctum');
|
|
Route::get('/user', [ApiAuthController::class, 'user'])->middleware('auth:sanctum');
|
|
});
|
|
```
|
|
|
|
Example controller:
|
|
|
|
```php
|
|
// app/Http/Controllers/Auth/ApiAuthController.php
|
|
namespace App\Http\Controllers\Auth;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class ApiAuthController extends Controller
|
|
{
|
|
public function login(Request $request)
|
|
{
|
|
$credentials = $request->validate([
|
|
'email' => 'required|email',
|
|
'password' => 'required',
|
|
]);
|
|
|
|
if (Auth::attempt($credentials, $request->boolean('remember'))) {
|
|
$user = Auth::user();
|
|
$token = $user->createToken('auth-token')->plainTextToken;
|
|
|
|
return response()->json([
|
|
'user' => $user,
|
|
'token' => $token,
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'message' => 'Invalid credentials',
|
|
], 401);
|
|
}
|
|
|
|
public function logout(Request $request)
|
|
{
|
|
$request->user()->currentAccessToken()->delete();
|
|
return response()->json(['message' => 'Logged out successfully']);
|
|
}
|
|
|
|
public function user(Request $request)
|
|
{
|
|
return response()->json(['user' => $request->user()]);
|
|
}
|
|
}
|
|
```
|
|
|
|
## 💾 Persistence
|
|
|
|
The auth store automatically persists the `user` and `token` to localStorage using `pinia-plugin-persistedstate`. This means:
|
|
- User stays logged in after page refresh
|
|
- Auth state is restored on app load
|
|
- Logout clears the persisted data
|
|
|
|
## 🎯 Example: Update Your Login Page
|
|
|
|
Update your existing `resources/js/pages/auth/Login.vue`:
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { useAuthStore } from '@/stores/auth';
|
|
import { useGuestGuard } from '@/composables/useAuthGuard';
|
|
import { router } from '@inertiajs/vue3';
|
|
import { ref } from 'vue';
|
|
|
|
// Redirect if already authenticated
|
|
useGuestGuard();
|
|
|
|
const authStore = useAuthStore();
|
|
const email = ref('');
|
|
const password = ref('');
|
|
const remember = ref(false);
|
|
|
|
async function handleLogin() {
|
|
const success = await authStore.login({
|
|
email: email.value,
|
|
password: password.value,
|
|
remember: remember.value,
|
|
});
|
|
|
|
if (success) {
|
|
router.get('/dashboard');
|
|
}
|
|
}
|
|
</script>
|
|
```
|
|
|
|
## 🎯 Example: Protect Dashboard
|
|
|
|
Update your dashboard to require authentication:
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { useAuthGuard } from '@/composables/useAuthGuard';
|
|
|
|
// This will redirect to login if not authenticated
|
|
useAuthGuard();
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<h1>Dashboard</h1>
|
|
<!-- Your dashboard content -->
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
## 📝 Notes
|
|
|
|
1. **Axios is already installed** in your project at version `1.11.0`
|
|
2. **Pinia is already installed** and configured with persistence
|
|
3. The auth system works with your existing Inertia.js setup
|
|
4. CSRF tokens are automatically handled via the existing `resources/js/lib/http.ts`
|
|
5. Authentication state persists across page reloads
|
|
|
|
## 🔄 Customization
|
|
|
|
### Change API URLs
|
|
Edit `resources/js/services/authService.ts` to change the API endpoints.
|
|
|
|
### Change Redirect Routes
|
|
Edit the composables in `resources/js/composables/useAuthGuard.ts` to change default redirect routes.
|
|
|
|
### Add More User Fields
|
|
Update the `User` interface in `resources/js/services/authService.ts` to match your user model.
|