Praxsuite

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

sk_live_

Clave de servidor

Tu backend

No

pk_live_

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 Origin del pedido tiene que coincidir con alguna, o la llamada es 403. Un pedido sin Origin se 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.

Una app de navegador arranca sin credencial, pide la clave publicable pk_live_ del workspace con GET /auth/config, autentica al usuario final con POST /auth/login para obtener un JWT, y manda ese JWT en POST /query. Una clave de servidor sk_live_ nunca participa de esta cadena.

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é

GET /{ws}/auth/config

Arranca un cliente de navegador: devuelve la clave publicable y el branding

GET /{ws}/auth/logo

Redirige al logo del workspace, para la pantalla de login

GET /{ws}/auth/jwks.json

Claves públicas para verificar tokens de redirección

GET /{ws}/auth/confirm-email

Se abre desde un enlace de correo, que no manda cabeceras

GET /{ws}/files/...?exp=&sig=

Un enlace de archivo firmado — la firma es la credencial

POST /{ws}/endpoint/{id}

Los endpoints personalizados autentican con HMAC, no con claves

GET /api/v1/gateway/openapi.json y los demás documentos de discovery

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 where sobre esa tabla

Agregaciones permitidas

Si está apagado, cualquier groupBy o select agregado se rechaza

Límite máximo

Topea el limit de esa tabla; el techo absoluto es 1000 filas

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

401

Sin clave, clave mal formada, clave desconocida, o de otro workspace

401

La credencial tiene vencimiento y ya pasó

403

La credencial está Revocada o Comprometida

403

El principal dueño de la credencial no está Activo

403

Clave de cliente, con reglas de origen, y el Origin no coincide

Seguir

  • Errores y límites — cómo se ve un rechazo

  • Autenticación de usuarios finales — toda la superficie /auth