Kritim Yantra
Jun 04, 2025
Imagine your JWT token is a concert ticket π«:
Without refresh logic, users get logged out constantly. Letβs fix that!
In .env
, set token lifetimes:
JWT_TTL=60 # Access token expires in 60 minutes (for testing)
JWT_REFRESH_TTL=10080 # Refresh token expires in 7 days (10080 minutes)
Add to routes/api.php
:
Route::post('/refresh', [AuthController::class, 'refresh']);
Update AuthController.php
:
public function refresh() {
try {
$newToken = auth()->refresh();
return response()->json([
'token' => $newToken,
'refresh_token' => $newToken // Simplified for clarity
]);
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
return response()->json(['error' => 'Invalid token'], 401);
}
}
Update your Axios setup (resources/js/app.js
):
axios.interceptors.response.use(response => response, async error => {
const originalRequest = error.config;
// If token expired (401) and not already retrying
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
// Attempt token refresh
const refreshResponse = await axios.post('/api/refresh');
const newToken = refreshResponse.data.token;
// Update stored token
localStorage.setItem('jwt_token', newToken);
// Retry original request with new token
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return axios(originalRequest);
} catch (refreshError) {
// Refresh failed - force logout
localStorage.removeItem('jwt_token');
window.location.href = '/login';
}
}
return Promise.reject(error);
});
Create resources/js/components/Profile.vue
:
<template>
<div class="profile-card">
<h1>π Hello, {{ user.name }}!</h1>
<div class="details">
<p><strong>π§ Email:</strong> {{ user.email }}</p>
<p><strong>π User ID:</strong> {{ user.id }}</p>
<p><strong>π Member since:</strong> {{ formattedDate }}</p>
</div>
<button @click="logout" class="logout-btn">Log Out</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
user: {}
};
},
computed: {
formattedDate() {
return new Date(this.user.created_at).toLocaleDateString();
}
},
async mounted() {
try {
const response = await axios.get('/api/user');
this.user = response.data;
} catch (error) {
console.error("Profile load error:", error);
}
},
methods: {
logout() {
axios.post('/api/logout');
localStorage.removeItem('jwt_token');
this.$router.push('/login');
}
}
};
</script>
<style scoped>
.profile-card {
max-width: 500px;
margin: 2rem auto;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
background: white;
}
.details {
text-align: left;
padding: 1.5rem;
background: #f9fafb;
border-radius: 8px;
margin: 1.5rem 0;
}
.logout-btn {
background: #ef4444;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: background 0.3s;
}
.logout-btn:hover {
background: #dc2626;
}
</style>
Install Vue Router:
npm install vue-router@4
Create resources/js/router.js
:
import { createRouter, createWebHistory } from 'vue-router';
import Login from './components/Login.vue';
import Profile from './components/Profile.vue';
const routes = [
{ path: '/', redirect: '/profile' },
{ path: '/login', component: Login },
{ path: '/profile', component: Profile, meta: { requiresAuth: true } }
];
const router = createRouter({
history: createWebHistory(),
routes
});
// Auth protection
router.beforeEach((to, from, next) => {
const hasToken = localStorage.getItem('jwt_token');
if (to.meta.requiresAuth && !hasToken) {
next('/login');
} else {
next();
}
});
export default router;
Update app.js
:
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
createApp(App).use(router).mount('#app');
Ensure routes/api.php
has:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
/profile
β See your details! "Good authentication is like oxygen β users only notice it when itβs missing."
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 13, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google