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)