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

Juego de Tragamonedas o Tragaperras

El juego de las tragamonedas o tragaperras es un juego muy popular de azar que se puede encontrar tanto en los casinos o[...]

Contar segundos (Problema Resuelto)

El problema dice asi: Se desea contar los segundos que se presiona un JButton en un formulario. Solución: Para resolver[...]

Cargar fuente TTF

Cuando realizamos un proyecto java utilizando fuentes de nuestro sistema, al momento de distribuir el programa y ejecuta[...]

Como hacer una factura en Java (Proyecto)

Tiempo atras me pidieron un ejemplo de como realizar un reporte con iReport tipo factura, recibo o como le llamen, compl[...]

Envía tu nombre a Marte en la Mars 2020 Rover

La misión espacial de la NASA, el Mars  2020 Rover Mission esta proyectada para lanzarse en julio de 2020 y su llegada s[...]

Tangram: El rompecabezas chino

El Tangram es un juego chino muy antiguo, esta compuesto por 7 piezas: un paralelogramo (romboide), un cuadrado y 5 triá[...]