Este blog fue publicado primero en SAP Community (inglés): https://community.sap.com/t5/technology-blog-posts-by-sap/dynamic-authorisation-with-user-attributes-in-sap-cap-and-ams/ba-p/14388853
Traducido con IA y revisado por mí.
Introducción: El Desafío de Negocio
Tu empresa acaba de adquirir una nueva unidad de negocio. De la noche a la mañana, 500 usuarios necesitan acceso a datos de ventas, pero solo para su división. El control de acceso tradicional basado en roles significa crear roles como Sales_Manager_EMEA, Sales_Manager_APAC, Sales_Manager_LATAM, y un sinfín de variaciones. A medida que se multiplican las dimensiones (división, región, departamento, centro de costos), te enfrentas a una explosión de roles—cientos o miles de roles que no escalan.
Hay una mejor manera. Con Authorization Management Service (AMS) y Cloud Identity Services, defines una única política con una restricción:
Dar acceso de READ donde division = $user.division
El $user.division se obtiene del perfil del usuario autenticado. Los administradores de autorización gestionan las políticas a través de la consola de Cloud Identity Services—sin cambios de código, sin despliegues. Cuando un gerente de ventas se transfiere de EMEA a APAC, RRHH actualiza el atributo division en el sistema de identidad corporativo, y el acceso se ajusta automáticamente en todas las aplicaciones. No se requiere reasignación de roles.
Entendiendo la Base Técnica
Basándonos en blogs recientes de SAP Community sobre AMS (aquí y aquí), enfoquémonos en la autorización basada en atributos.
La arquitectura:
- Cloud Identity Services autentica usuarios y almacena atributos (división, centro de costos, región)
- AMS gestiona y evalúa políticas de autorización en tiempo de ejecución
- Aplicaciones CAP aplican la autorización usando atributos de usuario para filtrado dinámico
RBAC tradicional vs. basado en atributos:
- Tradicional:
Sales_Manager_EMEA,Sales_Manager_APAC,Sales_Manager_LATAM→ no escala - Basado en atributos:
where division = $user.division→ dinámico, se adapta automáticamente
El flujo en tiempo de ejecución:
- El usuario inicia sesión a través del IdP corporativo (ej., Microsoft Entra ID)
- IAS devuelve un JWT con atributos personalizados (
division,warehouse, etc.) - CAP extrae los atributos y los pone a disposición de AMS
- Las consultas a la base de datos se filtran automáticamente según los atributos del usuario
- El usuario solo ve los datos que está autorizado a ver
Este enfoque ofrece beneficios de negocio medibles: reducción significativa de solicitudes de “cambio de acceso” a los equipos de IT, y una única fuente de verdad en IAS para decisiones de acceso con registro de auditoría completo para cumplimiento.
Guía de Implementación: La Imagen Completa
Veamos la implementación paso a paso:
- Configuración IAS: Configurar atributos personalizados en Cloud Identity Services
- Schema AMS: Declarar atributos de usuario disponibles en el schema
- Integración CAP Server: Extraer atributos del JWT y mapearlos al objeto de usuario CAP & AMS
- Políticas de Autorización: Crear políticas en Cloud Identity Services con restricciones basadas en atributos
Paso 1: Configurar Atributos Personalizados en Cloud Identity Services
Contexto de negocio: Tu organización estructura el acceso por división y almacén. Los usuarios solo deben acceder a datos relacionados con su división y ubicación de almacén asignadas.
Pasos de configuración:
- Navega a IAS Admin Console → Applications → Tu Aplicación
- En la pestaña Trust → Attributes, añade nuevos atributos:
- Name:
division - Source: Cloud Identity Services o el proveedor de identidad corporativo
- Name:
Haz lo mismo para el atributo warehouse.
Ejemplo de atributos de usuario:
- [email protected] → division: “LOG”, warehouse: “MAD”
- [email protected] → division: “RET”, warehouse: “BCN”
Verificar el atributo en JWT:
Después de la autenticación, decodifica el token JWT (ej., en jwt.io) y encontrarás:
{
"sub": "[email protected]",
"division": "LOG",
"warehouse": "MAD"
}
Esto confirma que el atributo personalizado está fluyendo desde IAS hacia el token de autenticación de tu aplicación.
Paso 2: Definir Atributos de Usuario en el Schema AMS
Antes de usar $user.division o $user.warehouse en políticas, debes declararlo en el schema AMS. Esto le dice al runtime de AMS qué atributos están disponibles para la evaluación de políticas.
Edita ams/dcl/schema.dcl:
SCHEMA {
"$user": {
groups: String,
division: String,
warehouse: String
}
}
Qué hace esto:
- Declara la estructura de atributos de usuario disponibles en expresiones de política
divisionywarehouseahora son reconocidos por el compilador DCL- Habilita autocompletado y validación en archivos de política
Paso 3: Mapear Atributos del Token JWT a la Entrada AMS
La pieza crítica: AMS necesita extraer atributos personalizados del token JWT y ponerlos a disposición para la evaluación de políticas. Aquí es donde conectas los atributos IAS al contexto de autorización CAP/AMS.
Crea un proveedor de autenticación personalizado en srv/server.js:
const cds = require('@sap/cds');
const { amsCapPluginRuntime, IdentityServiceAuthProvider } = require("@sap/ams");
class CustomAuthProvider extends IdentityServiceAuthProvider {
/**
* @param {import("@sap/xssec").IdentityServiceSecurityContext} securityContext
*/
getInput(securityContext) {
const defaultInput = super.getInput(securityContext);
// Extraer atributo personalizado del payload del token JWT
const division = securityContext.token.payload.division;
if (division) {
defaultInput["$user.division"] = division;
}
// Puedes añadir más atributos aquí
const warehouse = securityContext.token.payload.warehouse;
if (warehouse) {
defaultInput["$user.warehouse"] = warehouse;
}
return defaultInput;
}
}
// Registrar el proveedor de autenticación personalizado
amsCapPluginRuntime.authProvider.xssecAuthProvider = new CustomAuthProvider(amsCapPluginRuntime.ams);
Qué hace esto:
- Extiende el
IdentityServiceAuthProviderde AMS para interceptar el procesamiento del token - Extrae
divisionywarehousedel payload del JWT (ej.:securityContext.token.payload.division) - Lo mapea a
$user.divisionpara usar en políticas DCL y restricciones CAP - Los atributos ahora están disponibles en toda tu lógica de autorización
Verificación: Puedes registrar el atributo para confirmar que es accesible:
// En srv/service.js
this.before('READ', 'Orders', async (req) => {
console.log('User division:', req.user.attr.division || 'not set');
console.log('User warehouse:', req.user.attr.warehouse || 'not set');
});
Paso 4: Crear Políticas de Autorización con Restricciones de Atributos de Usuario
Ahora que los atributos fluyen desde IAS → JWT → contexto CAP/AMS, puedes crear políticas de autorización que los referencien.
Enfoque de Políticas de Autorización en Cloud Identity Services
Navega a Cloud Identity Services → Applications → Tu Aplicación → Authorization Policies para crear políticas con restricciones basadas en atributos.
Creando una política DivisionReader:
- En la consola de administración de Cloud Identity Services, abre tu aplicación
- Navega a la pestaña Authorization Policies
- Crea una nueva restricción (ej.,
ReaderByDivision) basada en una restricción existente (Readeren el ejemplo abajo) - Añade una Restriction:
division = $user.division - Asigna usuarios o grupos a esta política
Qué sucede en tiempo de ejecución:
- Un usuario con
division: "LOG"solicitaGET /orders - AMS evalúa la política
DivisionReadercon$user.division = "LOG" - La restricción
division = $user.divisionse convierte endivision = "LOG" - CAP inyecta
WHERE division = 'LOG'en la consulta SQL - El usuario solo ve pedidos para la división Logistics & Distribution
- La misma consulta ejecutada por un usuario con
division: "RET"devuelve automáticamente solo pedidos de Retail Operations
Enfoque de anotaciones de restricción en servicio CAP
Para desarrolladores que prefieren definir reglas de autorización en código (especialmente durante el desarrollo), también puedes referenciar $user.division directamente en definiciones de servicio CAP:
service OrderService {
@restrict: [{
grant: ['READ'],
to: ['ReadOrders'],
where: 'division = $user.division'
}]
entity Orders as projection on data.Orders;
@restrict: [{
grant: ['READ'],
to: ['ReadInventory'],
where: 'warehouse = $user.warehouse'
}]
entity Inventory as projection on data.Inventory;
}
Beneficios y Separación de Responsabilidades
Este enfoque de autorización basada en atributos ofrece ventajas concretas a través de una clara separación de responsabilidades:
Para Desarrolladores: Construir la base técnica una vez
- Configurar la extracción de atributos de tokens JWT
- Declarar atributos disponibles en el schema AMS
- Desplegar la aplicación
Para Administradores de Autorización: Gestionar el acceso a través de la interfaz
- Crear políticas en Cloud Identity Services
- Definir restricciones basadas en atributos sin programar
- Modificar políticas según cambien las necesidades organizacionales—sin despliegues requeridos
Para Equipos de RRHH/Identidad: Mantener atributos de usuario como única fuente de verdad
- Actualizar perfiles de usuario cuando los empleados cambian de rol o división
- Los atributos se sincronizan automáticamente con Cloud Identity Services mediante Identity Provisioning
- El acceso se ajusta en todas las aplicaciones integradas
Referencias
Consulta el repositorio ams-samples-node. Guía del Desarrollador CAP: Asignación de Roles con AMS Documentación AMS