Test your skills on our all Hosting services and get 15% off!

Use code at checkout:

Skills
08.10.2024

Building a Secure Laravel API with JWT Authentication

When building APIs with Laravel, ensuring secure authentication is crucial, especially when dealing with user data. JSON Web Tokens (JWT) offer a robust method for handling authentication in stateless applications, allowing secure transmission of user information between parties. This guide will walk you through the process of building a secure Laravel API using JWT authentication.

Prerequisites

  • Basic knowledge of PHP and Laravel.
  • Laravel installed on your machine (preferably Laravel 9 or newer).
  • Composer installed.
  • MySQL or another database set up for your application.

Step 1: Create a New Laravel Project

First, create a new Laravel project using Composer:

composer create-project laravel/laravel laravel-jwt-api

Navigate to your project directory:

cd laravel-jwt-api

Step 2: Install JWT Authentication Package

The most commonly used package for JWT authentication in Laravel is

tymon/jwt-auth
. Install it using Composer:

composer require tymon/jwt-auth

After the package installation, publish the JWT configuration:

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

This will create a

config/jwt.php
file in your project.

Step 3: Generate JWT Secret Key

Generate a secret key that JWT will use for signing tokens:

php artisan jwt:secret

This will add a

JWT_SECRET
entry to your
.env
file, which is used for encoding and decoding the tokens.

Step 4: Set Up Authentication

To set up JWT authentication, you need to configure the default guard for your API. Update the

config/auth.php
file as follows:

'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],

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

This tells Laravel to use the

jwt
driver for API requests and authenticate against the
users
provider.

Step 5: Create the User Model and Migration

If you haven’t created a

User
model yet, you can create it along with its migration file:

php artisan make:model User -m

Open the generated migration file in

database/migrations/
and add the necessary fields, such as
name
,
email
, and
password
:

public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
}

Run the migration to create the

users
table:

php artisan migrate

Step 6: Implement JWT Methods in the User Model

In the

User
model (
app/Models/User.php
), implement the
JWTSubject
interface and the required methods:

use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements JWTSubject
{
public function getJWTIdentifier()
{
return $this->getKey();
}

public function getJWTCustomClaims()
{
return [];
}
}

Step 7: Create Authentication Controllers

Create a controller for handling user authentication:

php artisan make:controller AuthController

In

AuthController.php
, add methods for registering a user, logging in, and logging out:

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Tymon\JWTAuth\Facades\JWTAuth;

class AuthController extends Controller
{
public function register(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);

$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);

$token = JWTAuth::fromUser($user);

return response()->json(['token' => $token], 201);
}

public function login(Request $request)
{
$credentials = $request->only('email', 'password');

if (!$token = Auth::attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}

return response()->json(['token' => $token]);
}

public function logout()
{
Auth::logout();

return response()->json(['message' => 'Successfully logged out']);
}

public function me()
{
return response()->json(Auth::user());
}
}

Step 8: Define API Routes

Add routes for authentication in

routes/api.php
:

use App\Http\Controllers\AuthController;

Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);
Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:api');
Route::get('me', [AuthController::class, 'me'])->middleware('auth:api');

These routes handle user registration, login, logout, and fetching the authenticated user.

Step 9: Protecting API Routes

To protect other API routes, you can use the

auth:api
middleware. For example, if you have a resource route for
posts
:

Route::middleware('auth:api')->group(function () {
Route::resource('posts', PostController::class);
});

This ensures that only authenticated users can access these routes.

Step 10: Testing the API

You can test your API using tools like Postman or cURL.

  • Register a user:
    POST /api/register
    Content-Type: application/json

    {
    "name": "John Doe",
    "email": "john@example.com",
    "password": "password",
    "password_confirmation": "password"
    }

  • Log in:
    POST /api/login
    Content-Type: application/json

    {
    "email": "john@example.com",
    "password": "password"
    }

    This will return a token that you can use to authenticate other requests.

  • Access protected route:

    To access a protected route like

    GET /api/me
    , include the token in the
    Authorization
    header:

    Authorization: Bearer <token>

Step 11: Refreshing JWT Tokens (Optional)

To refresh a token, you can add a method in

AuthController
:

public function refresh()
{
$token = Auth::refresh();
return response()->json(['token' => $token]);
}

Add the route for refreshing:

Route::post('refresh', [AuthController::class, 'refresh'])->middleware('auth:api');

Conclusion

By following this guide, you’ve built a secure Laravel API with JWT authentication, enabling user registration, login, and access to protected routes. JWT allows you to maintain a stateless authentication mechanism, which is especially useful for scaling APIs. With this setup, you can further customize your application’s authentication logic and integrate additional features, such as role-based access control and refresh tokens for long-lived sessions.

Test your skills on our all Hosting services and get 15% off!

Use code at checkout:

Skills