Membuat token itu mudah; kebersihan jangka panjang justru ditentukan oleh pencabutan. Ponsel hilang, laptop dijual, atau integrasi pihak ketiga selesai dipakai — semuanya menuntut aksesnya dimatikan seketika. Karena verifikasi token selalu berakhir di baris personal_access_tokens, mencabut akses di Sanctum bermakna menghapus baris tersebut; tidak ada daftar hitam terpisah yang perlu dirawat. Chapter ini membahas empat granularitas pencabutan — satu token, perangkat saat ini, semua perangkat, dan kedaluwarsa otomatis — semuanya dibuktikan lewat test sungguhan yang mengakhiri request dengan 401.

Mencabut Satu Token #

Cara paling langsung: panggil delete() pada model token yang didapat dari relasi. Token lain milik user yang sama tetap hidup:

php
<?php

$newToken = $user->createToken('mobile-budi');

// ... suatu saat nanti:
$newToken->accessToken->delete();

Kunci ujinya sederhana — request yang sah sebelum pencabutan harus menjadi 401 setelah pencabutan:

php
<?php

// tests/Feature/Sanctum/RevokingTest.php (cuplikan)

public function test_token_yang_dihapus_langsung_ditolak(): void
{
    $user = User::factory()->create(['email' => '[email protected]']);

    $newToken = $user->createToken('mobile-budi');
    $plain = $newToken->plainTextToken;

    // request pertama: masih sah
    $this->withToken($plain)->getJson('/api/profil')->assertStatus(200);

    // cabut token
    $newToken->accessToken->delete();

    // request kedua: ditolak (guard di-reset untuk menyimulasikan
    // request yang datang dari proses PHP terpisah seperti di produksi)
    $this->app->make('auth')->forgetGuards();
    $this->withToken($plain)->getJson('/api/profil')->assertStatus(401);
}

Di chapter API Token Management , tombol hapus di halaman kelola token memanggil endpoint DELETE /api/tokens/{id} yang pada intinya melakukan hal yang sama lewat query builder.

Logout Semua Perangkat vs Perangkat Ini #

Relasi tokens memungkinkan pencabutan massal dalam satu query. Ini tombol “keluar dari semua perangkat” — misalnya saat Budi mencurigai akunnya dibobol:

php
<?php

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

Adapun untuk tombol “logout” di aplikasi mobile atau SPA berbasis token, kita hanya mencabut token yang sedang dipakai request tersebut. Objek token aktif bisa diambil lewat currentAccessToken():

php
<?php

// routes/api.php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::post('/logout-current', function (Request $request) {
    $request->user()->currentAccessToken()->delete();

    return response()->json(['message' => 'Token perangkat ini dicabut.']);
})->middleware('auth:sanctum');

Pola auth:sanctum + currentAccessToken()->delete() adalah padanan API dari Auth::logout() berbasis session yang kita kenal di chapter Login dan Logout . Kedua granularitas ini kita kunci dalam satu test:

Output yang Dihasilkan:

text
  PASS  Tests\Feature\Sanctum\RevokingTest
  ✓ token yang dihapus langsung ditolak
  ✓ logout semua perangkat
  ✓ logout perangkat ini saja

  Tests:    6 passed (10 assertions)

Test logout perangkat ini saja memeriksa kombinasi pentingnya: setelah token mobile-budi dicabut lewat endpoint, request berikutnya dari token tersebut ditolak 401, sementara token tablet-budi milik Budi yang sama masih diterima 200.

Kedaluwarsa Otomatis #

Pencabutan manual membutuhkan manusia yang ingat. Dua mekanisme otomatis melengkapinya. Pertama, per token: argumen ketiga createToken() menerima objek DateTimeInterface untuk kolom expires_at:

php
<?php

use Illuminate\Support\Carbon;

// token hanya berlaku 7 hari
$user->createToken('sementara', ['*'], Carbon::now()->addDays(7));

Kedua, global: mengisi expiration di config/sanctum.php (atau env SANCTUM_EXPIRATION) memberlakukan umur maksimum dalam menit untuk semua token — nilai ini mengesampingkan expires_at per token. Kita uji keduanya:

php
<?php

public function test_token_dengan_expires_at_masa_lalu_ditolak(): void
{
    $user = User::factory()->create(['email' => '[email protected]']);

    $plain = $user->createToken('lama-budi', ['*'], now()->subMinute())
        ->plainTextToken;

    $this->withToken($plain)->getJson('/api/profil')->assertStatus(401);
}

public function test_expiration_global_mencabut_token_lama(): void
{
    config(['sanctum.expiration' => 1]);

    $user = User::factory()->create(['email' => '[email protected]']);
    $plain = $user->createToken('lama-budi')->plainTextToken;

    // token dibuat 5 menit lalu — lebih tua dari batas 1 menit
    $user->tokens()->update(['created_at' => now()->subMinutes(5)]);

    $this->withToken($plain)->getJson('/api/profil')->assertStatus(401);
}

Output yang Dihasilkan:

text
  ✓ token dengan expires at masa lalu ditolak
  ✓ token masa depan masih sah
  ✓ expiration global mencabut token lama

Merapikan Token Kedaluwarsa #

Penolakan token kedaluwarsa hanya membuat barisnya tidak berlaku; barisnya masih menumpuk di tabel. Sanctum menyediakan perintah sanctum:prune-expired untuk membersihkannya, dengan opsi --hours menentukan tenggang setelah kedaluwarsa:

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

Output yang Dihasilkan:

text
  Pruning tokens with expired expires_at timestamps ............. 12.65ms DONE

   WARN  Expiration value not specified in configuration file.

   INFO  Tokens expired for more than [24 hours] pruned successfully.

Baris pertama menghapus baris dengan expires_at yang lampau; peringatan muncul karena sandbox belum mengatur SANCTUM_EXPIRATION. Bila konfigurasi global terisi, perintah ini menjalankan pembersihan tambahan untuk token berumur melebihi expiration. Efek bersihnya terukur di runner sandbox: dua token di database (satu expires_at 30 hari lampau, satu tanpa kedaluwarsa) menjadi satu baris tersisa setelah perintah berjalan — hanya baru-budi yang selamat. Agar tabel tetap ramping, jadwalkan perintah ini di routes/console.php:

php
<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('sanctum:prune-expired')->daily();

Penjadwalan ini berjalan lewat mekanisme scheduler yang sudah kita bahasi di section Task Scheduling , jadi tidak ada kode baru yang perlu dipelajari di sini. Keempat granularitas pencabutan kini lengkap, dan satu keterampilan terakhir menutup section ini: menguji semuanya secara efisien lewat actingAs dan Sanctum::actingAs di chapter Pengujian Sanctum . Dokumentasi resminya ada di dokumentasi Sanctum — token expiration .