Laravel Sanctum: الدليل الشامل للمصادقة وحماية REST APIs في Laravel

تُعد المصادقة Authentication واحدة من أهم الأجزاء في أي تطبيق ويب أو تطبيق هاتف يتعامل مع حسابات المستخدمين. فعند بناء REST API نحتاج إلى وسيلة آمنة تمكّن الخادم من معرفة هوية المستخدم، وتحديد ما إذا كان يملك الصلاحية للوصول إلى مورد أو تنفيذ عملية معينة.

يوفر Laravel عدة حلول للمصادقة، ومن أبسطها وأكثرها ملاءمةً لتطبيقات الهاتف وواجهات API البسيطة Laravel Sanctum.

في هذا الدليل سنتعرف على Laravel Sanctum بصورة عملية، بدءًا من فهم آلية عمله، مرورًا بتثبيته وإصدار Access Tokens وحماية API Routes، وصولًا إلى Token Abilities وإلغاء الرموز وانتهاء صلاحيتها.

جدول المحتويات

  1. ما هو Laravel Sanctum؟
  2. كيف تعمل المصادقة في Sanctum؟
  3. SPA Authentication أم API Tokens؟
  4. تثبيت Laravel Sanctum
  5. تجهيز User Model
  6. إنشاء مستخدم تجريبي
  7. تسجيل مستخدم جديد
  8. تسجيل الدخول
  9. استخدام Device Name
  10. إرسال Access Token
  11. حماية API Routes
  12. الحصول على المستخدم الحالي
  13. تسجيل الخروج من الجهاز الحالي
  14. تسجيل الخروج من جميع الأجهزة
  15. Token Abilities والصلاحيات
  16. حماية Routes باستخدام Abilities
  17. انتهاء صلاحية Access Tokens
  18. تحديد Expiration لكل Token
  19. حذف Tokens المنتهية
  20. اختبار API باستخدام Postman
  21. HTTP Status Codes
  22. مثال كامل لـ routes/api.php
  23. مثال AuthController متكامل
  24. اعتبارات أمنية مهمة
  25. Sanctum مع SPA
  26. هل Sanctum بديل عن OAuth؟
  27. الخلاصة

ما هو Laravel Sanctum؟

Laravel Sanctum هو نظام مصادقة خفيف توفره Laravel للتعامل مع مجموعة من سيناريوهات المصادقة، ومن أبرزها:

  • تطبيقات الهاتف Mobile Applications.
  • واجهات REST APIs.
  • تطبيقات Single Page Applications أو SPA.
  • إصدار Personal Access Tokens.
  • إنشاء أكثر من Token للمستخدم نفسه.
  • تحديد صلاحيات مختلفة لكل Token.

الفكرة الأساسية في Token Authentication بسيطة. بعد نجاح تسجيل الدخول يستطيع الخادم إنشاء Access Token للمستخدم، ثم يقوم التطبيق بإرسال هذا Token مع الطلبات التي تحتاج إلى مصادقة.

على سبيل المثال:

Authorization: Bearer YOUR_ACCESS_TOKEN

يستقبل Laravel الطلب ويتحقق من Token، ومن خلاله يستطيع تحديد المستخدم المرتبط بالطلب.

لكن هناك نقطة مهمة يجب فهمها قبل البدء: Sanctum لا يستخدم الطريقة نفسها في جميع سيناريوهات المصادقة.

كيف تعمل المصادقة في Laravel Sanctum؟

يوفر Sanctum بشكل أساسي طريقتين للمصادقة:

API Token Authentication

تُستخدم هذه الطريقة عادةً مع تطبيقات الهاتف أو التطبيقات الخارجية التي تتصل بـ Laravel API.

Flutter / Android / iOS
          |
          | Bearer Token
          v
      Laravel API
          |
          v
       Database

بعد تسجيل الدخول يحصل التطبيق على Token ويرسله في الطلبات التالية.

SPA Authentication

إذا كان لديك تطبيق Frontend خاص بك مثل React أو Vue ويتصل بـ Laravel ضمن بنية First-Party، فإن Sanctum يستطيع استخدام نظام Session وCookies الخاص بـ Laravel مع حماية CSRF بدل الاعتماد على Personal Access Tokens.

وهذا الفرق أساسي لفهم الطريقة الصحيحة لاستخدام Sanctum.

متى نستخدم SPA Authentication ومتى نستخدم API Tokens؟

إذا كان لدينا تطبيق هاتف:

Flutter / Android / iOS
          |
          v
      Laravel API

فيمكن استخدام:

Authorization: Bearer TOKEN

أما إذا كان لدينا تطبيق Frontend تابع للنظام نفسه مثل React أو Vue ويعمل مع Laravel كتطبيق First-Party، فمن الأفضل دراسة استخدام SPA Authentication الخاص بـ Sanctum بدل تخزين Personal Access Token في JavaScript.

في هذا المقال سنركز بشكل أساسي على API Token Authentication لأنها من أكثر الطرق استخدامًا عند بناء REST API أو Backend لتطبيق هاتف.

تثبيت Laravel Sanctum

في إصدارات Laravel الحديثة يمكن تجهيز API Authentication باستخدام الأمر:

php artisan install:api

بعد ذلك يتم تنفيذ migrations عند الحاجة:

php artisan migrate

يستخدم Sanctum جدولًا باسم:

personal_access_tokens

ويُستخدم هذا الجدول لتخزين المعلومات المرتبطة بالـAccess Tokens.

من المهم معرفة أن Sanctum لا يخزن القيمة الأصلية الكاملة للـToken بشكل مكشوف داخل قاعدة البيانات، وإنما يخزن Hash للرمز.

تجهيز User Model

لكي يستطيع المستخدم إنشاء Access Tokens يجب أن يستخدم User Model الـTrait التالية:

use Laravel\Sanctum\HasApiTokens;

ليصبح نموذج المستخدم مثلًا:

<?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 HasApiTokens, HasFactory, Notifiable;
}

توفر HasApiTokens مجموعة من الوظائف المهمة للتعامل مع Tokens.

على سبيل المثال:

$user->createToken(...);

كما يمكن الوصول إلى Tokens الخاصة بالمستخدم:

$user->tokens;

إنشاء مستخدم تجريبي

يمكن استخدام Seeder لإنشاء مستخدم للاختبار:

php artisan make:seeder UsersTableSeeder

ثم:

<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;

class UsersTableSeeder extends Seeder
{
    public function run(): void
    {
        User::create([
            'name' => 'John Doe',
            'email' => 'john@example.com',
            'password' => Hash::make('password123'),
        ]);
    }
}

بعد ذلك يمكن تشغيل Seeder:

php artisan db:seed --class=UsersTableSeeder

لاحظ استخدام:

Hash::make()

وذلك لتخزين كلمة المرور بصورة آمنة بدل تخزينها كنص صريح Plain Text.

تسجيل مستخدم جديد

لننشئ Auth Controller:

php artisan make:controller Api/AuthController

ثم نضيف Route داخل:

routes/api.php

بالشكل التالي:

use App\Http\Controllers\Api\AuthController;
use Illuminate\Support\Facades\Route;

Route::post('/register', [AuthController::class, 'register']);

داخل Controller يمكن إنشاء دالة التسجيل:

public function register(Request $request)
{
    $validated = $request->validate([
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'email', 'max:255', 'unique:users,email'],
        'password' => [
            'required',
            'confirmed',
            Password::min(8),
        ],
        'device_name' => ['required', 'string', 'max:255'],
    ]);

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

    $token = $user->createToken(
        $validated['device_name']
    )->plainTextToken;

    return response()->json([
        'message' => 'User registered successfully.',
        'user' => $user,
        'token' => $token,
    ], 201);
}

وبما أننا استخدمنا قاعدة التحقق:

'confirmed'

فيجب إرسال حقل password_confirmation أيضًا:

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

تسجيل الدخول باستخدام Laravel Sanctum

نضيف Route لتسجيل الدخول:

Route::post('/login', [AuthController::class, 'login']);

ثم نضيف الدالة التالية داخل Controller:

public function login(Request $request)
{
    $validated = $request->validate([
        'email' => ['required', 'email'],
        'password' => ['required', 'string'],
        'device_name' => ['required', 'string'],
    ]);

    $user = User::where('email', $validated['email'])->first();

    if (! $user || ! Hash::check($validated['password'], $user->password)) {
        throw ValidationException::withMessages([
            'email' => ['The provided credentials are incorrect.'],
        ]);
    }

    $token = $user->createToken(
        $validated['device_name']
    )->plainTextToken;

    return response()->json([
        'message' => 'Login successful.',
        'user' => $user,
        'token' => $token,
    ]);
}

في البداية نحصل على المستخدم من خلال البريد الإلكتروني:

$user = User::where('email', $validated['email'])->first();

ثم نتحقق من كلمة المرور:

Hash::check($validated['password'], $user->password)

إذا كانت بيانات الدخول صحيحة ننشئ Token:

$user->createToken($validated['device_name'])

ثم نحصل على القيمة التي سيستخدمها Client:

->plainTextToken

لماذا نستخدم Device Name؟

يمكن أن يمتلك المستخدم أكثر من جهاز، مثل:

  • iPhone
  • Android
  • iPad
  • Desktop Application

وبالتالي يمكن إصدار Token مستقل لكل جهاز:

$user->createToken('iPhone');

أو:

$user->createToken('Android');

وهذا يجعل إدارة الجلسات والأجهزة أكثر مرونة، حيث يمكن إلغاء Token لجهاز معين دون الحاجة إلى تسجيل خروج المستخدم من جميع أجهزته.

إرسال Access Token

بعد تسجيل الدخول قد يعيد API استجابة مشابهة:

{
    "message": "Login successful.",
    "user": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com"
    },
    "token": "1|xxxxxxxxxxxxxxxxxxxxxxxx"
}

القيمة الموجودة في token هي التي يحتاج إليها التطبيق لإرسال الطلبات المحمية.

يتم إرسالها داخل HTTP Header:

Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxx

ويُفضّل كذلك إرسال:

Accept: application/json

حماية API Routes

لنفترض أن لدينا Route:

Route::get('/profile', [ProfileController::class, 'show']);

إذا أردنا منع المستخدم غير المسجل من الوصول إليه نستخدم:

Route::get('/profile', [ProfileController::class, 'show'])
    ->middleware('auth:sanctum');

كما يمكن حماية مجموعة Routes كاملة:

Route::middleware('auth:sanctum')->group(function () {

    Route::get('/profile', [ProfileController::class, 'show']);

    Route::get('/orders', [OrderController::class, 'index']);

    Route::post('/logout', [AuthController::class, 'logout']);

});

الآن لا يمكن الوصول إلى هذه المسارات إلا من خلال Request تمت مصادقته بواسطة Sanctum.

الحصول على المستخدم الحالي

بعد نجاح المصادقة يمكن الحصول على المستخدم من Request:

public function profile(Request $request)
{
    return response()->json([
        'user' => $request->user(),
    ]);
}

يستطيع Laravel تحديد المستخدم لأن Sanctum قام بالتحقق من بيانات المصادقة المرتبطة بالطلب.

تسجيل الخروج من الجهاز الحالي

إذا أردنا تسجيل خروج المستخدم من الجهاز الحالي فقط، يمكن حذف Token المستخدم في الطلب الحالي:

public function logout(Request $request)
{
    $request->user()
        ->currentAccessToken()
        ->delete();

    return response()->json([
        'message' => 'Logged out successfully.',
    ]);
}

بمجرد حذف Token لن يستطيع Client استخدامه مرة أخرى للوصول إلى Routes المحمية.

تسجيل الخروج من جميع الأجهزة

هناك فرق بين تسجيل الخروج من الجهاز الحالي وتسجيل الخروج من جميع الأجهزة.

لحذف جميع Tokens الخاصة بالمستخدم:

$request->user()->tokens()->delete();

مثال:

public function logoutAll(Request $request)
{
    $request->user()->tokens()->delete();

    return response()->json([
        'message' => 'Logged out from all devices.',
    ]);
}

وبذلك تصبح جميع Access Tokens السابقة الخاصة بالمستخدم غير صالحة.

أما لحذف Token محدد:

$user->tokens()
    ->where('id', $tokenId)
    ->delete();

هذه الإمكانية مفيدة عند إنشاء قسم لإدارة الأجهزة والجلسات النشطة داخل التطبيق.

Token Abilities والصلاحيات

لا يقتصر Sanctum على إنشاء Tokens فقط، بل يمكن إعطاء Token صلاحيات محددة تسمى Abilities.

لنفترض أننا نريد إنشاء Token يستطيع قراءة الطلبات فقط:

$token = $user->createToken(
    'mobile-app',
    ['orders:read']
)->plainTextToken;

ويمكن إنشاء Token يمتلك عدة صلاحيات:

$token = $user->createToken(
    'admin-app',
    [
        'orders:read',
        'orders:create',
        'orders:update'
    ]
)->plainTextToken;

ثم يمكن التحقق من صلاحية معينة:

if ($request->user()->tokenCan('orders:update')) {
    // Token has permission.
}

كما يمكن استخدام:

tokenCant()

للتحقق من عدم امتلاك Token لصلاحية معينة:

if ($request->user()->tokenCant('orders:update')) {
    abort(403);
}

حماية Routes باستخدام Token Abilities

يوفر Sanctum Middleware للتحقق من Abilities المطلوبة للوصول إلى Route معين.

يمكن تعريف Middleware Aliases داخل:

bootstrap/app.php

باستخدام:

use Laravel\Sanctum\Http\Middleware\CheckAbilities;
use Laravel\Sanctum\Http\Middleware\CheckForAnyAbility;

ثم:

->withMiddleware(function (Middleware $middleware): void {

    $middleware->alias([
        'abilities' => CheckAbilities::class,
        'ability' => CheckForAnyAbility::class,
    ]);

})

بعد ذلك يمكن حماية Route:

Route::get('/orders', [OrderController::class, 'index'])
    ->middleware([
        'auth:sanctum',
        'abilities:orders:read'
    ]);

وبذلك لا يكفي أن يكون Token صالحًا، بل يجب أيضًا أن يمتلك الصلاحية المطلوبة.

انتهاء صلاحية Access Tokens

من النقاط المهمة في Sanctum أن Tokens لا تنتهي افتراضيًا لمجرد مرور مدة زمنية ما لم يتم إعداد Expiration أو إلغاء Token.

يمكن تحديد مدة عامة من:

config/sanctum.php

على سبيل المثال:

'expiration' => 10080,

القيمة تكون بالدقائق، وبالتالي:

  • 60 = ساعة.
  • 1440 = يوم.
  • 10080 = 7 أيام.

اختيار المدة المناسبة يعتمد على طبيعة التطبيق ومتطلباته الأمنية.

تحديد Expiration لكل Token

يمكن كذلك تحديد تاريخ انتهاء صلاحية Token عند إنشائه:

$token = $user->createToken(
    'mobile-app',
    ['*'],
    now()->addWeek()
)->plainTextToken;

وبذلك يكون لهذا Token تاريخ انتهاء مستقل.

حذف Tokens المنتهية

مع مرور الوقت قد يحتوي جدول personal_access_tokens على Tokens منتهية الصلاحية.

يوفر Sanctum أمرًا لتنظيفها:

php artisan sanctum:prune-expired --hours=24

ويمكن جدولة هذا الأمر ليعمل بصورة دورية بدل تنفيذه يدويًا.

اختبار Laravel Sanctum باستخدام Postman

يمكن تجربة تسجيل الدخول عبر:

POST /api/login

مع Body:

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

إذا كانت البيانات صحيحة سيعيد API الـToken.

بعد ذلك نختبر:

GET /api/profile

ونضيف:

Authorization: Bearer YOUR_TOKEN

في Postman يمكن أيضًا اختيار Bearer Token من قسم Authorization ووضع Token في الحقل المخصص له.

HTTP Status Codes

عند بناء REST API احترافي يجب الاهتمام باستخدام HTTP Status Codes المناسبة.

200 OK

تُستخدم عادةً عندما تتم العملية بنجاح.

201 Created

تُستخدم عند إنشاء Resource جديد بنجاح، مثل إنشاء مستخدم جديد.

401 Unauthorized

تعني أن الطلب يحتاج إلى Authentication صحيحة.

403 Forbidden

تعني أن هوية المستخدم معروفة، لكنه لا يمتلك الصلاحية المطلوبة لتنفيذ العملية.

422 Unprocessable Content

تُستخدم عادةً عندما توجد مشكلة في البيانات المدخلة أو Validation.

استخدام Status Codes بشكل صحيح يجعل API أسهل في التكامل والصيانة ومعالجة الأخطاء في تطبيقات الهاتف والـFrontend.

مثال كامل لـ routes/api.php

يمكن أن يصبح ملف Routes لدينا بالشكل التالي:

<?php

use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\OrderController;
use Illuminate\Support\Facades\Route;

Route::post('/register', [AuthController::class, 'register']);

Route::post('/login', [AuthController::class, 'login']);

Route::middleware('auth:sanctum')->group(function () {

    Route::get('/profile', [AuthController::class, 'profile']);

    Route::get('/orders', [OrderController::class, 'index']);

    Route::post('/logout', [AuthController::class, 'logout']);

    Route::post('/logout-all', [AuthController::class, 'logoutAll']);

});

وبذلك لدينا Public Routes:

/api/register
/api/login

وProtected Routes:

/api/profile
/api/orders
/api/logout
/api/logout-all

مثال AuthController متكامل

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\ValidationException;

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

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

        $token = $user->createToken(
            $validated['device_name']
        )->plainTextToken;

        return response()->json([
            'message' => 'User registered successfully.',
            'user' => $user,
            'token' => $token,
        ], 201);
    }


    public function login(Request $request)
    {
        $validated = $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
            'device_name' => ['required', 'string'],
        ]);

        $user = User::where(
            'email',
            $validated['email']
        )->first();

        if (
            ! $user ||
            ! Hash::check(
                $validated['password'],
                $user->password
            )
        ) {
            throw ValidationException::withMessages([
                'email' => [
                    'The provided credentials are incorrect.'
                ],
            ]);
        }

        $token = $user->createToken(
            $validated['device_name']
        )->plainTextToken;

        return response()->json([
            'message' => 'Login successful.',
            'user' => $user,
            'token' => $token,
        ]);
    }


    public function profile(Request $request)
    {
        return response()->json([
            'user' => $request->user(),
        ]);
    }


    public function logout(Request $request)
    {
        $request->user()
            ->currentAccessToken()
            ->delete();

        return response()->json([
            'message' => 'Logged out successfully.',
        ]);
    }


    public function logoutAll(Request $request)
    {
        $request->user()
            ->tokens()
            ->delete();

        return response()->json([
            'message' => 'Logged out from all devices.',
        ]);
    }
}

اعتبارات أمنية مهمة عند استخدام Laravel Sanctum

استخدام Sanctum لا يعني أن API أصبح آمنًا تلقائيًا. المصادقة ليست سوى طبقة واحدة من منظومة حماية التطبيق.

استخدم HTTPS دائمًا

يجب عدم إرسال Access Tokens عبر اتصال HTTP غير مشفر في بيئة Production.

https://

لا تسجل Access Tokens داخل Logs

تجنب تسجيل Token داخل ملفات Log، مثل:

Log::info($token);

كما يجب عدم وضع Access Tokens داخل رسائل الأخطاء أو خدمات Analytics.

لا ترسل Token داخل URL

تجنب:

/api/profile?token=xxxx

واستخدم HTTP Authorization Header:

Authorization: Bearer TOKEN

امنح Token أقل قدر ممكن من الصلاحيات

إذا كان التطبيق يحتاج فقط إلى:

orders:read

فلا توجد حاجة لمنحه جميع الصلاحيات.

يعرف هذا المبدأ باسم Principle of Least Privilege.

ألغِ Tokens عند الحاجة

عند الاشتباه في جهاز أو Session يجب أن يوفر النظام وسيلة لإلغاء Token الخاص بذلك الجهاز.

حدد سياسة مناسبة لانتهاء Tokens

ترك Token صالحًا إلى أجل غير محدد ليس الخيار الأنسب لجميع التطبيقات، خصوصًا الأنظمة التي تتعامل مع معلومات حساسة.

استخدم Rate Limiting

يجب الاهتمام بحماية Endpoints الحساسة، مثل:

  • /login
  • /register
  • /password-reset

وذلك لتقليل محاولات الإساءة أو إرسال عدد كبير من الطلبات.

لا تعتمد على Token Abilities وحدها

Abilities مفيدة في تحديد ما يستطيع Token فعله، لكنها لا تلغي الحاجة إلى Authorization داخل التطبيق.

في الأنظمة الكبيرة يمكن استخدام:

  • Laravel Policies
  • Laravel Gates
  • Authorization Rules

على سبيل المثال، امتلاك المستخدم لصلاحية:

orders:update

لا يعني بالضرورة أنه يجب أن يستطيع تعديل أي Order داخل النظام. فقد يكون مسموحًا له فقط بتعديل الطلبات التابعة لحسابه.

استخدام Laravel Sanctum مع SPA

إذا كنت تستخدم Sanctum مع First-Party SPA فإن طريقة المصادقة تختلف عن Mobile API.

في هذا السيناريو يستطيع Sanctum استخدام Session Cookies بدل Personal Access Tokens.

في Laravel الحديث يمكن تفعيل Stateful API Middleware من:

bootstrap/app.php

باستخدام:

->withMiddleware(function (Middleware $middleware): void {
    $middleware->statefulApi();
})

ويبدأ SPA عادةً بطلب:

/sanctum/csrf-cookie

وذلك لتهيئة حماية CSRF قبل عملية تسجيل الدخول.

لذلك لا ينبغي أخذ مثال Bearer Token الخاص بتطبيقات الهاتف وتطبيقه تلقائيًا على First-Party SPA دون فهم الفرق بين الطريقتين.

هل Laravel Sanctum بديل عن OAuth؟

ليس في جميع الحالات.

Sanctum مناسب جدًا لسيناريوهات مثل:

  • Laravel مع Flutter.
  • Laravel Backend لتطبيق Android أو iOS.
  • REST API بسيط.
  • First-Party SPA.
  • Personal Access Tokens.

أما إذا كان المشروع يحتاج إلى تطبيق كامل لبروتوكول OAuth2 ومتطلباته، فقد يكون من المناسب استخدام حل مثل Laravel Passport أو مزود OAuth/OIDC متخصص وفق بنية ومتطلبات المشروع.

لذلك يجب اختيار Sanctum بناءً على طبيعة النظام وليس فقط بسبب سهولة تركيبه.

الخلاصة

يوفر Laravel Sanctum طريقة بسيطة وقوية لبناء طبقة Authentication لتطبيقات Laravel دون الدخول في تعقيدات OAuth عندما لا يحتاج المشروع إليها.

في تطبيقات Mobile وواجهات API يمكن إصدار Access Token للمستخدم وإرساله في الطلبات باستخدام:

Authorization: Bearer TOKEN

ثم حماية Routes بواسطة:

auth:sanctum

كما يمكن إنشاء أكثر من Token للمستخدم، وتحديد Abilities لكل Token، وإلغاء Token الحالي أو جميع Tokens، وتحديد مدة انتهاء للرموز.

أما في تطبيقات SPA التابعة للنظام نفسه، فيوفر Sanctum آلية مختلفة تعتمد على Laravel Sessions وCookies وCSRF بدل الاعتماد على Personal Access Tokens.

والأهم عند بناء نظام حقيقي ألا نتعامل مع Sanctum باعتباره الحماية الكاملة للتطبيق؛ بل باعتباره طبقة Authentication يجب أن تعمل إلى جانب HTTPS وValidation وAuthorization وRate Limiting وسياسات مناسبة لإدارة Tokens والصلاحيات.

بهذا نكون قد وضعنا أساسًا واضحًا وقابلًا للتوسع لبناء نظام مصادقة وحماية REST APIs باستخدام Laravel Sanctum.