Authentification REST API avec Laravel et Sanctum

Authentification REST API avec Laravel et Sanctum

Configurer une REST API avec Laravel 11 en utilisant l’authentification Sanctum.

Nous développerons une application complète d’authentification REST API avec Sanctum en suivant un guide simple et étape par étape.

Qu’est-ce qu’une API ?

Une API (Application Programming Interface) est simplement un moyen de communication entre deux ou plusieurs programmes informatiques.

Les API sont également utilisées pour le développement d’applications web et mobiles. Ainsi, créer une REST API est essentiel pour tout développeur d’applications web ou mobiles.

Qu’est-ce que Laravel Sanctum ?

Laravel Sanctum est un package d’authentification pour les applications Laravel, offrant un système d’authentification léger et facile à utiliser pour les applications monopages (SPA), les applications mobiles et autres projets basés sur des APIs. Il fournit une authentification par jeton, soit en utilisant JSON Web Tokens (JWT), soit via des tokens API, permettant une authentification sécurisée sans la complexité des systèmes basés sur des sessions. Sanctum simplifie la configuration de l’authentification par token, permettant aux développeurs de se concentrer sur la construction de leurs applications plutôt que sur les détails complexes de l’authentification.

Nous utiliserons Laravel Sanctum pour développer des APIs simples  (single-page applications) généralement construites avec React JS, Angular ou Vue JS.

Installer une application Laravel 11.
Installer le package composer Sanctum pour l’authentification API.
Créer des APIs pour l’enregistrement et la connexion des utilisateurs.
Créer une REST API pour les produits nécessitant une authentification par token utilisateur.

Étapes pour configurer Sanctum REST API avec Laravel

Installer Laravel 11
Installer Sanctum API
Configurer Sanctum
Ajouter une table et un modèle pour les produits
Créer des routes API
Créer les fichiers de contrôleurs
Lancer l’application Laravel

Étape 1 : Installer Laravel 11

composer create-project laravel/laravel example-app

Étape 2 : Installer Sanctum API

Dans Laravel 11, par défaut, le fichier api.php pour les routes API n’est pas inclus.

Exécutez simplement la commande suivante pour installer Sanctum avec le fichier api.php :

php artisan install:api

Étape 3 : Configuration de Sanctum

Dans cette étape, nous configurons trois fichiers principaux : le modèle, le fournisseur de services et le fichier de configuration auth. Les modifications incluent :

Ajouter la classe HasApiTokens de Sanctum dans le modèle utilisateur.

Configurer l’authentification API dans le fichier auth.php.

// app/Models/User.php

<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
  
class User extends Authenticatable
{
    use HasFactory, Notifiable, HasApiTokens;
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
  
    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
  
    /**
     * Get the attributes that should be cast.
     *
     * @return array
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}

Étape 4 : Ajouter une table et un modèle pour les produits

Créez une migration pour la table des produits avec la commande suivante :

php artisan make:migration create_products_table
<?php
    
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
    
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('detail');
            $table->timestamps();
        });
    }
    
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

Après avoir créé la table, exécutez la commande suivante pour appliquer la migration :

php artisan migrate

Ensuite, créez un modèle pour gérer les produits.

// app/Models/Product.php


<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
  
class Product extends Model
{
    use HasFactory;
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'detail'
    ];
}

Étape 5 : Créer des routes API

Ajoutez des routes pour les APIs d’inscription, de connexion et de gestion des produits dans le fichier routes/api.php.

// routes/api.php

<?php
  
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
  
use App\Http\Controllers\API\RegisterController;
use App\Http\Controllers\API\ProductController;
   
Route::controller(RegisterController::class)->group(function(){
    Route::post('register', 'register');
    Route::post('login', 'login');
});
         
Route::middleware('auth:sanctum')->group( function () {
    Route::resource('products', ProductController::class);
});

Étape 6 : Créer les fichiers de contrôleurs

Créez trois contrôleurs :

BaseController pour les réponses communes (succès et erreurs).
RegisterController pour gérer l’inscription et la connexion des utilisateurs.
ProductController pour gérer les produits (création, mise à jour, suppression, liste et détail).

// app/Http/Controllers/API/BaseController.php

<?php
  
namespace App\Http\Controllers\API;
  
use Illuminate\Http\Request;
use App\Http\Controllers\Controller as Controller;
  
class BaseController extends Controller
{
    /**
     * success response method.
     *
     * @return \Illuminate\Http\Response
     */
    public function sendResponse($result, $message)
    {
        $response = [
            'success' => true,
            'data'    => $result,
            'message' => $message,
        ];
  
        return response()->json($response, 200);
    }
  
    /**
     * return error response.
     *
     * @return \Illuminate\Http\Response
     */
    public function sendError($error, $errorMessages = [], $code = 404)
    {
        $response = [
            'success' => false,
            'message' => $error,
        ];
  
        if(!empty($errorMessages)){
            $response['data'] = $errorMessages;
        }
  
        return response()->json($response, $code);
    }
}
// app/Http/Controllers/API/RegisterController.php

<?php
   
namespace App\Http\Controllers\API;
   
use Illuminate\Http\Request;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Validator;
use Illuminate\Http\JsonResponse;
   
class RegisterController extends BaseController
{
    /**
     * Register api
     *
     * @return \Illuminate\Http\Response
     */
    public function register(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'email' => 'required|email',
            'password' => 'required',
            'c_password' => 'required|same:password',
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $input = $request->all();
        $input['password'] = bcrypt($input['password']);
        $user = User::create($input);
        $success['token'] =  $user->createToken('MyApp')->plainTextToken;
        $success['name'] =  $user->name;
   
        return $this->sendResponse($success, 'User register successfully.');
    }
   
    /**
     * Login api
     *
     * @return \Illuminate\Http\Response
     */
    public function login(Request $request): JsonResponse
    {
        if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){ 
            $user = Auth::user(); 
            $success['token'] =  $user->createToken('MyApp')->plainTextToken; 
            $success['name'] =  $user->name;
   
            return $this->sendResponse($success, 'User login successfully.');
        } 
        else{ 
            return $this->sendError('Unauthorised.', ['error'=>'Unauthorised']);
        } 
    }
}
// app/Http/Controllers/API/ProductController.php


<?php
   
namespace App\Http\Controllers\API;
   
use Illuminate\Http\Request;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Models\Product;
use Validator;
use App\Http\Resources\ProductResource;
use Illuminate\Http\JsonResponse;
   
class ProductController extends BaseController
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(): JsonResponse
    {
        $products = Product::all();
    
        return $this->sendResponse(ProductResource::collection($products), 'Products retrieved successfully.');
    }




    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request): JsonResponse
    {
        $input = $request->all();
   
        $validator = Validator::make($input, [
            'name' => 'required',
            'detail' => 'required'
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $product = Product::create($input);
   
        return $this->sendResponse(new ProductResource($product), 'Product created successfully.');
    } 
   
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id): JsonResponse
    {
        $product = Product::find($id);
  
        if (is_null($product)) {
            return $this->sendError('Product not found.');
        }
   
        return $this->sendResponse(new ProductResource($product), 'Product retrieved successfully.');
    }
    
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Product $product): JsonResponse
    {
        $input = $request->all();
   
        $validator = Validator::make($input, [
            'name' => 'required',
            'detail' => 'required'
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $product->name = $input['name'];
        $product->detail = $input['detail'];
        $product->save();
   
        return $this->sendResponse(new ProductResource($product), 'Product updated successfully.');
    }
   
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Product $product): JsonResponse
    {
        $product->delete();
   
        return $this->sendResponse([], 'Product deleted successfully.');
    }
}

Étape 7 : Lancer l’application Laravel

php artisan make:resource ProductResource
// app/Http/Resources/ProductResource.php


<?php
  
namespace App\Http\Resources;
  
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
  
class ProductResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @return array
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'detail' => $this->detail,
            'created_at' => $this->created_at->format('d/m/Y'),
            'updated_at' => $this->updated_at->format('d/m/Y'),
        ];
    }
}

Une fois toutes les étapes complétées, lancez l’application Laravel avec la commande suivante :

php artisan serve
'headers' => [
    'Accept' => 'application/json',
    'Authorization' => 'Bearer '.$accessToken,
]

Testez les APIs en utilisant Postman ou un autre outil similaire. Assurez-vous d’inclure les en-têtes suivants pour les APIs nécessitant un token :

Routes disponibles :

API d’inscription : POST /api/register
API de connexion : POST /api/login
Liste des produits : GET /api/products
Créer un produit : POST /api/products
Détails d’un produit : GET /api/products/{id}
Mettre à jour un produit : PUT /api/products/{id}
Supprimer un produit : DELETE /api/products/{id}

 

 

par