Vue 3 Auth Setup

User
Vue 3 login and register setup
Assistant
Setting up login and registration in Vue 3 typically involves integrating it with a backend (e.g., Laravel). Below is a structured approach to implementing authentication using Vue 3 with Vue Router and Axios.

## **1. Install Dependencies**
Ensure you have Vue 3, Vue Router, and Axios installed.

npm install vue-router@4 axios

## **2. Setup Vue Router**
Create a `router.js` file to define routes.

import { createRouter, createWebHistory } from 'vue-router';
import Login from './views/Login.vue';
import Register from './views/Register.vue';
import Dashboard from './views/Dashboard.vue';

const routes = [
  { path: '/', redirect: '/login' },
  { path: '/login', component: Login },
  { path: '/register', component: Register },
  { path: '/dashboard', component: Dashboard, meta: { requiresAuth: true } }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

// Navigation guard
router.beforeEach((to, from, next) => {
  const isAuthenticated = !!localStorage.getItem('token'); // Check if token exists
  if (to.meta.requiresAuth && !isAuthenticated) {
    next('/login');
  } else {
    next();
  }
});

export default router;

## **3. Create Authentication Store (Optional)**
Use Pinia or Vue’s reactive state for managing authentication.

Install Pinia:

npm install pinia

Then, create a `store/auth.js`:

import { defineStore } from 'pinia';
import axios from 'axios';

export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: null,
    token: localStorage.getItem('token') || null
  }),
  actions: {
    async login(credentials) {
      const response = await axios.post('/api/login', credentials);
      this.token = response.data.token;
      localStorage.setItem('token', this.token);
      axios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`;
    },
    async register(userData) {
      await axios.post('/api/register', userData);
    },
    logout() {
      this.token = null;
      this.user = null;
      localStorage.removeItem('token');
      delete axios.defaults.headers.common['Authorization'];
    }
  }
});

## **4. Create Login Component (`views/Login.vue`)**

<script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { useAuthStore } from '../store/auth';

const router = useRouter();
const authStore = useAuthStore();

const email = ref('');
const password = ref('');
const errorMessage = ref('');

const login = async () => {
  try {
    await authStore.login({ email: email.value, password: password.value });
    router.push('/dashboard');
  } catch (error) {
    errorMessage.value = error.response?.data?.message || 'Login failed';
  }
};
</script>

<template>
  <div>
    <h2>Login</h2>
    <input v-model="email" type="email" placeholder="Email">
    <input v-model="password" type="password" placeholder="Password">
    <button @click="login">Login</button>
    <p v-if="errorMessage">{{ errorMessage }}</p>
  </div>
</template>

## **5. Create Register Component (`views/Register.vue`)**

<script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { useAuthStore } from '../store/auth';

const router = useRouter();
const authStore = useAuthStore();

const name = ref('');
const email = ref('');
const password = ref('');
const errorMessage = ref('');

const register = async () => {
  try {
    await authStore.register({ name: name.value, email: email.value, password: password.value });
    router.push('/login');
  } catch (error) {
    errorMessage.value = error.response?.data?.message || 'Registration failed';
  }
};
</script>

<template>
  <div>
    <h2>Register</h2>
    <input v-model="name" type="text" placeholder="Name">
    <input v-model="email" type="email" placeholder="Email">
    <input v-model="password" type="password" placeholder="Password">
    <button @click="register">Register</button>
    <p v-if="errorMessage">{{ errorMessage }}</p>
  </div>
</template>

## **6. Create Dashboard Component (`views/Dashboard.vue`)**

<script setup>
import { useAuthStore } from '../store/auth';
import { useRouter } from 'vue-router';

const authStore = useAuthStore();
const router = useRouter();

const logout = () => {
  authStore.logout();
  router.push('/login');
};
</script>

<template>
  <div>
    <h2>Dashboard</h2>
    <button @click="logout">Logout</button>
  </div>
</template>

## **7. Setup Axios Global Config (`main.js`)**

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
import axios from 'axios';

axios.defaults.baseURL = 'http://localhost:8000'; // Change according to your backend API

const app = createApp(App);
app.use(createPinia());
app.use(router);
app.mount('#app');

### **8. Backend (Laravel) API Setup (Optional)**
If using Laravel, set up API routes in `routes/api.php`:

use AppHttpControllersAuthController;
use IlluminateSupportFacadesRoute;

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Example `AuthController.php`:

namespace AppHttpControllers;

use AppModelsUser;
use IlluminateHttpRequest;
use IlluminateSupportFacadesHash;
use IlluminateValidationValidationException;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:6'
        ]);

        User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password)
        ]);

        return response()->json(['message' => 'User registered successfully'], 201);
    }

    public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required'
        ]);

        $user = User::where('email', $request->email)->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages(['email' => 'Invalid credentials']);
        }

        return response()->json(['token' => $user->createToken('auth_token')->plainTextToken]);
    }
}

## **9. Protect Routes (Sanctum Middleware)**
Ensure Laravel Sanctum is installed:

composer require laravel/sanctum
php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"
php artisan migrate

Then add `'auth:sanctum'` middleware to protected API routes.

## **10. Test Authentication Flow**
– Run your Laravel backend (`php artisan serve`)
– Run your Vue app (`npm run dev`)
– Try registering, logging in, and accessing the dashboard

This setup ensures a complete login and registration flow in Vue 3 with a Laravel API backend. Let me know if you need modifications based on your project.

Leave a Comment

Your email address will not be published. Required fields are marked *