Construir aplicaciones sanitarias sobre un servidor FHIR se ha convertido en una práctica habitual. Los servidores FHIR proporcionan almacenamiento estandarizado y APIs para recursos clínicos, lo que permite a los desarrolladores centrarse en crear funcionalidades en lugar de gestionar la infraestructura de datos sanitarios. Sin embargo, esto plantea una pregunta importante: ¿cómo garantizar que los distintos usuarios vean únicamente los datos que tienen permitido ver?
Por ejemplo, un médico debería tener acceso completo a las observaciones del paciente — tanto los resultados de laboratorio como los signos vitales. Un técnico de laboratorio, por su parte, solo debería ver los resultados de laboratorio finalizados que sean relevantes para su trabajo. Implementar este tipo de control de acceso granular requiere tradicionalmente una lógica compleja a nivel de aplicación, reglas de autorización personalizadas y pruebas exhaustivas.
Existe una forma mejor: un enfoque basado en estándares que aprovecha su proveedor de identidad existente y no requiere ningún código de autorización personalizado en su aplicación.
En esta entrada, exploraremos cómo implementar un control de acceso basado en roles (RBAC) sofisticado para recursos FHIR utilizando roles de Keycloak (una solución de gestión de identidad y acceso de código abierto) mapeados a ámbitos de SMART on FHIR V2, con aplicación automática por parte de Aidbox. ¿Lo mejor? El mismo endpoint de API devuelve datos diferentes según quién realiza la consulta — de forma completamente transparente.
El problema: un endpoint, múltiples niveles de acceso
Imagine que está construyendo una aplicación sanitaria sobre el servidor FHIR con dos tipos de usuarios:
Dra. Sara (médico)
- Necesita ver todas las observaciones del paciente
- Revisa tanto los resultados de laboratorio como los signos vitales
- Toma decisiones clínicas basándose en los datos completos del paciente
Miguel (técnico de laboratorio)
- Trabaja únicamente con resultados de laboratorio finalizados
- No debería ver los signos vitales ni los datos de laboratorio preliminares
- Necesita un acceso limitado a su función laboral específica
Ambos usuarios llaman al mismo endpoint de la API: GET /fhir/Observation. Pero deberían ver resultados completamente diferentes.
Tradicionalmente, los desarrolladores resolverían esto añadiendo:
- Middleware personalizado para verificar los roles del usuario
- Filtros de consulta complejos en el código de la aplicación
- Endpoints de API separados o parámetros distintos para diferentes tipos de usuarios
- Pruebas unitarias exhaustivas para cada escenario de autorización
- Problemas de mantenimiento a medida que evolucionan los requisitos
Este enfoque funciona, pero es difícil de mantener y propenso a errores conforme los requisitos evolucionan. Existe una forma mejor.
La solución: los ámbitos SMART se combinan con los roles de Keycloak
SMART on FHIR V2 introduce un concepto poderoso: ámbitos con parámetros de consulta. En lugar de otorgar simplemente un acceso amplio como «este usuario puede leer Observations», puede especificar reglas exactas, como:
user/Observation.rs?category=laboratory&status=final
Este ámbito significa: «El usuario puede leer y buscar Observations, pero solo observaciones de laboratorio con estado final».
Combinando esto con el sistema de roles compuestos de Keycloak, podemos:
- Definir permisos granulares como roles básicos de Keycloak (cada uno representando un ámbito SMART)
- Agruparlos en funciones laborales mediante roles compuestos (como «physician» o «lab_technician»)
- Resolver automáticamente los roles compuestos en ámbitos SMART dentro del token de acceso
- Dejar que Aidbox aplique las reglas automáticamente — sin necesidad de código personalizado
Así funciona el flujo:
User Login → Keycloak resolves roles → Token with SMART scopes →
Aidbox validates token → Automatic data filtering → Correct results
Implementación: construcción de la estructura de roles
Paso 1: definir los roles básicos (ámbitos SMART granulares)
En Keycloak, creamos roles básicos que se mapean directamente a ámbitos de SMART on FHIR V2:
Roles básicos:
user/Patient.rs- Leer y buscar datos de pacientesuser/Encounter.rs- Leer y buscar encuentrosuser/Observation.rs- Leer y buscar TODAS las observacionesuser/Observation.rs?category=laboratory&status=final- Leer y buscar ÚNICAMENTE resultados de laboratorio finalizados
Estos roles básicos son los bloques de construcción. Cada uno representa un permiso específico con restricciones opcionales de parámetros de consulta.
Paso 2: crear roles compuestos (funciones laborales)
A continuación, combine los roles básicos en roles compuestos que reflejen las funciones laborales reales:
Rol de médico (acceso clínico completo):
user/Patient.rsuser/Encounter.rsuser/Observation.rs
Rol de técnico de laboratorio (limitado a resultados de laboratorio):
user/Patient.rsuser/Observation.rs?category=laboratory&status=final
Observe que el rol de técnico de laboratorio utiliza el ámbito de Observation restringido — impidiendo el acceso a los signos vitales o a los resultados preliminares.
Paso 3: configurar el mapeador de tokens
Aquí es donde ocurre la magia. Keycloak convierte los roles en tokens de acceso. El token es un archivo pequeño y seguro (JSON Web Token — JWT) que viaja con cada solicitud de API y le indica a Aidbox qué tiene permitido hacer el usuario. Necesitamos que Keycloak:
- Resuelva los roles compuestos (p. ej., «physician») en sus roles básicos constituyentes
- Incluya esos roles básicos en el claim
scopedel token como ámbitos SMART - Añada el claim
atv: "2"para indicar que hay ámbitos SMART on FHIR en el token que deben procesarse
Esto lo conseguimos mediante un mapeador de protocolo basado en scripts personalizado. Cuando un técnico de laboratorio inicia sesión, su token de acceso tiene este aspecto:
{
"sub": "lab_technician",
"scope": "user/Patient.rs
user/Observation.rs?category=laboratory&status=final",
"atv": "2"
}
Paso 4: configurar Aidbox para la aplicación automática
Aquí está la parte más elegante: Aidbox aplica automáticamente las reglas de acceso definidas en el token. Todo lo que necesita es:
- TokenIntrospector - Verifica que el token es válido y fue emitido por su instancia de Keycloak:
{
"resourceType": "TokenIntrospector",
"jwt": {
"iss": "http://localhost:8888/realms/master"
},
"type": "jwt",
"jwks_uri":
"http://keycloak:8888/realms/master/protocol/openid-connect/certs",
"id": "external-auth-server",
"resourceType": "TokenIntrospector"
}
- AccessPolicy — Permite las solicitudes con tokens validados:
{
"resourceType": "AccessPolicy",
"id": "keycloak-access-policy",
"engine": "matcho",
"matcho": {
"jwt": {
"iss": "http://localhost:8888/realms/master"
}
}
}
Eso es todo. Cuando Aidbox recibe una solicitud con un token que contiene atv: "2" y ámbitos SMART, automáticamente:
- Analiza los ámbitos para determinar los tipos de recursos permitidos
- Aplica los filtros de parámetros de consulta derivados de los ámbitos
- Devuelve únicamente los datos que coinciden con las restricciones del ámbito
- Rechaza las solicitudes de tipos de recursos no autorizados
Sin código de autorización personalizado. Sin lógica de control de acceso compleja. Simplemente funciona.
Viéndolo en acción
Veamos ambos escenarios de usuario para comprobar cómo la misma llamada a la API devuelve resultados diferentes. Imagine que ha configurado su sistema con Aidbox conectado a Keycloak, y que tanto la Dra. Sara (la médico) como Miguel (el técnico de laboratorio) utilizan la misma aplicación.
En el sistema existen dos recursos Observation:
- Hemoglobina — una observación de laboratorio con estado «final»
- Tensión arterial — una observación de signos vitales
Ambos usuarios accederán al mismo endpoint: GET /fhir/Observation
Pero Aidbox devolverá respuestas diferentes según quién realice la solicitud.
Prueba 1: acceso del médico (acceso completo)
Credenciales de inicio de sesión:
Username: physician
Password: password
Llamada a la API:
GET /fhir/Observation
Authorization: Bearer <physician_token>
Ámbitos del token:
user/Patient.rs user/Encounter.rs user/Observation.rs
Resultado: El médico ve ambas observaciones:
- Hemoglobina (laboratorio, final)
- Tensión arterial (signos vitales)
El ámbito user/Observation.rs concede acceso sin restricciones a todos los recursos Observation.
Prueba 2: acceso del técnico de laboratorio (acceso restringido)
Credenciales de inicio de sesión:
Username: lab_technician
Password: password
Llamada a la API:
GET /fhir/Observation
Authorization: Bearer <lab_technician_token>
Ámbitos del token:
user/Patient.rs
user/Observation.rs?category=laboratory&status=final
Resultado: El técnico de laboratorio ve únicamente una observación:
- Hemoglobina (laboratorio, final)
La observación de tensión arterial queda filtrada porque no cumple los requisitos del ámbito:
- Su categoría es «vital-signs» (no «laboratory»)
- El ámbito exige explícitamente
category=laboratory&status=final
El mismo endpoint, el mismo código, resultados diferentes según quién realiza la consulta. Sin necesidad de lógica de filtrado personalizada.
Pruébelo usted mismo
¿Desea verlo en acción? El ejemplo completo está listo para ejecutarse con Docker.
Requisitos previos: Docker y Docker Compose instalados
Inicio rápido:
- Clone el repositorio y navegue al ejemplo:
cd aidbox-features/smart-keycloak-roles
- Inicie todos los servicios:
docker compose up --build
-
Inicialice Aidbox: Navegue a http://localhost:8080 y complete la inicialización de Aidbox.
-
Abra la aplicación de demostración: Navegue a http://localhost:3000.
-
Pruebe ambos roles de usuario:
Inicie sesión como physician/password — vea todas las observaciones
- Haga clic en «Start Over» e inicie sesión como
lab_technician/password— vea solo los resultados de laboratorio
La aplicación de demostración muestra en paralelo a qué puede acceder cada usuario, haciendo que las diferencias de control de acceso sean inmediatamente visibles.
Conclusiones clave
Este enfoque ofrece varios beneficios significativos:
1. Cero código de autorización personalizado Su aplicación no necesita entender los roles ni implementar lógica de filtrado. Aidbox lo gestiona automáticamente basándose en los ámbitos SMART.
2. Control de acceso centralizado Todas las definiciones de roles residen en su proveedor de identidad (Keycloak). Cambie los permisos de un rol en un único lugar y se aplicará en todas partes.
3. Basado en estándares Construido sobre SMART on FHIR V2, un estándar consolidado de interoperabilidad sanitaria. Sin soluciones propietarias ni dependencia de un proveedor específico.
4. Control granular Las restricciones de parámetros de consulta (?category=laboratory&status=final) permiten un control de acceso preciso sin reglas personalizadas complejas.
5. Fácil de extender ¿Necesita un nuevo rol? Cree un rol compuesto en Keycloak combinando los roles básicos adecuados. No se requieren cambios en el código.
Más información:
- Ámbitos SMART on FHIR en Aidbox
- Control de acceso basado en roles de Keycloak
- Marco SMART App Launch
Conclusión
El control de acceso granular para recursos FHIR no tiene por qué ser complicado. Combinando los ámbitos de SMART on FHIR V2, el sistema de roles compuestos de Keycloak y la aplicación automática de ámbitos de Aidbox, puede implementar un RBAC sofisticado sin escribir código de autorización personalizado.
El resultado: aplicaciones más seguras, mantenimiento más sencillo y una mejor alineación con los estándares de interoperabilidad sanitaria.
¿Listo para implementar el control de acceso basado en roles en su aplicación FHIR? Comience con el repositorio de ejemplo y personalice los roles para su caso de uso específico.





