Commit 80cc4497 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix(security): revoke the tokens the removed mobile API issued

AuthOtpController::verify() accepted a constant '0000' in the mode every instance
shipped with, and minted a Sanctum token with ability 'mobile:*' for whichever
active user matched the submitted phone number — staff included. The routes were
deleted in 883391c7, so the tokens reach nothing today, but a credential that was
issuable without authentication should not sit in the table waiting for the next
surface that accepts Sanctum.

Every client gets this, so it is a migration rather than an SSH per instance.
Two such rows exist on the one instance that used the API; the others have none,
and the table guard covers instances that never ran Sanctum's migration.

Deleting rows in up() is a deliberate exception to "destructive operations live
in down() only" — that rule protects schema and client data, and this is neither.
Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
parent 05a6a63e
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
/**
* Revoke every Sanctum token issued to the removed mobile API.
*
* AuthOtpController::verify() accepted a constant '0000' whenever auth_otp_mode
* was 'demo' — the value every instance shipped with — and then minted a token
* with ability 'mobile:*' for whichever active user matched the submitted phone
* number, staff included. The routes are gone, so these tokens no longer reach
* anything, but a credential that was issuable without authentication should not
* be left in the table: the deleted route is the only thing standing between it
* and the next surface that accepts Sanctum.
*
* Every client gets this, which is why it is a migration rather than something
* applied per instance over SSH.
*
* Deleting rows in up() is the deliberate exception to "destructive operations
* live in down() only". That rule protects schema and client data; this is
* neither. The only effect on a real person is that a mobile session they can no
* longer use in any case stops existing — and leaving it would keep a credential
* alive that should never have been issuable.
*
* Guarded on the table because personal_access_tokens ships with Sanctum's own
* migration, which an instance may not have run.
*/
return new class extends Migration
{
public function up(): void
{
if (! Schema::hasTable('personal_access_tokens')) {
return;
}
DB::table('personal_access_tokens')
->where('name', 'mobile')
->delete();
}
public function down(): void
{
// Irreversible by design. A revoked credential is not restorable, and
// recreating these would reissue exactly what this migration removed.
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment