Saltar al contenido principal

Autenticación

La API de Kadu usa un access token de la Cuenta Kobana para autenticar todas las solicitudes, en el header Authorization: Bearer, como las demás APIs de Kobana.

curl -H "Authorization: Bearer $KOBANA_TOKEN" \
-H "Content-Type: application/json" \
https://api.kadu.ia.br/v1/me

El token​

El token es un access token emitido por el Authorization Server de Kobana (account.kobana.com.br). Kadu solo lo verifica: no guarda una clave de firma y no puede emitir ningún token.

  • Algoritmo: RS256, y solo RS256.
  • Tipo: el encabezado del token debe tener typ: at+jwt (RFC 9068). Otro JWT del mismo emisor, como un ID token, se rechaza.
  • Clave: pública, y descubierta, no configurada. El identificador del emisor es una URL, y el endpoint de las claves (jwks_uri) se lee del documento de metadata RFC 8414 publicado bajo ella (/.well-known/oauth-authorization-server). Cuando el Authorization Server rota la clave, Kadu la sigue solo.
  • Cuándo se llama al Authorization Server: nunca para verificar un token, porque la verificación de la firma es local. Lo que viene de él es el conjunto de claves, que se guarda en caché. Una consulta solo ocurre con la caché vacía, con el conjunto en caché hace más de una hora, o cuando llega un token con un kid que no está en la caché (una rotación; como máximo una nueva consulta cada 30 segundos). Cada consulta tiene un timeout de 5 segundos.

Claims​

ClaimDescripción
issEl identificador del Authorization Server, como URL: https://account[.{env}].kobana.com.br.
audEsta API, como URL: https://api.kadu.ia.br (staging: https://api.staging.kadu.ia.br). Puede ser una lista: la regla es contiene, no igualdad, así que un token puede dirigirse a más de una API de Kobana.
expObligatoria. Un token sin expiración se rechaza.
orgLa organización en nombre de la cual actúa el token, y es obligatoria. Es ella la que delimita toda respuesta. Un token sin org se rechaza, en lugar de caer en el sub.
subLa persona, nunca la organización. Va a la auditoría.
emailCuando está presente, vincula el token a una persona de la organización, y también vale su rol. Un token de integración, sin persona, vale solo por los alcances.
jtiId único del token, usado en la revocación y en el límite de solicitudes.
scopeAlcances separados por espacio (abajo).

:::info Verifica el entorno El aud de producción no vale en staging, y viceversa. No reutilices el token entre entornos. :::

Probar el token​

GET /v1/me dice quién está detrás del token. Es la única ruta sin verificación de alcance, justamente para que pruebes un token nuevo.

Alcances​

Los alcances tienen dos ejes ortogonales: el recurso, siempre con el prefijo de la app (kadu/tasks), y el nivel de acceso, un alcance global sin prefijo: read, write, delete, import, export o all. Un recurso sin verbo significa lectura. Todo lo demás exige los dos: el alcance del recurso y el nivel.

El recurso de una ruta es el primer segmento después de /v1: /v1/executions/{id}/logs es del recurso executions.

AlcanceConcede lectura de
kadu/organizationsla organización del token
kadu/workspacesworkspaces
kadu/activitiesactividades
kadu/taskstareas, la verificación previa del lanzamiento y el endpoint de lanzamiento (el lanzamiento en sí es write)
kadu/executionsejecuciones, logs, eventos, pendientes y la búsqueda (cancelar y continuar son write)
kadu/todospendientes (resolver es write)
kadu/filesarchivos de entrada y de salida
kadu/environmentsentornos
kadu/secretssecrets: clave, notas y metadatos. El valor nunca lo devuelve ningún endpoint
kadu/schedulesprogramaciones
kadu/memoriesmemorias
kadu/webhookswebhooks (rotar el signing secret es write)
kadu/webhook_deliveriesentregas de webhook (reenviar es write)
kadu/repositoryel Playbook (sincronizar es write)
kadu/usageuso y costo
kadu/usersmiembros de la organización
kadu/membershipsvínculos de personas con la organización
kadu/rolesroles
kadu/system_eventseventos de sistema
kadu/allcomodín del eje de recurso: lee todos los recursos anteriores y no concede ningún nivel
Nivel de accesoConcede
readLectura. El alcance del recurso ya la implica; en un token sin alcance kadu/…, lee todos los recursos
writeTodo POST, PUT y PATCH en los recursos que el token lleva: crear, modificar, lanzar, cancelar, sincronizar, rotar secreto, reenviar entrega. No elimina
deleteTodo DELETE en los recursos que el token lleva, y nada más
importImportación masiva. Ningún endpoint de esta API importa en masa hoy
exportExportación masiva. Ningún endpoint de esta API exporta en masa hoy
allTodos los niveles anteriores

Qué nivel exige cada endpoint​

Un nivel por solicitud, dado por el método HTTP. Ningún nivel sustituye a otro: write no elimina, y delete no escribe.

SolicitudExige
GETEl alcance del recurso (kadu/tasks)
POST, PUT, PATCHEl alcance del recurso + write (kadu/tasks write)
DELETEEl alcance del recurso + delete (kadu/tasks delete); write no basta
GET /v1/meCualquier token válido, sin verificación de alcance

Toda eliminación es un DELETE (el recurso recibe deleted_at) y todo DELETE es una eliminación.

Tres ejemplos: kadu/executions lee ejecuciones y no cancela; kadu/tasks write también crea, modifica y lanza tareas, pero no las elimina; kadu/tasks write delete hace las tres cosas. Ninguno de ellos alcanza los secrets.

La forma granular kadu/tasks:write (o kadu/tasks:delete) es una excepción de la gramática, no el formato estándar: satisface por sí sola los dos ejes de ese recurso y existe para "lee un recurso, escribe otro". kadu/* es un comodín de registro y nunca se emite en un token: la comparación aquí es siempre literal.

Un token que lleva alcances kadu/… queda limitado a los recursos que ellos nombran, y los niveles actúan solo dentro de ellos. Un token sin alcances kadu/… queda limitado por el nivel: lee con read, write o all; escribe con write o all; elimina con delete o all. Un token sin ninguno de los dos no alcanza nada más allá de GET /v1/me.

Un alcance insuficiente responde 403 INSUFFICIENT_SCOPE, con los niveles que bastarían en details.required y los alcances del token en details.granted.

Pipeline de validación​

En este orden:

  1. Extrae Authorization: Bearer <jwt>.
  2. Verifica la firma con la clave pública del Authorization Server, aceptando solo RS256 y typ: at+jwt.
  3. Valida iss, que el aud contiene esta API, y que exp está presente y en el futuro.
  4. Comprueba si el jti fue revocado.
  5. Resuelve la organización por el org.
  6. Aplica el límite de solicitudes del token.
  7. Verifica el alcance contra el endpoint.
  8. Con una persona en el token, verifica su rol en la organización (Permisos).

Aislamiento entre organizaciones​

Toda consulta se filtra por la organización del org. No hay forma de apuntar a otra organización por el cuerpo o por el query. Un recurso de otra organización responde 404 NOT_FOUND, y no 403, para no revelar que existe.

Modos de falla​

HTTPcodeCausa
401INVALID_TOKENJWT ausente, mal formado, con firma inválida o con otro typ
401INVALID_AUDIENCEaud de otra app o de otro entorno
401INVALID_ISSUERemisor distinto del Authorization Server de Kobana
401TOKEN_EXPIREDexp en el pasado
401TOKEN_REVOKEDjti revocado
403UNKNOWN_ORGANIZATIONel org apunta a una organización que Kadu no conoce
403INSUFFICIENT_SCOPEtoken sin el alcance exigido
403USER_PERMISSION_DENIED, NOT_A_MEMBERel rol de la persona del token no lo permite, o ella no pertenece a la organización (Permisos)
429RATE_LIMITEDlímite del token excedido (Límites)
503AS_UNAVAILABLEno se pudieron obtener las claves de firma del Authorization Server. La verificación en sí es local, así que esto solo ocurre en los momentos listados en Cuándo se llama al Authorization Server. No es un problema de tu token: intenta de nuevo después del Retry-After. Es 5xx a propósito: un 401 te mandaría a depurar una credencial buena durante una indisponibilidad nuestra.

Mira Errores para el envelope completo.

Buenas prácticas​

  • Nunca versiones un token en git. Usa variables de entorno o una bóveda (AWS Secrets Manager, Vault…).
  • Usa un token por integración: se puede revocar uno sin tumbar los demás.
  • Pide los alcances mínimos: kadu/executions para quien solo sigue, kadu/tasks write para quien lanza, delete solo para quien elimina.
  • Revoca de inmediato cualquier token filtrado.