Vue and Laravel API Token Authentication

Vue and Laravel API Token Authentication

This tutorial will guide you through setting up API token-based authentication using Laravel as the backend and Vue 3 as the frontend.

Laravel Setup

Install Laravel

composer create-project laravel/laravel laravel-api-auth

cd laravel-api-auth

php artisan serve

Create API Authentication

Laravel 10 has built-in token abilities using Sanctum.

composer require laravel/sanctum

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

php artisan migrate

Configure config/sanctum.php

Make sure middleware is included for API requests.

Add Sanctum to api middleware in app/Http/Kernel.php

'api' => [

 \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,

 'throttle:api',

 \Illuminate\Routing\Middleware\SubstituteBindings::class,

],

User Model Setup

use Laravel\Sanctum\HasApiTokens;


class User extends Authenticatable

{

 use HasApiTokens, Notifiable;

}

API Routes

routes/api.php

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Route;

use App\Models\User;

use Illuminate\Support\Facades\Hash;


Route::post('/register', function(Request $request){

 $user = User::create([

 'name' => $request->name,

 'email' => $request->email,

 'password' => Hash::make($request->password),

 ]);

 $token = $user->createToken('api-token')->plainTextToken;

 return response()->json(['user'=>$user, 'token'=>$token]);

});


Route::post('/login', function(Request $request){

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

 if(!$user || !Hash::check($request->password, $user->password)){

 return response()->json(['message'=>'Invalid credentials'], 401);

 }

 $token = $user->createToken('api-token')->plainTextToken;

 return response()->json(['user'=>$user, 'token'=>$token]);

});


Route::middleware('auth:sanctum')->get('/user', function(Request $request){

 return $request->user();

});

Vue 3 Setup

Create Vue App (with Vite)

npm create vite@latest vue-laravel-auth

cd vue-laravel-auth

npm install

npm run dev

Install Axios

npm install axios

Vue 3 Auth Store (Pinia)

npm install pinia

src/stores/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(email, password){

 const res = await axios.post('http://localhost:8000/api/login', { email, password });

 this.user = res.data.user;

 this.token = res.data.token;

 localStorage.setItem('token', this.token);

 axios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`;

 },

 async register(name, email, password){

 const res = await axios.post('http://localhost:8000/api/register', { name, email, password });

 this.user = res.data.user;

 this.token = res.data.token;

 localStorage.setItem('token', this.token);

 axios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`;

 },

 logout(){

 this.user = null;

 this.token = null;

 localStorage.removeItem('token');

 delete axios.defaults.headers.common['Authorization'];

 }

 }

});

Vue Login Component

<script setup>

import { ref } from 'vue';

import { useAuthStore } from '../stores/auth';


const email = ref('');

const password = ref('');

const auth = useAuthStore();


const handleLogin = async () => {

try {

await auth.login(email.value, password.value);

alert('Login Successful');

 } catch(e) {

alert('Invalid Credentials');

 }

};

</script>


<template>

 <input v-model="email" placeholder="Email" />

 <input v-model="password" placeholder="Password" type="password" />

 <button @click="handleLogin">Login</button>

</template>

Vue Protected Route

import axios from 'axios';

const res = await axios.get('http://localhost:8000/api/user');

console.log(res.data);