LaravelSep 5, 20267 min read
Laravel JWT Authentication: A Practical Setup Guide
Step-by-step guide to implementing JWT authentication in Laravel for API-based applications, including token generation, refresh tokens, and middleware protection.
Why JWT for Laravel APIs
When building APIs that serve both web and mobile clients, session-based auth doesn't scale well. JWT (JSON Web Tokens) provide stateless authentication — the server doesn't need to store session data.
I use JWT authentication in healthcare applications where patient data security is critical and the API serves multiple client types.
Installing the Package
The most common approach is using tymon/jwt-auth:
composer require tymon/jwt-auth
php artisan jwt:secretUser Model Setup
Your User model needs to implement the JWTSubject interface:
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return [];
}
}Authentication Controller
class AuthController extends Controller
{
public function login(LoginRequest $request)
{
$credentials = $request->only('email', 'password');
if (!$token = auth()->attempt($credentials)) {
return response()->json([
'success' => false,
'message' => 'Invalid credentials',
], 401);
}
return response()->json([
'success' => true,
'token' => $token,
'token_type' => 'bearer',
'expires_in' => auth()->factory()->getTTL() * 60,
'user' => new UserResource(auth()->user()),
]);
}
public function me()
{
return new UserResource(auth()->user());
}
public function logout()
{
auth()->logout();
return response()->json(['message' => 'Logged out']);
}
}Protecting Routes
Apply the JWT middleware to routes that require authentication:
Route::middleware('auth:api')->group(function () {
Route::get('/me', [AuthController::class, 'me']);
Route::post('/logout', [AuthController::class, 'logout']);
});Token Refresh
Implement token refresh to avoid forcing users to log in repeatedly:
public function refresh()
{
return response()->json([
'token' => auth()->refresh(),
'token_type' => 'bearer',
'expires_in' => auth()->factory()->getTTL() * 60,
]);
}