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!!!
Acierta los colores o Adivina los colores es un sencillo juego que consiste en que dado 6 colores «rojo», «verde», «salm[...]
DOM4J es una de las librerías para java más populares para el trabajo con XML ya que nos permite crea, editar y leer doc[...]
En este post mostramos como personalizar el Header (encabezado) de un componente JTable en Java colocando iconos, centra[...]
Utilizando pygame para hacer gráficos en python, se muestra a continuación un sencillo ejemplo de cómo utilizar esta lib[...]
El laberinto del terror es un juego en el que haciendo uso del ratón y de tu pulso de borracho debes cruzar distintos la[...]
Cuando llevamos tiempo programando vamos armando un librería personal de código que utilizamos con frecuencia en nuestro[...]