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

Ejemplo de operaciones CRUD con MyBatis 3

«MyBatis es una herramienta de persistencia Java que se encarga de mapear sentencias SQL y procedimientos almacenados co[...]

Elimina el fondo de tus fotografías en 5 segundos

Si te gusta realizar tus propios memes o foto montajes pero tienes poca o nula experiencia en editores gráficos como Pho[...]

JavaScript: Script y Web para generar banderas ondeando

Online Flag Waver es una páginas web con la que podemos generar banderas ondeando con la textura que elijamos ya sea des[...]

Software gratuito para la creación de prototipos GUI

En esta oportunidad te presento una herramienta de creación de prototipos de Interfaz Gráfica de Usuario o GUI de código[...]

Búsqueda binaria (Binary Search)

Un algoritmo de búsqueda binaria se emplea para buscar un valor en particular en un arreglo previamente ordenado. Para i[...]

Sonidos y Eventos en Swing

La siguiente clase reproduce sonidos WAV en controles Swing de Java Netbeans, los controles son pasados en el constructo[...]