Autenticación
Vincent Depassier · 17 de septiembre de 2026
Toda llamada lleva una credencial. El gateway decide qué puedes ver a partir de esa credencial y nada más — no hay un segundo paso de autorización en tu código, ni forma de que un cliente pida más de lo que su credencial permite.
Cómo mandar la credencial
Cualquiera de las dos cabeceras sirve, y son equivalentes:
Authorization: Bearer sk_live_...
x-api-key: sk_live_...Un pedido sin credencial se rechaza con 401 y una cabecera WWW-Authenticate que apunta a los metadatos de recurso protegido de la ruta que se llamó:
WWW-Authenticate: Bearer realm="Praxsuite Gateway", resource_metadata="https://gateway.praxsuite.com/.well-known/oauth-protected-resource/{workspaceId}/mcp"Ese documento (RFC 9728) nombra al servidor de autorización que protege este recurso, que es lo que le permite a un cliente MCP descubrir dónde autenticarse en vez de adivinar. Ver Documentos de discovery para ese documento y el salto que viene después.
Dos tipos de clave
Prefijo | Nombre | Dónde va | Se valida el origen |
| Clave de servidor | Tu backend | No |
| Clave de cliente | Navegador, app móvil, cliente de juego | Sólo si configuras orígenes |
La diferencia no son los permisos: las dos se acotan desde la misma pantalla y de la misma forma. La diferencia es la exposición. Una clave de servidor se guarda como un hash de una sola vía —la clave en sí no se puede recuperar, y no se vuelve a mostrar después de crearla—, así que es segura únicamente donde tus usuarios no llegan. Una clave de cliente está pensada para viajar dentro de código que cualquiera puede leer.
Pon una clave pk_live_ en todo lo que un usuario pueda abrir. Una clave de servidor en un bundle de frontend es una credencial completa del workspace entregada a cada visitante.
Los orígenes no vienen puestos
Aquí es donde se equivoca la mayoría. Una clave de cliente no está restringida por defecto:
Sin reglas de origen → la clave funciona desde cualquier sitio. El gateway registra una advertencia y deja pasar la llamada.
Con una o más reglas → la cabecera
Origindel pedido tiene que coincidir con alguna, o la llamada es403. Un pedido sinOriginse rechaza, porque un navegador siempre la manda.Una regla puede ser un origen exacto (
https://app.ejemplo.com) o un comodín de subdominio (*.ejemplo.com).
Un despliegue se puede configurar para rechazar de plano las claves de cliente sin reglas, en cuyo caso la llamada es 403 con "This client key has no allowed origins configured." No cuentes con que esté activo. Carga tú los orígenes.
La clave pública de una credencial sólo la entrega GET /auth/config después de que alguien la haya marcado explícitamente como publicable, porque publicarla le da los permisos de tabla de esa credencial a cualquiera que conozca el GUID del workspace. Acota la credencial antes de marcarla.
Tokens de usuario final
Las claves de arriba identifican a tu aplicación. El usuario final de tu aplicación es una identidad aparte, y autenticarlo devuelve un JWT.
Ese JWT se acepta en las rutas de datos —/query, /schema— y en /auth/change-password. Todo el resto de /auth exige una API key, porque esas rutas son la forma en que una aplicación demuestra que puede crear identidades en este workspace. Mandar un JWT a /auth/login es 401 con "Auth endpoints require a valid API key."
La forma práctica de una app de navegador es una cadena de dos credenciales: una clave publicable para entrar, y después un token que le pertenece a la persona.
Existe un tercer tipo de token, para integraciones con tiendas de IA: un token OAuth2 emitido durante un flujo de authorization code + PKCE. Se comporta como una credencial, no como un usuario final.
Rutas que no piden credencial
Ruta | Por qué |
| Arranca un cliente de navegador: devuelve la clave publicable y el branding |
| Redirige al logo del workspace, para la pantalla de login |
| Claves públicas para verificar tokens de redirección |
| Se abre desde un enlace de correo, que no manda cabeceras |
| Un enlace de archivo firmado — la firma es la credencial |
| Los endpoints personalizados autentican con HMAC, no con claves |
| Descripciones legibles por máquina |
Permisos
Una credencial da acceso tabla por tabla y, dentro de una tabla, columna por columna.
Nombrar una tabla para la que la credencial no tiene permiso es un 403 SCOPE_VIOLATION duro — el mensaje dice qué alias se rechazó, y deliberadamente no confirma si la tabla existe, así nadie puede mapear tu workspace probando. Las columnas se comportan distinto: select: "*" devuelve sólo las columnas marcadas como legibles, así que una credencial con permisos de columna acotados ve una fila más angosta en lugar de un error.
Un permiso de tabla trae además tres límites que conviene conocer antes de diseñar una consulta:
Ajuste | Efecto sobre el pedido |
Filtro de filas | Se suma con AND, en silencio, a todo |
Agregaciones permitidas | Si está apagado, cualquier |
Límite máximo | Topea el |
Una columna puede llevar además una regla de enmascarado, en cuyo caso la columna vuelve pero su valor no es el almacenado.
Una credencial sin permisos de columna definidos está abierta en todas las columnas de las tablas que alcanza. Los permisos de columna son un recorte, no una lista blanca que haya que llenar.
Cuándo aplica un cambio de credencial
De inmediato. Revocar una credencial, o recortarle los permisos, aplica en la llamada siguiente — no hay período de gracia que esperar ni nada que reiniciar.
Por qué se rechaza una credencial
Estado | Causa |
| Sin clave, clave mal formada, clave desconocida, o de otro workspace |
| La credencial tiene vencimiento y ya pasó |
| La credencial está Revocada o Comprometida |
| El principal dueño de la credencial no está Activo |
| Clave de cliente, con reglas de origen, y el |
Seguir
Errores y límites — cómo se ve un rechazo
Autenticación de usuarios finales — toda la superficie
/auth