Installing via composer
composer require tymon/jwt-auth
Publishing the config
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
This command will create a file in config/jwt.php
There you can modify the default config like the expiration time of the token
Generating the secret key
php artisan jwt:secret
This command will add the key JWT_SECRET in your .env
Adding api guard
Inside the config/auth.php
Make the following changes
'defaults' => [ 'guard' => env('AUTH_GUARD', 'api'), 'passwords' => env('AUTH_PASSWORD_BROKER', 'users'), ],
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ],
Updating the User model
use Tymon\JWTAuth\Contracts\JWTSubject; class User extends Authenticatable implements JWTSubject
Adding the require methods
public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; }
Creating the UserController
php artisan make:controller UserController --api --model=User
Defining the store method
public function store(Request $request) { $data = $request->validate([ 'name' => 'required', 'email' => 'required|email|unique:users', 'password' => 'required|min:6', ]); $data['password'] = bcrypt($data['password']); $user = User::create($data); return response()->json($user, 201); }
Defining the me method
public function me() { return response()->json(auth()->user()); }
Creating the AuthController
php artisan make:controller AuthController
Defining the login method
public function login(Request $request) { $credentials = $request->validate([ 'email' => 'required|email', 'password' => 'required' ]); $token = auth()->attempt($credentials); if (!$token) { return response()->json([ 'status' => 401, 'message' => 'Credenciales incorrectas' ], 401); } return response()->json([ 'token' => $token, 'user' => auth()->user(), 'expire_in' => auth()->factory()->getTTL() * 60 ]); }
Defining the me method
public function me() { return response()->json(auth()->user()); }
Creating GuestMiddleware
php artisan make:middleware GuestMiddleware
This command will create the middleware in app/Http/Middlewares
import use Illuminate\Support\Facades\Auth;
public function handle(Request $request, Closure $next, ...$guards): Response { if (Auth::guard($guards)->check()) { abort(401, 'You are not allowed to access this resource'); } return $next($request); }
This middleware will prevent the users authenticated can access to some routes like login route
Creating AuthMiddleware
php artisan make:middleware AuthMiddleware
This command will create the middleware in app/Http/Middlewares
import use Illuminate\Support\Facades\Auth;
public function handle(Request $request, Closure $next, ...$guards): Response { if (!Auth::guard($guards)->check()) { abort(401, 'You are not allowed to access this resource'); } return $next($request); }
This middleware will prevent the users unauthenticated can access to some routes like me route
Defining the routes
use App\Http\Controllers\UserController; use App\Http\Controllers\AuthController; use App\Http\Middleware\GuestMiddleware; use App\Http\Middleware\AuthMiddleware; Route::middleware(GuestMiddleware::class)->group(function () { Route::post('login', [AuthController::class, 'login'])->name('login'); }); Route::middleware(AuthMiddleware::class)->group(function () { Route::get('me', [AuthController::class, 'me'])->name('me'); }); Route::apiResource('users', UserController::class);
Creating the AuthTest
php artisan make:test AuthTest
This command will create a file in tests/Feature
use Illuminate\Foundation\Testing\RefreshDatabase; use PHPUnit\Framework\Attributes\Test; class AuthTest extends TestCase { use RefreshDatabase; private User $user; protected function setUp(): void { parent::setUp(); $this->user = User::create([ 'name' => 'User', 'email' => 'user@gmail.com', 'password' => '1234', ]); } }
Tests methods
#[Test] public function should_create_a_user(): void { $data = [ 'name' => 'Test', 'email' => 'test@gmail.com', 'password' => '1234', ]; $response = $this->postJson(route('users.store'), $data); $response->assertStatus(201); $this->assertDatabaseHas('users', ['email' => 'test@gmail.com']); } #[Test] public function should_login(): void { $data = [ 'email' => $this->user->email, 'password' => '1234', ]; $response = $this->postJson(route('login'), $data); $response->assertStatus(200); $response->assertJsonStructure(['token']); } #[Test] public function should_not_login(): void { $data = [ 'email' => $this->user->email, 'password' => '12345', ]; $response = $this->postJson(route('login'), $data); $response->assertStatus(401); } #[Test] public function should_return_user_authenticated(): void { $response = $this->actingAs($this->user)->getJson(route('me')); $response->assertStatus(200); $response->assertJsonStructure(['id', 'name', 'email']); $response->assertJson(['id' => $this->user->id]); }
Remove comments in the file phpunit.xml
<env name="APP_ENV" value="testing"/> <env name="APP_MAINTENANCE_DRIVER" value="file"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_STORE" value="array"/> <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value=":memory:"/> <env name="MAIL_MAILER" value="array"/> <env name="PULSE_ENABLED" value="false"/> <env name="QUEUE_CONNECTION" value="sync"/> <env name="SESSION_DRIVER" value="array"/> <env name="TELESCOPE_ENABLED" value="false"/>
Running the tests
php artisan test --filter AuthTest
Top comments (0)