Aprende Java Aprende Php Aprende C++ Aprende HTML 5 Aprende JavaScript Aprende JSON Aprende MySQL Aprende SQLServer Aprende Visual Basic 6 Aprende PostgreSQL Aprende SQLite Aprende Redis Aprende Kotlin Aprende XML Aprende Linux VSC Aprende Wordpress Aprende Laravel Aprende VueJS Aprende JQuery Aprende Bootstrap Aprende Netbeans Aprende Android
Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube Sigueme en TikTok Sigueme en Whatsapp
Home / PHP / Autenticación basada en API Keys en Laravel 12

Autenticación basada en API Keys en Laravel 12

Por jc mouse jueves, junio 12, 2025

La autenticación basada en API keys es un método para proteger el acceso a una API. Se utiliza una clave alfanumérica única (la API key) para identificar y verificar la identidad del usuario o aplicación que realiza la solicitud a la API.

Este método de autenticación es bastante facil de implementar sin el uso de plugins externos y de esta forma logramos un control total sobre la autenticación. Este metodo tambien es relativamente seguro ya que nos permite controlar el acceso de los clientes y revocar su permiso si se sospecha de algo fraudulento, al mismo tiempo este metodo como cualquier otro entra en juego el error humano, si la API Key es expuesta un atacante podra utilizarla para acceder a la API sin autorización.

Este método como ya mencionamos, es bastante fácil de implementar en proyectos pequeños pero no es tan escalable en proyectos mucho mas grandes, para ello se recomienda el uso de tokens.

A continuación implementaremos un pequeño proyecto en Laravel 12 para la creación y uso de API Keys.

Paso 1. Crear un proyecto en Laravel y llamaño por ejemplo «testAPI». Configura una base de datos en el archivo .ENV, aún no realices la migracion.

Paso 2. Crear una migración «api_keys», esta tabla nos servirá para almacenar los API Keys que se vayan generando y usando.

php artisan make:migration create_api_keys_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('api_keys', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->nullable()->constrained()->onDelete('cascade'); 
            $table->string('key', 64)->unique(); 
            $table->string('name')->nullable(); 
            $table->boolean('is_active')->default(true);
            $table->timestamp('last_used_at')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('api_keys');
    }
};

y ejecutamos la migración:

php artisan migrate

Paso 3. El modelo ApiKey

Creamos un modelo llamado ApiKey, en el mismo declaramos la función «generateKey» el cual creará una API Key de 60 caracteres alfanumericos, el mismo controlará que la llave sea unica.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Str;
class ApiKey extends Model
{
    use HasFactory;

     protected $fillable = [
        'user_id',
        'key',
        'name',
        'is_active',
        'last_used_at',
    ];

    /**
     * Genera una nueva API Key.
     *
     * @return string
     */
    public static function generateKey(): string
    {
        do {
            $key = Str::random(60); // Cadena aleatoria de 60 caracteres
        } while (self::where('key', $key)->exists()); // Asegura que la clave sea única
        return $key;
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

}

Paso 4. El Controlador

En el controlador declaramos las funciones «createApikey» para el registro de una nueva API Key generada por el cliente. Tambien se incluye una funcion «listApiKeys» para el listado de las llaves generadas. En una app real se debe incluir el CRUD completo para las llaves incluido una para deshabilitar la API Key.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; 
use App\Models\ApiKey;
class ManageApiKeysController extends Controller
{
    public function createApiKey($name)
    {         
        $apiKey = ApiKey::create([
            'user_id' => Auth::id(), // Solo si la clave pertenece al usuario autenticado, sino sera NULL
            'key' => ApiKey::generateKey(),
            'name' => $name,
            'is_active' => true,
        ]);

        return response()->json([
            'message' => 'API Key generada exitosamente.',
            'key' => $apiKey->key, 
        ]);
    }    

    public function listApiKeys(Request $request)
    {
        $apiKeys = ApiKey::where('user_id', auth()->id())->get(); 
        return response()->json($apiKeys->map(function($key) {
            return [
                'id' => $key->id,
                'name' => $key->name,
                'is_active' => $key->is_active,
                'last_used_at' => $key->last_used_at,
                'created_at' => $key->created_at,
                // NO incluyas la clave completa aquí por seguridad
                'key_prefix' => substr($key->key, 0, 8) . '...',
            ];
        }));
    }

}

Paso 5. Middleware

php artisan make:middleware AuthenticateApiKey
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use App\Models\ApiKey;
class AuthenticateApiKey
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
         $apiKey = $request->header('JC-API-Key');

        if (empty($apiKey)) {
            return response()->json(['message' => 'API Key no proporcionada. Operación no autorizada.'], 401);
        }

        $validApiKey = ApiKey::where('key', $apiKey)
                             ->where('is_active', true)
                             ->first();

        if (! $validApiKey) {
            return response()->json(['message' => 'API Key inválida o inactiva.'], 401);
        }

        // Actualiza la última vez que se usó la clave
        $validApiKey->update(['last_used_at' => now()]);

        return $next($request);
    }
}

Paso 6. Registrar el Middleware

Nos dirigimos a «Bootstrap/app.php» y añadimos en la sección de «withMiddleware«

->withMiddleware(function (Middleware $middleware): void {        
        $middleware->alias([
            'api.key' => AuthenticateApiKey::class,
        ]);
    })

Paso 7. Las rutas

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ManageApiKeysController;

Route::get('/generate/{name}', [ManageApiKeysController::class, 'createApiKey']);
Route::get('/api-keys', [ManageApiKeysController::class, 'listApiKeys']);

//para verificar el funcionamiento del API Key
Route::middleware('api.key')->group(function () {
    Route::get('/data', function () {
        return response()->json([
            'message' => 'Datos obtenidos con exito.'            
        ]);
    });
});

Y eso es todo, ahora vamos primero a generar un API Key de la forma:

https://tu-dominio.com/generate/appDePedro

Donde «appDePedro «es el nombre identificador de quien tendra el acceso, obviamente esto se deberia hacer mediante POST.

Al ejecutar obtendremos algo parecido a esto:

{
  "message": "API Key generada exitosamente.",
  "key": "TEzXdbJgAcay7hW1xpYid3y8tFsrm0706A0iOuNsxJfWHCoYg6MkTmt6KMDJ"
}

Probando la API Keys desde un cliente

Utilizaremos Postman para mas comodidad, si tu utilizas otro cliente no hay problema.

En la URL colocaremos:

GET http://tu-dominio.com/data

Y en la sección de encabezados colocamos el API Key

Si no se proporciona la Api Key obtendremos un mensaje de la forma:

{
    "message": "API Key no proporcionada. Operación no autorizada."
}

Si la API Key es válida tendremos:

{
    "message": "Datos obtenidos con exito."
}

Y finalmente si la API Key ha sido desactivada o es inválida tenemos:

{
    "message": "API Key inválida o inactiva."
}

Enjoy!!!

Tags

Artículos similares

Crea un blog sin base de datos con Grav

Existen muchas plataformas CMS de código abierto excelentes, como Joomla y WordPress, así como algunas plataformas emerg[...]

WhatsApp: Disponible función de envío de fotos y videos que desaparecen tras ser vistos

WhatsApp anuncio a través de su blog que ya se encuentra disponible la función de envío de fotos y videos TEMPORALES, es[...]

Como capturar cambios del Slider en JavaFX

En este tutorial veremos como usar el componente Slider de JavaFX , capturas los cambios que realice el usuario y con es[...]

Manejo de excepciones: Uso de Throw Exception en Laravel 11

El manejo correcto de excepciones permite que nuestras aplicaciones sean robustas, tolerante a fallos y amigable con el[...]

Búsqueda dinámica en JList

Un JList nos permite almacenar objetos en una lista y mostrarlos gráficamente en una serie vertical en el cual el usuari[...]

Ejercicios Resueltos C Sharp

1. Dado N números enteros ingresados por teclado, determine el promedio de estos 01 static void Main(string[] args) 02 {[...]