1-3Evolución: Del Body a los Headers

 


Antes (Menos Seguro):

http
POST /login HTTP/1.1
Content-Type: application/json

{
  "email": "usuario@ejemplo.com",
  "password": "miclave123",
  "api_key": "mi_api_key_secreta"
}

Ahora (Más Seguro):

http
GET /api/usuarios HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
X-API-Key: abc123def456
Content-Type: application/json

{
  "email": "usuario@ejemplo.com",
  "password": "miclave123"
}

¿Por Qué Esta Evolución?

Problemas de Enviar Claves en el Body:

  1. Logs y Caché: Los bodies suelen loguearse y cachearse

  2. Exposición en URLs: En GET, el body no se usa, así que iban en query params

  3. Seguridad: Más vulnerable a ataques MITM (Man-in-the-Middle)

Ventajas de Usar Headers:

  1. Separación clara: Autenticación vs Datos

  2. Estándar HTTP: Los headers están diseñados para metadatos

  3. Mejor seguridad: Menos propensos a logging accidental

  4. Caché apropiada: Las respuestas pueden cachearse sin exponer credenciales

Cómo Manejar Esto en Laravel

1. Autenticación con Tokens en Headers

php
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', function (Request $request) {
        return $request->user();
    });
});

// En el frontend o cliente
$response = Http::withHeaders([
    'Authorization' => 'Bearer ' . $token,
    'Accept' => 'application/json',
])->get('https://api.tudominio.com/user');

2. Diferentes Tipos de Autenticación por Headers

php
// Bearer Token (JWT)
$request->header('Authorization'); // 'Bearer eyJhbGci...'

// API Key
$request->header('X-API-Key');
$request->header('API-Key');

// Basic Auth
$request->header('Authorization'); // 'Basic base64_encode(user:pass)'

3. Middleware para Validar Headers Personalizados

php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class ValidateApiKey
{
    public function handle(Request $request, Closure $next)
    {
        $apiKey = $request->header('X-API-Key');
        
        if (!$apiKey || $apiKey !== config('app.api_key')) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
        
        return $next($request);
    }
}

Cuándo Usar Body vs Headers

Usar HEADERS para:

php
// Autenticación
Authorization: Bearer token123

// API Keys
X-API-Key: abc123

// Metadatos de solicitud
Accept: application/json
Content-Type: application/json
User-Agent: MyApp/1.0

// Caché
If-None-Match: "etag_value"

Usar BODY para:

php
// Datos del usuario para crear/actualizar
{
  "name": "Juan",
  "email": "juan@ejemplo.com",
  "password": "clave_segura" // Solo en login/registro
}

// Filtros y búsquedas complejas
{
  "filters": {
    "status": "active",
    "date_from": "2024-01-01"
  }
}

// Operaciones complejas
{
  "operations": [
    {"action": "update", "field": "name", "value": "Nuevo"},
    {"action": "delete", "id": 123}
  ]
}

Ejemplo Completo: Login Seguro

Solicitud de Login (Body para credenciales iniciales)

http
POST /api/login HTTP/1.1
Content-Type: application/json

{
  "email": "usuario@ejemplo.com",
  "password": "clave_temporal"
}

Respuesta Exitosa

http
HTTP/1.1 200 OK
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

{
  "user": {
    "id": 1,
    "name": "Juan",
    "email": "usuario@ejemplo.com"
  },
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Solicitudes Subsecuentes (Token en Header)

http
GET /api/usuarios/1 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Accept: application/json

Implementación en Laravel

Login Controller:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
    public function login(Request $request)
    {
        // Credenciales van en el body (solo para login)
        $credentials = $request->validate([
            'email' => 'required|email',
            'password' => 'required'
        ]);

        if (Auth::attempt($credentials)) {
            $user = Auth::user();
            $token = $user->createToken('api-token')->plainTextToken;
            
            return response()->json([
                'user' => $user,
                'access_token' => $token,
                'token_type' => 'Bearer'
            ])->header('Authorization', 'Bearer ' . $token);
        }
        
        return response()->json(['error' => 'Unauthorized'], 401);
    }

    public function logout(Request $request)
    {
        // El token va en el header
        $request->user()->currentAccessToken()->delete();
        
        return response()->json(['message' => 'Logged out']);
    }

    public function getUser(Request $request)
    {
        // Token en header para autenticación
        return response()->json($request->user());
    }
}

Cliente API (Ejemplo con JavaScript):

javascript
// Login (credenciales en body)
const login = async (email, password) => {
    const response = await fetch('/api/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email, password })
    });
    
    const data = await response.json();
    localStorage.setItem('token', data.access_token);
    return data;
};

// Solicitudes autenticadas (token en header)
const getUsers = async () => {
    const token = localStorage.getItem('token');
    
    const response = await fetch('/api/usuarios', {
        method: 'GET',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Accept': 'application/json'
        }
    });
    
    return response.json();
};

Reglas de Oro:

  1. Credenciales iniciales (login) → Body (por única vez)

  2. Tokens de acceso → Headers (siempre)

  3. API Keys → Headers (siempre)

  4. Datos del usuario → Body

  5. Metadatos → Headers

¿Quieres que profundice en algún aspecto específico como JWT, OAuth, o seguridad avanzada?

Comentarios

Entradas más populares de este blog

8-Creación de una API RESTful con Laravel

02 -Rutas en Laravel

3-Rutas