Una clave de API es una cadena única que identifica a la app que llama a una API; la seguridad de claves de API es la disciplina de acotarla y protegerla. Precisión primero, porque la mayoría de las definiciones lo difumina: una clave identifica a la aplicación, ofrece solo autenticación débil (es una credencial bearer — quien la tiene, es tú) y lleva autorización gruesa (el alcance que se le adjuntó al crearla). Los usuarios se autentican con tokens; las apps se identifican con claves — y ninguna RFC define la clave de API. Es una convención, y exactamente por eso su seguridad es tu configuración, no la garantía de un estándar.
Puntos clave
| Pregunta | Respuesta |
|---|---|
| Qué hace una clave | Identifica la app · mide el uso · ancla los rate limits |
| Los dos animales | Claves publicables (hechas para embarcarse) vs. claves secretas (categoría contraseña) |
| La escalera del almacenamiento | Hardcodeada: nunca → variables de entorno: el mínimo → gestor de secretos: el estándar |
| La ley de hierro | Todo lo que va en un bundle de cliente es público — planifica para la extracción |
| Respuesta a una fuga | Revocar → sustituir → purgar el historial → auditar — en minutos, no en días |
La solicitud, y los dos tipos de clave
GET /v1/search?q=espresso HTTP/1.1
Host: api.example.com
X-Api-Key: pk_live_7f2c… ← en un HEADER — las URLs terminan en logs,
historial y referrers
Dos animales distintos comparten un nombre:
clave publicable se embarca en bundles web/móviles · identifica la app,
mide el uso · diseñada sabiendo que SERÁ extraída
clave secreta solo server-side · credencial bearer categoría contraseña ·
quien la tiene eres tú
El modelo publicable en la práctica — claves que se embarcan porque la seguridad vive en otra parte:
// JavaScript / Node.js — Back4app JS SDK
// Publishable keys: safe to ship BECAUSE authorization lives server-side
Parse.initialize(APP_ID, JS_KEY); // both ship in your bundle — by design
Parse.serverURL = 'https://parseapi.back4app.com';
// What protects data isn't key secrecy — it's CLPs + ACLs checked per request
// The one key that never ships: the Master Key bypasses every ACL and CLP.
// Server-only (Cloud Code / trusted backend), read from env or secret manager. // Flutter / Dart — Back4app Flutter SDK
// Publishable keys: safe to ship BECAUSE authorization lives server-side
await Parse().initialize(
appId, // ships in the app — by design
'https://parseapi.back4app.com',
clientKey: clientKey, // publishable, extractable, NOT a secret
);
// What protects data isn't key secrecy — it's CLPs + ACLs checked per request
// The Master Key bypasses every ACL and CLP: server-only, never in the app. // iOS / Swift — Back4app Swift SDK
// Publishable keys: safe to ship BECAUSE authorization lives server-side
ParseSwift.initialize(
applicationId: appId, // ships in the IPA — by design
clientKey: clientKey, // publishable, extractable, NOT a secret
serverURL: URL(string: "https://parseapi.back4app.com")!
)
// What protects data isn't key secrecy — it's CLPs + ACLs checked per request
// The Master Key bypasses every ACL and CLP: server-only, never in the app. // Android / Kotlin — Back4app Android SDK
// Publishable keys: safe to ship BECAUSE authorization lives server-side
Parse.initialize(
Parse.Configuration.Builder(context)
.applicationId(APP_ID) // ships in the APK — by design
.clientKey(CLIENT_KEY) // publishable, extractable, NOT a secret
.server("https://parseapi.back4app.com")
.build()
)
// What protects data isn't key secrecy — it's CLPs + ACLs checked per request
// The Master Key bypasses every ACL and CLP: server-only, never in the app. Claves de API vs. tokens vs. JWTs
| Clave de API | Access token de OAuth | JWT | |
|---|---|---|---|
| Identifica | La aplicación | El usuario (y el grant) | Lo que digan sus claims |
| Emisión | Una vez, por un admin | En cada login, por un flujo | Es un formato, no una emisión |
| Vida útil | Hasta que se rota (a menudo nunca) | Minutos a horas | Lo que diga exp |
| Alcance | Fijo al crearla | Scopes por grant | Definido por las claims |
| Estándar | Ninguno — convención | OAuth 2.0 | RFC 7519 |
| Trabajo correcto | Identificación server-to-server, medición | Acceso a API delegado por el usuario | Transporte de claims firmadas |
La comparación colapsa en una frase que vale memorizar: las claves identifican apps; los tokens autentican usuarios. Usar una clave donde importa la identidad del usuario es reconstruir mal la autenticación; usar tokens por usuario para medición anónima de apps es maquinaria sin propósito.
Dónde viven las claves: la escalera del almacenamiento
Hardcodeada — nunca. El código fuente se copia, se forkea y se commitea; git recuerda para siempre, y los bots de escaneo de secretos encuentran claves en commits públicos en cuestión de minutos. Variables de entorno — el mínimo, con la salvedad sobre la que el cheat sheet de OWASP es directo: las variables de entorno se filtran por logs de error, volcados de proceso y definiciones de contenedor; mantienen los secretos fuera de git, no fuera de problemas. Un gestor de secretos — el estándar de equipo: cifrado en reposo, con acceso controlado por servicio, auditado por lectura, rotable centralmente (las opciones open-source incluyen Vault, SOPS e Infisical). Suma la higiene que hace sobrevivibles las fugas: claves generadas con aleatoriedad criptográfica, prefijadas (estilo sk_live_…) para que los escáneres las reconozcan, guardadas con hash del lado del proveedor como contraseñas, una clave por app por entorno — y escaneo de secretos (gitleaks, trufflehog) conectado al CI, para que el commit que filtra una clave falle antes de aterrizar.
El problema del client-side, con honestidad
Todo explicador dice “no pongas claves secretas en el código del cliente”; casi ninguno dice la segunda mitad: tu bundle es público. El JavaScript web es legible por definición; los binarios móviles se desempaquetan y se les extraen strings de forma rutinaria; la ofuscación eleva el esfuerzo de minutos a horas, una sola vez. Se siguen dos consecuencias. Primera: las únicas claves que pertenecen a los clientes son las publicables — diseñadas para identificar, no para proteger, con la autorización real aplicada server-side en cada solicitud. Segunda: cuando un cliente debe usar un servicio de terceros con clave secreta, el secreto se queda detrás de tu propio backend — el patrón proxy:
Cuando una clave se filtra: el runbook
El reloj importa — los bots monitorean repositorios públicos y explotan claves commiteadas en uno a cinco minutos. En orden: 1 · Revoca la clave en el proveedor — antes de investigar, antes de la daily. 2 · Sustituye — emite la clave nueva y despliégala vía configuración, no código. 3 · Purga — elimínala del código fuente y del historial de git; una línea borrada sigue viva en cada clon. 4 · Audita — los logs del proveedor durante la ventana de la fuga: qué se leyó, se creó, se gastó. 5 · Amplía — todo lo co-ubicado con la clave (el mismo .env, el mismo repo) se presume quemado; rótalo también. Y la salvedad que separa la respuesta real del ritual: la revocación detiene el uso futuro — no des-exfiltra datos. Lo que se llevaron durante la ventana es un incidente, no una rotación.
Rotación sin downtime
La rotación acota el valor de las fugas no detectadas — una clave robada con 60 días de vida restante es un activo distinto de una válida para siempre. Cadencia basada en riesgo: 30–90 días para claves de alcance amplio o compartidas externamente, hasta un año para las internas de alcance estrecho, inmediatamente ante una sospecha de exposición o la salida de cualquiera que la haya tenido. La jugada de cero downtime es la superposición de clave dual: emite la clave nueva mientras la vieja sigue válida, migra los despliegues con calma y luego revoca la vieja — el mismo truco que los sistemas de refresh tokens formalizan. Los regímenes de compliance exigen cada vez más el calendario; el argumento de seguridad nunca lo necesitó.
Casos de uso comunes
- Integración server-to-server — el hábitat nativo de la clave: un servicio identificándose ante otro.
- Medición de uso y facturación — la clave como la unidad que los proveedores cuentan, limitan y facturan.
- Identificación publicable de clientes — bundles de apps llevando claves hechas para la exposición, con la autorización en otra parte.
- Separación de entornos — claves de prueba y de producción manteniendo los accidentes de staging fuera de los datos de producción.
- Contención de abuso — rate limits por clave y revocación como los controles de radio de daño.
¿Qué credencial deberías usar? Matriz de decisión
| Situación | Usa |
|---|---|
| Backend llamando a una API de terceros | Clave secreta, en un gestor de secretos |
| Identificar tu app desde web/móvil | Clave publicable + autorización server-side |
| Actuar en nombre de un usuario con sesión | Tokens OAuth, no claves |
| Claims firmadas entre servicios | JWTs |
| El cliente necesita un servicio con clave secreta | Tu backend como proxy — el secreto nunca se embarca |
| Máquina-a-máquina con auth estilo usuario | Flujo client credentials de OAuth |
Limitaciones y trade-offs
- Las claves no prueban posesión. Una cadena bearer no ofrece vínculo criptográfico con el llamador; para auth de servicio de alta garantía, el TLS mutuo y las solicitudes firmadas existen por algo.
- Las credenciales estáticas envejecen mal. Sin expiración, cada fuga queda abierta hasta que alguien la nota; la rotación es el sustituto manual del ciclo de vida que los tokens obtienen gratis.
- Los alcances gruesos comparten de más. Una clave con permisos amplios es una llave maestra; el alcance granular cuesta administración y paga en radio de daño.
- Las claves identifican, no autentican. Construir confianza a nivel de usuario sobre identificación a nivel de app es el patrón de broken authentication que los auditores buscan primero.
- La deriva de inventario es real. Las claves sin uso de integraciones viejas siguen válidas hasta que se borran — la prima credencial-zombi de los endpoints zombis.
Claves de API en Back4app
Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. Su modelo de claves es la sección del client-side hecha concreta: el Application ID y las client keys se embarcan dentro de tus apps por diseño — la propia documentación de Back4app es explícita: las client keys no son mecanismos de seguridad — porque la autorización nunca depende de ellas: cada solicitud se verifica server-side contra los permisos a nivel de clase y las ACLs, así que una clave extraída le concede a un atacante exactamente lo que obtiene un usuario anónimo. El único secreto de verdad es la Master Key, que se salta toda ACL y CLP: vive solo server-side — Cloud Code, backends confiables, variables de entorno o gestor de secretos — y nunca en un bundle. Las pestañas de código muestran la división en la práctica; el runbook aplica solo a la master key, y ese es el punto: un secreto que cuidar es una postura de seguridad, cuarenta son una hoja de cálculo.
Preguntas frecuentes
¿Qué es una clave de API?
Una cadena única que un proveedor de API emite para una aplicación registrada, enviada con cada solicitud — idealmente en un header — para que el servidor identifique al llamador, aplique sus permisos, mida el uso e imponga rate limits. Un detalle notable: ningún estándar la define — las claves de API son una convención, no un protocolo.
¿Una clave de API es una contraseña?
Una clave secreta es funcionalmente de la misma categoría que las contraseñas: es una credencial bearer, así que cualquiera que la tenga es tratado como tú — misma disciplina de almacenamiento, mismas consecuencias de brecha. Las diferencias: las claves identifican aplicaciones, no personas, y muchas nunca expiran a menos que las rotes.
¿Cuál es la diferencia entre una clave de API y un token?
Las claves identifican apps; los tokens autentican usuarios. Una clave es estática, generada por un admin y con alcance de aplicación; un access token de OAuth se emite en el login, tiene vida corta, es renovable y lleva los permisos de un usuario específico. La identificación server-to-server va con claves; cualquier cosa específica de un usuario pertenece a los tokens.
¿Dónde debo guardar las claves de API?
Nunca en el código fuente. Las variables de entorno en un archivo fuera del versionado son el mínimo — con la salvedad de que se filtran por logs, volcados de proceso y definiciones de contenedor — y un gestor de secretos es el estándar de equipo: cifrado en reposo, con control de acceso, auditado y rotable.
¿Puedo poner una clave de API en el frontend o en una app móvil?
Solo una clave publicable, diseñada para eso. Cualquier cosa en un bundle de JavaScript o en el binario de una app es pública — la extracción es rutinaria y la ofuscación solo la retrasa. Las claves secretas se quedan server-side; cuando un cliente necesita un servicio con clave secreta, enruta la llamada a través de tu propio backend.
¿Qué debo hacer cuando una clave de API se filtra?
Inmediatamente: revoca la clave, despliega una sustituta, púrgala del código y del historial de git, audita los logs de uso en busca de abuso y rota todo lo que estaba almacenado junto a ella. Muévete rápido — los bots prueban claves commiteadas en repositorios públicos en cuestión de minutos — y recuerda: la revocación detiene el uso futuro, no los datos ya extraídos.
¿Cada cuánto deben rotarse las claves de API?
Según el riesgo: cada 30–90 días para claves de alcance amplio o expuestas externamente, más tiempo para las internas de bajo riesgo, e inmediatamente ante una sospecha de exposición o la salida de alguien del equipo. La rotación sin downtime usa una ventana de superposición en la que la clave vieja y la nueva valen a la vez mientras los despliegues se actualizan.
¿Cómo se filtran las claves de API?
En orden de infamia: commiteadas en repositorios git, embarcadas en bundles de cliente y binarios móviles, puestas en URLs donde los logs del servidor y el historial del navegador las capturan, impresas en logs de aplicación y de CI, y pegadas en chats y tickets. Cada vector es prevenible, que es lo que hace deprimente la lista.