JWT Token integration

  • STEP

    1. Enable API routes in Laravel 11:

    
                       php artisan install:api  
                            

    2.Update the API middleware to throw an exception instead of redirecting to login for authentication exceptions:

    bootstrap/app.php

    
                            use Illuminate\Foundation\Application;
                            use Illuminate\Foundation\Configuration\Exceptions;
                            use Illuminate\Foundation\Configuration\Middleware;
                            use Illuminate\Auth\AuthenticationException;
                            use Illuminate\Http\Request;
                            
                            return Application::configure(basePath: dirname(__DIR__))
                            ->withRouting(
                                    web: __DIR__.'/../routes/web.php',
                                    api: __DIR__.'/../routes/api.php',
                                    commands: __DIR__.'/../routes/console.php',
                                    health: '/up',
                            )
                            ->withMiddleware(function (Middleware $middleware) {
                                    //
                            })
                            ->withExceptions(function (Exceptions $exceptions) {
                                    $exceptions->render(function (AuthenticationException $e, Request $request) {
                                    if ($request->is('api/*')) {
                                            return response()->json([
                                            'message' => $e->getMessage(),
                                            ], 401);
                                    }
                                    });
                            })->create();
    
                            

    3.Run the following command to install the latest version of the JWT Auth package:

    
                            composer require tymon/jwt-auth  
                            

    4. Publish the package config file:

    
                            php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"        
                            

    5. Generate a secret key. This will add JWT config values on .env file:

    
                            php artisan jwt:secret 
                            

    6. Update auth guard config:

    config/auth.php

    
                            'guards' => [
                                    'web' => [
                                            'driver' => 'session',
                                            'provider' => 'users',
                                    ],
                                    'api' => [
                                            'driver' => 'jwt',
                                            'provider' => 'users',
                                    ],
                                    ],  
                                    

    7. In the User model, implement the Tymon\JWTAuth\Contracts\JWTSubject contract and add the getJWTIdentifier() and getJWTCustomClaims() methods:

    app/Models/User.php

    
                               namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Illuminate\Notifications\Notifiable;
    use Tymon\JWTAuth\Contracts\JWTSubject;
    
    class User extends Authenticatable implements JWTSubject
    {
        use HasFactory, Notifiable;
    
        protected $fillable = [
            'name',
            'email',
            'password',
        ];
    
        protected $hidden = [
            'password',
            'remember_token',
        ];
    
        protected function casts(): array
        {
            return [
                'email_verified_at' => 'datetime',
                'password' => 'hashed',
            ];
        }
    
        public function getJWTIdentifier()
        {
            return $this->getKey();
        }
    
        public function getJWTCustomClaims()
        {
            return [];
        }
    }  
    
    

    8. Create the AuthController

    
    php artisan make:controller AuthController  
    

    9. app/Http/Controllers/AuthController.php

    
    namespace App\Http\Controllers;
    
    use App\Http\Controllers\Controller;
    use App\Models\User;
    use Illuminate\Support\Facades\Validator;
    use Tymon\JWTAuth\Facades\JWTAuth;
    
    class AuthController extends Controller
    {
        public function register() {
            $validator = Validator::make(request()->all(), [
                'name' => 'required',
                'email' => 'required|email|unique:users',
                'password' => 'required|confirmed|min:8',
            ]);
    
            if($validator->fails()){
                return response()->json($validator->errors()->toJson(), 400);
            }
    
            $user = new User;
            $user->name = request()->name;
            $user->email = request()->email;
            $user->password = bcrypt(request()->password);
            $user->save();
    
            return response()->json($user, 201);
        }
    
        public function login()
        {
            $credentials = request(['email', 'password']);
    
            if (! $token = auth('api')->attempt($credentials)) {
                return response()->json(['error' => 'Unauthorized'], 401);
            }
    
            return $this->respondWithToken($token);
        }
    
        public function me()
        {
            return response()->json(auth('api')->user());
        }
    
        public function logout()
        {
            auth('api')->logout();
    
            return response()->json(['message' => 'Successfully logged out']);
        }
    
        public function refresh()
        {
            return $this->respondWithToken(JWTAuth::refresh());
        }
    
        protected function respondWithToken($token)
        {
            return response()->json([
                'access_token' => $token,
                'token_type' => 'bearer',
                'expires_in' => JWTAuth::factory()->getTTL() * 60
            ]);
        }
    } 
    
    

    10. In routes/api.php, register routes with auth:api middleware to ensure user authentication before processing requests.

    routes/api.php

    
    use Illuminate\Support\Facades\Route;
    use App\Http\Controllers\AuthController;
    
    Route::group([
        'middleware' => 'api',
        'prefix' => 'auth'
    ], function ($router) {
        Route::post('/register', [AuthController::class, 'register'])->name('register');
        Route::post('/login', [AuthController::class, 'login'])->name('login');
        Route::post('/logout', [AuthController::class, 'logout'])->middleware('auth:api')->name('logout');
        Route::post('/refresh', [AuthController::class, 'refresh'])->middleware('auth:api')->name('refresh');
        Route::post('/me', [AuthController::class, 'me'])->middleware('auth:api')->name('me');
    });