Implementing JWT Authentication in a Vue.js Application with Laravel
Introduction
JSON Web Tokens (JWT) are a popular method for implementing authentication in web applications. They provide a secure and efficient way to manage user sessions. In this article, we will explore how to implement JWT authentication in a Vue.js application using Laravel as the backend.
Setting Up the Project
To begin, you need to set up a new Laravel project using the following command:
bash
composer create-project --prefer-dist laravel/laravel jwt-laravel-vue
Next, install the necessary dependencies for Vue.js:
bash
npm install
Laravel Configuration
In Laravel, you need to install the JWT authentication package. You can do this using the following command:
bash
composer require tymon/jwt-auth
Then, add the JWT authentication service provider to the `config/app.php` file:
php
'providers' => [
// Other service providers...
Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
],
Creating the JWT Token
To create a JWT token, you need to use the `JWTAuth` facade in Laravel. Here is an example of how to do this:
php
use Tymon\JWTAuth\Facades\JWTAuth;
// Generate a token
$token = JWTAuth::attempt(['email' => '
<script language='JavaScript' type='text/javascript'>
<!--
var prefix = 'mailto:';
var suffix = '';
var attribs = '';
var path = 'hr' + 'ef' + '=';
var addy20111 = 'user' + '@';
addy20111 = addy20111 + 'example' + '.' + 'com';
document.write( '<a ' + path + '\'' + prefix + addy20111 + suffix + '\'' + attribs + '>' );
document.write( addy20111 );
document.write( '<\/a>' );
//-->
</script><script language='JavaScript' type='text/javascript'>
<!--
document.write( '<span style=\'display: none;\'>' );
//-->
</script>This e-mail address is being protected from spambots. You need JavaScript enabled to view it
<script language='JavaScript' type='text/javascript'>
<!--
document.write( '</' );
document.write( 'span>' );
//-->
</script>', 'password' => 'password']);
// Verify the token
if (!$token) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
// Return the token
return response()->json(['token' => $token]);
Handling JWT Tokens in Vue.js
In Vue.js, you can handle JWT tokens by storing them in local storage. Here is an example of how to do this:
javascript
// Store the token
localStorage.setItem('token', token);
// Retrieve the token
const token = localStorage.getItem('token');
// Use the token to make authenticated requests
axios.get('/api/data', {
headers: {
Authorization: `Bearer ${token}`,
},
});
Handling Token Refresh
When the token expires, you need to refresh it. You can do this by making a request to the `/refresh` endpoint in Laravel:
php
// Refresh the token
$token = JWTAuth::refresh($token);
// Store the new token
localStorage.setItem('token', $token);
Handling Token Revocation
When a user logs out, you need to revoke their token. You can do this by making a request to the `/revoke` endpoint in Laravel:
php
// Revoke the token
JWTAuth::revokeToken($token);
Implementing JWT authentication in a Vue.js application with Laravel involves setting up the JWT authentication package in Laravel, generating and verifying JWT tokens, and handling token refresh and revocation in Vue.js. By following these steps, you can securely manage user sessions in your application.
Here are some code examples for implementing JWT authentication in a Vue.js application with Laravel:
Setting Up JWT Authentication in Laravel
php
// Install JWT Auth package
composer require tymon/jwt-auth
// Add JWT Auth service provider and facade to Laravel
// config/app.php
'providers' => [
// ...
Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
],
'aliases' => [
// ...
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
],
// Configure JWT Auth in config/auth.php
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
// Create a User model that implements JWTSubject
// app/Models/User.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
// ...
public function getJWTCustomClaims()
{
return [];
}
public function getJWTIdentifier()
{
return $this->getKey();
}
}
Implementing JWT Authentication in Vue.js
javascript
// Install Vue.js and Vue Router
npm install vue vue-router
// Create a Vue.js component for login
// resources/js/components/Login.vue
<template>
<form @submit.prevent="login">
<input type="email" v-model="email" placeholder="Email">
<input type="password" v-model="password" placeholder="Password">
<button type="submit">Login</button>
</form>
</template>
<script>
export default {
data() {
return {
email: '',
password: '',
};
},
methods: {
login() {
axios.post('/api/auth/login', {
email: this.email,
password: this.password,
})
.then((response) => {
const token = response.data.token;
localStorage.setItem('id_token', token);
this.$router.push('/home');
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
// Create a Vue.js component for protected routes
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
<script>
export default {
data() {
return {
user: {},
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
};
</script>
// Update app.js to include Vue Router and JWT authentication
// resources/js/app.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import { JWTAuth } from 'vue-jwt-auth';
Vue.use(VueRouter);
Vue.use(JWTAuth);
const router = new VueRouter({
routes: [
{
path: '/login',
component: Login,
},
{
path: '/home',
component: Home,
meta: {
requiresAuth: true,
},
},
],
});
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => record.meta.requiresAuth)) {
const token = localStorage.getItem('id_token');
if (!token) {
next({ path: '/login' });
} else {
next();
}
} else {
next();
}
});
Handling JWT Refresh Tokens
php
// Implement refresh token logic in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function refresh()
{
$token = JWTAuth::refresh();
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle refresh tokens
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
token: '',
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
methods: {
refreshToken() {
axios.post('/api/auth/refresh')
.then((response) => {
this.token = response.data.token;
localStorage.setItem('id_token', this.token);
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
Handling JWT Authentication Errors
php
// Implement error handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function login(Request $request)
{
$credentials = $request->only(['email', 'password']);
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle authentication errors
// resources/js/components/Login.vue
<template>
<form @submit.prevent="login">
<input type="email" v-model="email" placeholder="Email">
<input type="password" v-model="password" placeholder="Password">
<button type="submit">Login</button>
</form>
</template>
</script><script>
export default {
data() {
return {
email: '',
password: '',
};
},
methods: {
login() {
axios.post('/api/auth/login', {
email: this.email,
password: this.password,
})
.then((response) => {
const token = response.data.token;
localStorage.setItem('id_token', token);
this.$router.push('/home');
})
.catch((error) => {
if (error.response.status === 401) {
this.$toast.error('Invalid credentials');
} else {
this.$toast.error('Error logging in');
}
});
},
},
};
</script>
Protecting Routes with JWT Authentication
php
// Implement route protection in Laravel's routes/api.php
// routes/api.php
Route::group(['middleware' => 'jwt.auth'], function () {
Route::get('/api/auth/user', 'AuthController@user');
});
Using JWT Authentication in Vue.js
javascript
// Update Vue.js code to use JWT authentication
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
};
</script>
Handling JWT Token Expiration
php
// Implement token expiration handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function refresh()
{
$token = JWTAuth::refresh();
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle token expiration
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
token: '',
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
methods: {
refreshToken() {
axios.post('/api/auth/refresh')
.then((response) => {
this.token = response.data.token;
localStorage.setItem('id_token', this.token);
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
Handling JWT Authentication Errors
php
// Implement error handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function login(Request $request)
{
$credentials = $request->only(['email', 'password']);
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle authentication errors
// resources/js/components/Login.vue
<template>
<form @submit.prevent="login">
<input type="email" v-model="email" placeholder="Email">
<input type="password" v-model="password" placeholder="Password">
<button type="submit">Login</button>
</form>
</template>
</script><script>
export default {
data() {
return {
email: '',
password: '',
};
},
methods: {
login() {
axios.post('/api/auth/login', {
email: this.email,
password: this.password,
})
.then((response) => {
const token = response.data.token;
localStorage.setItem('id_token', token);
this.$router.push('/home');
})
.catch((error) => {
if (error.response.status === 401) {
this.$toast.error('Invalid credentials');
} else {
this.$toast.error('Error logging in');
}
});
},
},
};
</script>
Protecting Routes with JWT Authentication
php
// Implement route protection in Laravel's routes/api.php
// routes/api.php
Route::group(['middleware' => 'jwt.auth'], function () {
Route::get('/api/auth/user', 'AuthController@user');
});
Using JWT Authentication in Vue.js
javascript
// Update Vue.js code to use JWT authentication
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
};
</script>
Handling JWT Token Expiration
php
// Implement token expiration handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function refresh()
{
$token = JWTAuth::refresh();
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle token expiration
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
token: '',
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
methods: {
refreshToken() {
axios.post('/api/auth/refresh')
.then((response) => {
this.token = response.data.token;
localStorage.setItem('id_token', this.token);
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
Handling JWT Authentication Errors
php
// Implement error handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function login(Request $request)
{
$credentials = $request->only(['email', 'password']);
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle authentication errors
// resources/js/components/Login.vue
<template>
<form @submit.prevent="login">
<input type="email" v-model="email" placeholder="Email">
<input type="password" v-model="password" placeholder="Password">
<button type="submit">Login</button>
</form>
</template>
</script><script>
export default {
data() {
return {
email: '',
password: '',
};
},
methods: {
login() {
axios.post('/api/auth/login', {
email: this.email,
password: this.password,
})
.then((response) => {
const token = response.data.token;
localStorage.setItem('id_token', token);
this.$router.push('/home');
})
.catch((error) => {
if (error.response.status === 401) {
this.$toast.error('Invalid credentials');
} else {
this.$toast.error('Error logging in');
}
});
},
},
};
</script>
Protecting Routes with JWT Authentication
php
// Implement route protection in Laravel's routes/api.php
// routes/api.php
Route::group(['middleware' => 'jwt.auth'], function () {
Route::get('/api/auth/user', 'AuthController@user');
});
Using JWT Authentication in Vue.js
javascript
// Update Vue.js code to use JWT authentication
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
};
</script>
Handling JWT Token Expiration
php
// Implement token expiration handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function refresh()
{
$token = JWTAuth::refresh();
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle token expiration
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
token: '',
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
methods: {
refreshToken() {
axios.post('/api/auth/refresh')
.then((response) => {
this.token = response.data.token;
localStorage.setItem('id_token', this.token);
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
Handling JWT Authentication Errors
php
// Implement error handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function login(Request $request)
{
$credentials = $request->only(['email', 'password']);
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle authentication errors
// resources/js/components/Login.vue
<template>
<form @submit.prevent="login">
<input type="email" v-model="email" placeholder="Email">
<input type="password" v-model="password" placeholder="Password">
<button type="submit">Login</button>
</form>
</template>
</script><script>
export default {
data() {
return {
email: '',
password: '',
};
},
methods: {
login() {
axios.post('/api/auth/login', {
email: this.email,
password: this.password,
})
.then((response) => {
const token = response.data.token;
localStorage.setItem('id_token', token);
this.$router.push('/home');
})
.catch((error) => {
if (error.response.status === 401) {
this.$toast.error('Invalid credentials');
} else {
this.$toast.error('Error logging in');
}
});
},
},
};
</script>
Protecting Routes with JWT Authentication
php
// Implement route protection in Laravel's routes/api.php
// routes/api.php
Route::group(['middleware' => 'jwt.auth'], function () {
Route::get('/api/auth/user', 'AuthController@user');
});
Using JWT Authentication in Vue.js
javascript
// Update Vue.js code to use JWT authentication
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
};
</script>
Handling JWT Token Expiration
php
// Implement token expiration handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function refresh()
{
$token = JWTAuth::refresh();
return response()->json(['token' => $token]);
}
// Update Vue.js code to handle token expiration
// resources/js/components/Home.vue
<template>
<h1>Welcome, {{ user.name }}!</h1>
</template>
</script><script>
export default {
data() {
return {
user: {},
token: '',
};
},
mounted() {
axios.get('/api/auth/user')
.then((response) => {
this.user = response.data;
})
.catch((error) => {
console.error(error);
});
},
methods: {
refreshToken() {
axios.post('/api/auth/refresh')
.then((response) => {
this.token = response.data.token;
localStorage.setItem('id_token', this.token);
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
Handling JWT Authentication Errors
```php// Implement error handling in Laravel's AuthController
// app/Http/Controllers/AuthController.php
public function login(Request $request)
{
$credentials = $request->only(['email', 'password']);
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json
Citations:
[1] https://www.youtube.com/watch?v=qJ-cMlCqlmo
[2] https://github.com/igaster/laravel-vue-jwt
[3] https://codeburst.io/api-authentication-in-laravel-vue-spa-using-jwt-auth-d8251b3632e0?gi=68aa9ea36da6
[4] https://github.com/codebriefly/VUEJS_LARAVEL_JWT_AUTH
[5] https://stackoverflow.com/questions/64643056/laravel-vue-js-jwt-implementation