Saltar al contenido

Lección 10 de 16 · Lectura y práctica

Autenticación y Manejo de Headers en APIs

Autenticación y Manejo de Headers en APIs Cuando trabajas con APIs web, la comunicación entre cliente y servidor no se limita únicamente al envío de datos. Existe un sistema de metadatos que acompaña cada petición y respuesta:.

Del concepto a la práctica

Taller de esta lección

Los encabezados separan metadatos de autenticación, negociación de contenido y trazabilidad. Una clave o token debe llegar desde una variable de entorno o un almacén seguro, nunca desde el código compartido. Además, los logs deben ocultar su valor. Un 401 no se arregla repitiendo indefinidamente la petición: exige revisar credenciales o renovar autorización según el contrato del servicio.

Ejemplo resuelto

El cliente prepara una petición sin revelar el token:

python
import os, requests
headers = {'Accept': 'application/json', 'Authorization': f"Bearer {os.environ['API_TOKEN']}"}
r = requests.get('https://ejemplo.invalid/recurso', headers=headers, timeout=5)
print(r.status_code, 'Authorization' in headers)
  1. Comprueba que API_TOKEN exista.

  2. Construye headers mínimos.

  3. Registra solo el código de estado.

  4. Detén el flujo ante 401 y solicita revisión.

Un error frecuente es guardar el token en un archivo de configuración versionado. Corrígelo con variables de entorno y un ejemplo sin valores reales.

Pruébalo

Simula estados 200, 401 y 429 con respuestas locales representadas como diccionarios.

Comprueba tu resultado

200 continúa, 401 detiene con mensaje de autenticación y 429 queda registrado como límite; ningún resultado contiene el token.

Diagrama de decisión con ramas Sí y No y un bucle que procesa cada elemento de una lista.
CursaloMapa de práctica
Cómo avanza un programa

Una condición decide qué camino ejecuta el programa. Un bucle repite una operación mientras queden elementos, y termina cuando la lista se agota. Separar ambas ideas ayuda a seguir el flujo y comprobar casos límite.

Ver la infografía en tamaño completo ↗

Autenticación y Manejo de Headers en APIs

Cuando trabajas con APIs web, la comunicación entre cliente y servidor no se limita únicamente al envío de datos. Existe un sistema de metadatos que acompaña cada petición y respuesta: los headers (encabezados). Dominar su uso, especialmente los relacionados con la autenticación, es fundamental para construir automatizaciones robustas y seguras.

¿Qué son los Headers HTTP?

Los headers HTTP son pares de clave-valor que se envían en las peticiones y respuestas HTTP. Se dividen en:

  • Request Headers: Enviados por el cliente al servidor.
  • Response Headers: Enviados por el servidor al cliente.
  • General Headers: Aplican tanto a peticiones como respuestas.
  • Entity Headers: Describen el contenido del cuerpo del mensaje.

En el contexto de la automatización con Python, los headers más relevantes son aquellos relacionados con la autenticación y el formato de datos.

Métodos de Autenticación en APIs

1. API Keys

Es el método más simple. Se proporciona una clave única que identifica al cliente. Generalmente se incluye en los headers o como parámetro de consulta.

import requests

# API Key como header personalizado
headers = {
    'X-API-Key': 'tu_clave_secreta_aqui',
    'Content-Type': 'application/json'
}

respuesta = requests.get('https://api.ejemplo.com/datos', headers=headers)
print(respuesta.status_code)
print(respuesta.json())

Nota: Muchas APIs usan el prefijo X- para headers personalizados. Otras utilizan convenciones como Authorization para headers estandarizados.

2. Basic Authentication

Utiliza usuario y contraseña codificados en Base64. Aunque es simple, debe usarse siempre sobre HTTPS.

import requests
from requests.auth import HTTPBasicAuth

# Método 1: Usando HTTPBasicAuth
respuesta = requests.get(
    'https://api.ejemplo.com/protegido',
    auth=HTTPBasicAuth('usuario', 'contraseña_segura')
)

# Método 2: Manualmente con headers
import base64
credenciales = base64.b64encode(b'usuario:contraseña_segura').decode('utf-8')
headers = {
    'Authorization': f'Basic {credenciales}'
}
respuesta = requests.get('https://api.ejemplo.com/protegido', headers=headers)

3. Bearer Token (Token JWT)

Es el método más popular en APIs modernas. Después de autenticarse exitosamente, el servidor devuelve un token que se envía en cada petición subsiguiente.

import requests

# Primero, obtenemos el token mediante autenticación
datos_login = {
    'email': 'usuario@ejemplo.com',
    'password': 'mi_contraseña'
}

respuesta_login = requests.post(
    'https://api.ejemplo.com/auth/login',
    json=datos_login
)

if respuesta_login.status_code == 200:
    token = respuesta_login.json()['access_token']
    
    # Usamos el token para peticiones protegidas
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }
    
    respuesta_datos = requests.get(
        'https://api.ejemplo.com/perfil',
        headers=headers
    )
    print(respuesta_datos.json())

4. OAuth 2.0

Es el estándar para autorización. Permite que las aplicaciones accedan a recursos sin compartir credenciales. Python tiene librerías como authlib que simplifican su implementación.

import requests
from authlib.integrations.requests_client import OAuth2Session

# Configuración del cliente OAuth
cliente = OAuth2Session(
    client_id='tu_client_id',
    client_secret='tu_client_secret',
    scope='read write'
)

# Obtener token de acceso
token = cliente.fetch_token(
    'https://api.ejemplo.com/oauth/token',
    username='usuario@ejemplo.com',
    password='contraseña',
    grant_type='password'
)

# Usar el token en peticiones
headers = {'Authorization': f"Bearer {token['access_token']}"}
respuesta = requests.get('https://api.ejemplo.com/recurso', headers=headers)

Manejo de Headers Personalizados

Aparte de la autenticación, los headers permiten enviar información adicional útil para las APIs:

import requests

headers = {
    'Authorization': 'Bearer tu_token_aqui',
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'User-Agent': 'MiAppPython/1.0',
    'Accept-Language': 'es-ES,es;q=0.9',
    'Cache-Control': 'no-cache'
}

respuesta = requests.get(
    'https://api.ejemplo.com/búsqueda',
    headers=headers,
    params={'query': 'automatización', 'limit': 10}
)

print(f"Rate Limit Remaining: {respuesta.headers.get('X-RateLimit-Remaining')}")
print(f"Content-Type: {respuesta.headers.get('Content-Type')}")

Ejemplo Práctico: Cliente de API con Manejo de Headers

Vamos a construir una clase reutilizable que maneje la autenticación de manera elegante:

import requests
from typing import Optional, Dict, Any

class ClienteAPI:
    def __init__(self, base_url: str, api_key: Optional[str] = None):
        self.base_url = base_url.rstrip('/')
        self.api_key = api_key
        self.session = requests.Session()
        self.token: Optional[str] = None
        
        # Headers base para todas las peticiones
        self.session.headers.update({
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'User-Agent': 'PythonAPIClient/1.0'
        })
    
    def autenticar_token(self, token: str) -> None:
        """Establece un token de Bearer para autenticación."""
        self.token = token
        self.session.headers.update({
            'Authorization': f'Bearer {token}'
        })
    
    def autenticar_api_key(self, api_key: str, header_name: str = 'X-API-Key') -> None:
        """Establece una API Key personalizada."""
        self.session.headers.update({header_name: api_key})
    
    def get(self, endpoint: str, params: Optional[Dict] = None) -> Dict[str, Any]:
        """Realiza una petición GET."""
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        respuesta = self.session.get(url, params=params)
        respuesta.raise_for_status()
        return respuesta.json()
    
    def post(self, endpoint: str, data: Optional[Dict] = None) -> Dict[str, Any]:
        """Realiza una petición POST."""
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        respuesta = self.session.post(url, json=data)
        respuesta.raise_for_status()
        return respuesta.json()

# Uso del cliente
cliente = ClienteAPI('https://api.ejemplo.com')
cliente.autenticar_token('mi_token_jwt')
datos = cliente.get('/usuarios', params={'activo': True})
print(datos)

Errores Comunes

Evita estos errores frecuentes al trabajar con autenticación y headers:

  1. Olvidar el prefijo "Bearer" en el token: El header debe ser Authorization: Bearer TOKEN, no solo Authorization: TOKEN. Esto causa un error 401 en la mayoría de APIs.
  2. No manejar tokens expirados: Los tokens JWT tienen caducidad. Debes implementar refresh tokens o detectar errores 401 para reautenticarte automáticamente.
  3. Enviar headers de autenticación en texto plano: Siempre usa HTTPS. Enviar tokens o credenciales sobre HTTP permite que terceros los intercepten fácilmente.

Buenas Prácticas

  • Nunca hardcodees credenciales: Usa variables de entorno o archivos de configuración seguros.
  • Implementa reintentos automáticos: Las APIs pueden devolver errores temporales.
  • Registra los headers de respuesta: Úsalos para depurar y monitorear rate limits.
  • Centraliza la autenticación: Una clase o módulo dedicado facilita el mantenimiento.

Recuerda: La seguridad de tu automatización depende del manejo adecuado de las credenciales. Un token expuesto puede comprometer toda tu aplicación.

Checklist de Dominio

  • Entiendo la diferencia entre headers de request y response
  • Sé implementar autenticación con API Key
  • Sé implementar autenticación Basic con usuario y contraseña
  • Sé implementar autenticación Bearer Token
  • Puedo extraer y utilizar headers de respuesta
  • Uso variables de entorno para almacenar credenciales
  • Implemento manejo de errores 401 y reautenticación
  • Utilizo HTTPS para todas las peticiones con autenticación
  • Creo clases reutilizables para gestión de APIs
  • Verifico los headers de rate limit para evitar bloqueos

Sigue con Automatización de Procesos con Python

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.