Las claves de API y OAuth resuelven problemas distintos, y la elección entre ambos empieza por una sola pregunta: ¿hay un tercero en el esquema?
Si tu servidor llama a la API de otro en su propio nombre, necesitas una clave. Si la aplicación de otro llama a tu API en nombre de tu usuario, necesitas OAuth. Cuando no hay tercero, OAuth añade ceremonia sin añadir seguridad.
A continuación: en qué se diferencian realmente, qué ha cambiado en OAuth en los últimos años y una propiedad de las claves de API de la que casi nadie escribe, aunque determina cómo convivirás con ellas en producción.
La clave de API: una cadena que dice «este programa puede»
Una clave es una cadena larga y aleatoria que colocas en una cabecera de la petición:
X-Api-Key: lix_live_9f2c...
El servidor encuentra la clave, deduce a qué cuenta pertenece y deja pasar la petición. Ese es todo el mecanismo.
De ahí se derivan sus propiedades:
- la clave no caduca sola. Vive hasta que alguien la revoca;
- la clave identifica a un programa, no a una persona. Quién del equipo hizo la llamada suele ser invisible;
- la clave concede todo lo que puede hacer la cuenta, salvo que limites sus permisos aparte;
- la clave es el único secreto. Si se filtra, se filtra el acceso: no hay pasos intermedios.
OAuth: un protocolo sobre el consentimiento
OAuth 2.0 (RFC 6749) responde a otra pregunta. Tiene cuatro participantes: el dueño de los datos, la aplicación que los quiere, un servidor de autorización y el servidor que guarda los datos.
El recorrido es más o menos así. La aplicación envía a la persona a la página del propio servicio. Esa persona ve quién pide y para qué, y acepta. La aplicación recibe un código, lo canjea por un token de acceso y llama a la API con él. El token dura poco —minutos u horas—; cuando caduca, la aplicación cambia un token de refresco por uno nuevo.
Lo que esto aporta y una clave no puede aportar por definición:
- la contraseña del usuario nunca llega a la aplicación. Ese es el sentido entero;
- los permisos se reparten en scopes. «Leer enlaces» y «borrar enlaces» son concesiones distintas;
- el consentimiento es visible y revocable. El usuario ve la lista de aplicaciones conectadas y puede desconectar una sin tocar las demás;
- los tokens caducan solos. Un token de acceso robado no sirve de nada una hora después.
El precio es la complejidad: un servidor de autorización, el registro de aplicaciones, una pantalla de consentimiento, guardar y rotar tokens de refresco, y gestionar la caducidad en cada llamada.
Comparación por los ejes que de verdad deciden
| Clave de API | OAuth 2.0 | |
|---|---|---|
| A quién acredita | al programa | al usuario en cuyo nombre actúa el programa |
| Vida útil | indefinida | token de acceso: minutos u horas |
| Cómo se corta el acceso | revocar la clave | revocar el consentimiento o el token |
| Alcance de permisos | normalmente toda la cuenta | scopes por acción |
| Secreto en manos del tercero | la propia clave | solo tokens, nunca la contraseña |
| Esfuerzo de integración | una cabecera | un servidor de autorización y el ciclo completo |
| Dónde encaja | servidor a servidor, scripts, integraciones internas | apps públicas, marketplaces, «Entrar con…» |
La regla para elegir
La pregunta no es cuál es más seguro en abstracto, sino quién delega el acceso a quién.
Tu servidor → API ajena, cuenta tuya
→ clave de API
App ajena → tu API, cuenta de tu usuario
→ OAuth
Tarea programada, CI, integración de backend
→ clave de API
El usuario debe ver y revocar el acceso por aplicación
→ OAuth
Recibir postbacks es el caso de manual para una clave. Cuando tu servidor avisa al nuestro de que un pedido se ha pagado, en ese intercambio no hay ningún usuario, no hay quien consienta ni dónde poner una pantalla de consentimiento. Lo mismo vale para los webhooks en sentido contrario.
Qué ha cambiado en OAuth mientras no mirabas
La mitad de los artículos sobre el tema describen el OAuth de 2015. Desde entonces se ha estrechado bastante.
En enero de 2025 el IETF publicó la RFC 9700, Best Current Practice for OAuth 2.0 Security. El documento reúne años de experiencia real con ataques y declara formalmente obsoletos dos flujos que antes se consideraban aceptables:
- el implicit grant, aquel que devolvía el token directamente en la barra de direcciones;
- resource owner password credentials, donde la aplicación pedía al usuario su usuario y su contraseña. Justo aquello que OAuth vino a evitar.
A la vez, PKCE pasó a ser obligatorio para todos los tipos de cliente, incluidos los de servidor, y no solo para los móviles como antes.
Conviene saberlo aparte: OAuth 2.1 sigue siendo un borrador, no una RFC publicada. Recoge esos mismos cambios en un único documento —PKCE obligatorio, comparación exacta de la redirect URI, sin implicit ni password grant, sin tokens en la cadena de consulta—. Citarlo como estándar vigente es prematuro.
Conclusión práctica: si una guía de OAuth propone el flujo implícito, la guía está caducada.
El punto débil de las claves del que casi no se habla
Una clave no caduca. Eso convierte la revocación en tu única palanca. Y aquí aparece lo incómodo: la revocación no suele ser instantánea.
Comprobar la clave en cada petición significa ir a la base de datos. En cualquier API con tráfico real ese resultado se cachea. En nuestro caso la correspondencia entre clave y cuenta permanece cinco minutos en caché. Así que entre pulsar «revocar» y el corte efectivo del acceso pasan hasta cinco minutos, durante los cuales una clave comprometida sigue funcionando.
No es un descuido, es un intercambio: sin caché, cada petición golpea la base de datos. Casi cualquier API con claves acepta un trato parecido, solo que no se suele decir en voz alta. Importa por dos motivos. Primero, ante una filtración real revocar la clave es la primera acción, no la última: después conviene revisar qué ocurrió en esos minutos. Segundo, es exactamente el problema que los tokens de vida corta de OAuth atacan por el otro lado: caducan solos, sin que intervenga ninguna base de datos.
Convivir con claves sin llevarse un disgusto
Si las claves bastan —y en la mayoría de integraciones bastan—, el mínimo es este:
- Guarda solo el hash. El servidor compara el hash de la clave recibida con el almacenado; la cadena original se muestra una sola vez, al crearla. Las nuestras se cotejan por SHA-256.
- Ponle un prefijo a la clave. Una cadena con la forma
lix_live_...la reconocen los escáneres de secretos en repositorios y en los registros. - Una clave por integración. Así revocar una no tumba las demás, y el historial muestra qué se ha comprometido exactamente.
- Nunca pongas la clave en la cadena de consulta. Las direcciones acaban en los registros del servidor web, en la cabecera
Referery en el historial del navegador. Solo cabecera. - Rota por calendario, no por incidente. Una clave que se ha rotado una vez se rota rápido. Una que no se ha rotado nunca aparecerá incrustada en cuatro sitios.
- Vigila la fecha de último uso. Una clave sin tocar durante medio año no es una reserva, es una puerta abierta.
Qué usamos nosotros
La API de Lix.li se autentica con claves: cabecera X-Api-Key, claves creadas y revocadas desde el panel, cotejo por hash y un límite de peticiones propio por clave. No hay OAuth, y es deliberado: los escenarios de la API son de servidor —crear un enlace, recoger estadísticas, aceptar una conversión— y en ninguno interviene un tercero al que el usuario deba dar su consentimiento.
Si apareciera la necesidad de dejar entrar aplicaciones ajenas a las cuentas de nuestros clientes, las claves dejarían de bastar: el usuario tiene que ver a quién le ha permitido qué y poder desconectar una aplicación sin romper el resto. Ahí es donde OAuth deja de ser ceremonia y pasa a ser la única opción honesta.
Las llamadas en sí están descritas en la documentación de la API, incluidos los códigos de respuesta que llegan con una clave inválida y con una revocada. En un tema vecino, por qué una redirección 301 convierte un POST en GET merece una lectura de quien esté montando la recepción de postbacks: una petición autenticada puede llegar con un método distinto al que salió.