Problema y escenario aplicable
Un servicio de documentos B2B utiliza una base de datos compartida. Un usuario puede pertenecer a varios inquilinos y tener un rol viewer, editor o admin en cada uno de ellos. Un documento también se puede compartir directamente con un miembro del mismo inquilino. El servicio expone APIs de lectura, actualización y eliminación de un solo documento, exportación masiva y generación asíncrona de archivos comprimidos. La validación de firma, expiración y audiencia de JWT ya funciona, pero el código heredado carga globalmente un documento mediante un document_id proporcionado por el cliente y luego solo verifica si la solicitud está autenticada.
Un atacante obtiene un UUID válido de una entrada de auditoría, un enlace compartido u otra API y reemplaza su propio ID de documento con él. El UUID es difícil de enumerar, pero el servidor aún revelará o modificará el documento a menos que verifique si el sujeto actual puede realizar esta acción sobre este recurso en el inquilino activo. OWASP llama a esto Broken Object Level Authorization (BOLA); el material común de seguridad web también utiliza Insecure Direct Object Reference (IDOR). Un identificador de objeto puede aparecer en una ruta, parámetro de consulta, encabezado, cuerpo JSON, variable de GraphQL, nombre de archivo o lista masiva.
Dos páginas públicas de preparación para entrevistas de API piden explícitamente a los candidatos que expliquen o prueben IDOR. Una discusión pública de enero de 2026 pregunta si cifrar los IDs de objeto soluciona IDOR, lo que demuestra que "ocultar el ID" sigue siendo un error conceptual práctico que los candidatos deben analizar. OWASP API Security Top 10 API1:2023 y un estudio empírico público de 2026 proporcionan contexto técnico y de riesgo adicional. Esta evidencia respalda la representatividad; no establece la pregunta o la frecuencia de entrevistas de una empresa en particular.
Esta es una pregunta de backend porque la tarea central es llevar la identidad autenticada, las relaciones de inquilinos, los atributos de recursos y las acciones hacia un límite de autorización a través de APIs, acceso a datos, transacciones, cachés y workers. El artículo existente de OAuth cubre flujos de identidad y código de autorización, la inyección SQL cubre la estructura de consultas y SSRF cubre la autorización de destinos salientes. Ninguno responde al acceso a nivel de objeto.
Qué está evaluando el entrevistador
La primera señal es la terminología precisa. La autenticación responde a "¿quién está llamando?". La autorización a nivel de objeto responde a "¿puede este sujeto realizar esta acción sobre este objeto ahora?". Un usuario que puede llamar a PATCH /documents/{id} pero no puede modificar el documento de otro inquilino expone BOLA. Un miembro regular que alcanza una función de eliminación masiva solo para administradores está más cerca de Broken Function Level Authorization. Permitir que un usuario actualice la propiedad protegida owner_id en su propio documento es un problema de autorización de propiedades de objeto.
La segunda señal es un modelo de autorización completo. Comparar únicamente document.owner_id == user.id pasa por alto los roles de inquilino, el uso compartido en equipo, los derechos de solo lectura, la revocación y el acceso temporal de soporte. Una respuesta sólida hace explícita una decisión:
allow(subject, tenant, action, resource, context) -> decision + reasonEl inquilino proviene de una membresía verificada. Las acciones distinguen read, update, delete, share y export. Los atributos del recurso incluyen inquilino, estado, propietario y relaciones de uso compartido. El contexto puede contener una concesión temporal de soporte y la versión de la política. Si ninguna regla de permiso coincide, la decisión es denegar.
La tercera señal es hacer cumplir el límite donde se seleccionan y modifican los datos. Cargar globalmente con findById(id) y depender de que un controlador agregue una verificación crea omisiones a través de endpoints masivos, workers, cachés y nuevas rutas. La ruta recomendada consulta a partir de un conjunto de datos autorizados. Una mutación lleva condiciones de alcance y versión dentro de la misma sentencia o transacción y verifica el conteo de filas afectadas.
La cuarta señal es comprender los límites de la defensa en profundidad. Los UUIDs aleatorios, las respuestas 404, los límites de tasa y Row-Level Security (RLS) de PostgreSQL ayudan, pero ninguno reemplaza la autorización comercial completa. La documentación de PostgreSQL 18 también establece que los superusuarios, los roles BYPASSRLS y normalmente los propietarios de tablas omiten RLS. La habilitación de políticas, los roles de conexión y el contexto de inquilino por solicitud deben verificarse.
La señal final es demostrar que cada ruta deniega el acceso entre objetos. Un GET exitoso para el propio documento es una prueba funcional. Las pruebas de seguridad utilizan múltiples cuentas, inquilinos, roles e IDs de objetos foráneos válidos conocidos. Cubren lecturas, escrituras, eliminaciones, operaciones masivas, exportaciones, descargas, GraphQL, aciertos de caché y ejecución de workers, y afirman que no ocurrió ningún efecto secundario en la base de datos, almacenamiento de objetos o mensajería.
Preguntas para aclarar antes de responder
- ¿Cómo se selecciona un inquilino? Un usuario puede cambiar de inquilino activo, pero un
X-Tenant-IDdel cliente expresa solo una
elección. El servidor debe revalidar la membresía para la identidad autenticada en lugar de confiar en el encabezado.
- ¿Qué determina el permiso? ¿Es solo un rol de inquilino o también la propiedad, la membresía de equipo, el uso compartido directo,
el estado del documento y las concesiones temporales de soporte? Las reglas más dinámicas necesitan una política central y motivos de auditoría estables.
- ¿Qué acciones requieren un permiso por separado? La lectura no incluye automáticamente la descarga, exportación, uso compartido
o eliminación. Una operación masiva aplica la misma decisión a nivel de acción a cada objeto.
- ¿La denegación debe devolver 403 o 404? Si un ID de objeto externo no debe revelar la existencia, faltante e invisible
pueden compartir un contrato 404. Un objeto visible del mismo inquilino con permisos de acción insuficientes puede devolver 403 bajo el contrato del producto. Ninguna de las respuestas puede exponer diferencias sensibles.
- ¿Los trabajos utilizan el permiso actual o una instantánea del momento de envío? Este diseño verifica al encolar y nuevamente en
la ejecución, de modo que una exportación en cola se detiene después de la revocación. Si se requieren derechos de instantánea inmutables, modela una concesión explícita, con alcance y que expire.
- ¿El personal de soporte puede acceder a los inquilinos? Si es así, utiliza una ruta separada just-in-time que requiera un ticket, motivo,
aprobación, expiración y auditoría completa. No le des a la conexión general de la aplicación un interruptor permanente de administrador global.
- ¿Se utilizará PostgreSQL RLS? Esta respuesta utiliza el alcance de inquilino a nivel de aplicación como control primario y RLS
contra omisiones. Otras combinaciones son válidas si los roles de base de datos, el contexto del pool, las migraciones y los workers mantienen sus garantías.
Marco de respuesta de 30 segundos
“Expresaría la autorización como subject + tenant + action + resource + context y denegaría por defecto. El middleware de autenticación establece únicamente el sujeto. El inquilino activo debe provenir de una membresía verificada. La capa de datos no expone una búsqueda de documentos sin alcance: las lecturas utilizan tenant_id + document_id, seguido de la política de acción sobre rol, propietario y uso compartido. Las actualizaciones y eliminaciones llevan esas condiciones a la misma sentencia o transacción; cero filas afectadas se maneja como invisible. Un UUID reduce la enumeración pero nunca reemplaza el control de acceso.
Las rutas masivas, de caché, descarga y exportación utilizan las mismas reglas. Las claves de caché incluyen el inquilino; los enlaces de capacidad vinculan recurso, acción y expiración; y un trabajo verifica al encolar y en la ejecución. PostgreSQL RLS puede respaldar errores, siempre que el rol de la aplicación no pueda eludirlo y se pruebe el cambio de inquilino en el pool. Finalmente, sustituiría IDs en rutas, cuerpos y listas masivas a través de una matriz de dos inquilinos y múltiples roles, y afirmaría que ninguna respuesta, dato, archivo o mensaje cruce el límite del inquilino.”
Análisis detallado paso a paso
Paso 1: Inventariar las tuplas de autorización y los puntos de entrada de objetos
Escribe las reglas de negocio como una matriz antes de dispersar nombres de roles a través de los controladores:
| Relación del sujeto | read | update | delete | share | export |
|---|---|---|---|---|---|
Inquilino viewer, no compartido | Denegar | Denegar | Denegar | Denegar | Denegar |
Inquilino viewer, compartido directamente | Permitir | Denegar | Denegar | Denegar | Permitir o específico del producto |
Inquilino editor | Permitir | Permitir | Denegar | Específico de política | Permitir |
| Propietario del documento | Permitir | Permitir | Específico de política | Permitir | Permitir |
Inquilino admin | Permitir | Permitir | Permitir | Permitir | Permitir |
Esta tabla es una suposición del escenario. Los responsables de producto y seguridad deben aprobar la matriz real y justificar cada regla de permiso. Denegar por defecto significa que una nueva acción, un rol desconocido, un contexto de inquilino faltante o un error de política fallan cerrados.
Luego, inventaría los puntos de entrada de objetos: parámetros de ruta, filtros de consulta, cuerpos, arreglos masivos, nodos de GraphQL, tokens de uso compartido, claves de almacén de objetos, claves de caché, mensajes y trabajos. La definición de OWASP no requiere un ID secuencial. Los UUIDs, nombres de archivo y cadenas genéricas también son referencias. Para cada entrada, registra el origen del sujeto, el origen del inquilino, la acción, el método de búsqueda y el efecto secundario final. Ese proceso expone las omisiones.
Paso 2: Derivar un inquilino de confianza a partir de la identidad autenticada
Un JWT verificado proporciona un user_id estable; no hace que cada reclamo de rol de larga duración sea actual ni hace que un ID de inquilino proporcionado por separado sea confiable. Cuando un usuario elige tenant_b, el servidor resuelve una membresía actual y crea un AuthContext con alcance de solicitud:
AuthContext {
user_id,
tenant_id,
membership_id,
roles,
policy_version,
support_grant_id?
}El middleware garantiza que el contexto exista; la política de dominio aún decide las acciones sobre los recursos. Los pools de conexiones, consumidores y solicitudes concurrentes no deben compartir un inquilino global mutable. Establece el contexto de base de datos dentro de cada transacción y límpialo antes de devolver la conexión para que una solicitud no pueda heredar el inquilino anterior.
Paso 3: Poner el alcance del inquilino en las consultas y restricciones de datos
La consulta no segura carga globalmente:
SELECT * FROM documents WHERE id = :document_id;El límite básico incluye el inquilino de confianza:
SELECT *
FROM documents
WHERE tenant_id = :auth_tenant_id
AND id = :document_id;Si el uso compartido directo determina la visibilidad, haz un join con la relación de uso compartido dentro de la consulta con alcance o carga solo el recurso del mismo inquilino y pásalo a un motor de políticas central. Nunca copies tenant_id del cuerpo a este predicado. Externamente, cero filas pueden producir consistentemente 404 para que "existe en otro inquilino" y "no existe" no sean distinguibles.
El diseño del esquema dificulta los errores. Las tablas de uso compartido, versiones, adjuntos y elementos de exportación llevan todas tenant_id. Donde sea apropiado, las claves únicas y foráneas utilizan (tenant_id, resource_id) para que un hijo en un inquilino no pueda apuntar a un padre en otro. La autorización en la aplicación sigue siendo necesaria; las restricciones rechazan relaciones accidentales entre inquilinos en el momento de la escritura.
Paso 4: Mantener la autorización y la mutación en un solo límite de corrección
"Cargar, autorizar en el código de la aplicación, actualizar después" tiene una condición de carrera time-of-check/time-of-use. El permiso o el estado del documento pueden cambiar entre los pasos. Una política simple puede usar una actualización condicional:
UPDATE documents
SET title = :title, version = version + 1
WHERE tenant_id = :auth_tenant_id
AND id = :document_id
AND version = :expected_version
AND (
owner_id = :user_id
OR :can_edit_tenant_documents
);Cuando se ven afectadas cero filas, no publiques un mensaje, no escribas una entrada de auditoría exitosa ni actualices una caché. El uso compartido complejo puede bloquear versiones relevantes de membresía y recursos en una sola transacción, o compilar la política en un predicado de base de datos. La evidencia de autorización y los efectos secundarios deben compartir un límite explícito de transacción/versión; una instantánea antigua no puede autorizar una escritura posterior incondicional.
Las operaciones masivas necesitan un contrato de atomicidad. Este escenario utiliza todo o nada: normaliza y desduplica todos los IDs, consulta el conjunto autorizado bajo un inquilino y acción confiables, y rechaza el lote si los conteos difieren. Exportar silenciosamente el subconjunto visible puede convertirse en un oráculo de existencia. Un contrato de producto por elemento también es posible, pero debe autorizar cada objeto y usar un resultado que no revele información para los elementos denegados.
Paso 5: Cubrir cachés, descargas y trabajos asíncronos
Una clave de caché incluye al menos el inquilino y la versión del recurso, como document:{tenant_id}:{document_id}:{version}. Un acierto recupera datos; no omite la autorización de la acción actual. Si las decisiones se almacenan en caché, la clave debe cubrir sujeto, inquilino, acción, recurso, versión de relación o política, y revocación. En sistemas complejos suele ser más seguro almacenar en caché los datos de relaciones y recalcular una pequeña decisión.
Una URL de descarga prefirmada es una capacidad de corta duración. Una vez emitida, un portador puede acceder al almacenamiento durante su tiempo de vida. Verifica download antes de emitirla y vincula el recurso, la acción, la expiración y la disposición del contenido. Los documentos sensibles utilizan tiempos de vida cortos, descargas de un solo uso o mediante proxy, y revocación cuando sea necesario. Una firma prueba que el servidor emitió la URL; no otorga a un llamador no autorizado permiso para obtenerla.
Una exportación verifica en dos momentos. La API verifica export en cada documento antes de encolar. En la ejecución, el worker utiliza las referencias de sujeto e inquilino en el trabajo para recargar la membresía actual y el permiso del recurso. Una membresía revocada, un cambio de inquilino o una concesión de soporte expirada detienen el trabajo antes de que exista un artefacto descargable. La carga útil del trabajo no puede aceptar un indicador de administrador proporcionado por el llamador ni preservar un arreglo de roles para siempre.
Paso 6: Tratar PostgreSQL RLS como defensa en profundidad verificable
Las tablas compartidas pueden habilitar RLS para que una política filtre las filas existentes por el inquilino de transacción confiable y WITH CHECK restrinja las filas insertadas o actualizadas. Denegar por defecto cuando no se aplica ninguna política es un modo de falla deseable. Antes del lanzamiento, verifica todo lo siguiente:
- la conexión de la aplicación no es un superusuario, carece de
BYPASSRLSy no es un propietario de tabla que normalmente
omite la política; usa FORCE ROW LEVEL SECURITY cuando sea apropiado;
- cada transacción establece el inquilino y lo limpia antes de regresar al pool; la falta de contexto deniega en lugar de seleccionar
un inquilino predeterminado;
USINGcubre filas antiguas visibles yWITH CHECKcubre filas nuevas insertadas o actualizadas;- migraciones, copias de seguridad, workers y herramientas de soporte utilizan roles separados y procedimientos explícitos;
- las políticas permisivas se combinan con
ORpor defecto, por lo que una política agregada no puede ampliar accidentalmente el acceso;
las políticas con subconsultas complejas también se revisan en cuanto a instantáneas de concurrencia y costo.
RLS no puede expresar todas las relaciones de producto y no puede proteger el almacenamiento de objetos o un índice de búsqueda que eluda la base de datos. La política de la aplicación posee la semántica de negocio completa; RLS detiene las fugas si una consulta omite el alcance del inquilino. Prueba ambas capas contra la misma matriz de permisos para lograr consistencia.
Paso 7: Diseñar errores, auditoría y pruebas falsables
Para objetos entre inquilinos o invisibles, este escenario devuelve un 404 uniforme y la misma estructura de respuesta. Una denegación no devuelve título, nombre del inquilino, propietario, versión, tamaño de archivo ni una pista de tiempo distintiva. La limitación de tasa reduce la enumeración y el ruido de auditoría, pero la afirmación de seguridad nunca depende de que un atacante no logre adivinar un UUID.
Audita actor, inquilino de confianza, acción, una representación controlada del ID del recurso, decisión, código de motivo, versión de política, concesión de soporte e ID de rastreo. No registres el contenido del documento, capacidades de descarga o JWTs completos. Las señales útiles incluyen denegaciones entre inquilinos, un sujeto sondeando muchos objetos inexistentes, errores de política, denegaciones de RLS, trabajos detenidos tras la revocación y el uso de concesiones de soporte.
La matriz de pruebas incluye al menos:
- dos inquilinos, cada uno con propietario, visualizador, editor y administrador, más un usuario revocado y un operador de soporte temporal;
- recursos propios, no compartidos del mismo inquilino, directamente compartidos, UUIDs válidos de otro inquilino y UUIDs inexistentes;
- list, GET, PATCH, DELETE, share, exportación masiva, GraphQL, descarga, acierto de caché y ejecución de worker;
- sustitución en rutas, consultas, JSON, arreglos, variables anidadas de GraphQL, claves de almacenamiento y cargas útiles de trabajos;
- ninguna fuga de respuesta en lecturas y ningún cambio de versión, uso compartido, archivo, mensaje, índice de búsqueda o auditoría de éxito en la denegación;
- revocación y actualización concurrentes, uso sucesivo de inquilinos de una conexión de pool, falta de contexto de RLS,
rol de aplicación mal configurado y caché de autorización obsoleta.
Genera casos de CI positivos y negativos a partir de la matriz de autorización, y exige que cada nuevo endpoint registre su recurso y acción. Los escáneres encuentran algunas rutas enumerables, pero no conocen la propiedad del negocio. Múltiples cuentas, objetos foráneos válidos conocidos y aserciones de efectos secundarios son la evidencia decisiva aquí.
Respuesta de ejemplo de alta calidad
“Clasificaría este defecto como BOLA. El JWT prueba la identidad del llamador, mientras que la API carece de permisos a nivel de acción para el documento de destino. Los UUIDs reducen la probabilidad de enumeración, pero no cambian la decisión de autorización. Primero definiría una matriz subject, tenant, action, resource, context y denegaría por defecto. Un usuario puede seleccionar un inquilino activo, pero el servidor deriva el contexto del inquilino a partir de una membresía actual verificada.
La capa de datos ya no expone un findById global a las rutas de negocio. Una lectura primero aplica el alcance mediante el tenant_id + document_id confiable, luego aplica reglas de rol, propiedad y uso compartido para read, update, delete, share o export. Una actualización simple lleva las condiciones de inquilino, objeto y acción, junto con la versión del recurso, en una sola sentencia condicional. Cero filas afectadas detiene todo efecto secundario. Las políticas complejas mantienen las versiones relevantes en una sola transacción. Las claves foráneas compuestas con inquilino evitan relaciones hijas entre inquilinos.
Incluiría cada posible elusión en ese modelo. La exportación masiva autoriza cada ID y aquí es todo o nada. Las claves de caché incluyen el inquilino y los aciertos de caché aún se reautorizan. Los enlaces de descarga requieren permiso download al emitirse y vinculan el objeto a una expiración corta. Los trabajos verifican al encolar y en la ejecución para que la revocación surta efecto antes de la exportación. RLS es un respaldo, pero el rol de la aplicación debe carecer de BYPASSRLS y propiedad de tablas, y el contexto de transacción del pool debe probarse para evitar fugas entre inquilinos.
Finalmente, usaría cuentas con múltiples roles en dos inquilinos y colocaría un UUID foráneo válido conocido en rutas, JSON, listas masivas y GraphQL. Las pruebas cubren rutas de lectura, escritura, eliminación, exportación, descarga, caché y worker. Cada denegación afirma una respuesta sin divulgación y ningún cambio en la versión de la base de datos, archivo, mensaje o índice de búsqueda. Esto demuestra la autorización a nivel de objeto ruta por ruta mientras cubre inicio de sesión, respuestas de error y efectos secundarios.”
Errores comunes
- Tratar UUID, Base64 o IDs cifrados como la solución → Los IDs se filtran a través de registros, enlaces compartidos u otras APIs, y una
referencia válida aún cruza el límite → **Autoriza sujeto, inquilino, objeto y acción en cada solicitud; usa IDs aleatorios solo como defensa en profundidad.**
- Permitir cualquier ID después de la validación de JWT → La autenticación identifica al sujeto pero no otorga derechos sobre el recurso →
Construye el contexto de inquilino a partir de la membresía verificada y luego toma la decisión sobre el objeto.
- Cargar globalmente en los controladores y escribir a mano una verificación de propietario → Las nuevas rutas, operaciones masivas, caché y workers la omiten,
mientras que el uso compartido en equipo se deniega erróneamente → Expón acceso a datos con alcance de inquilino y política central con denegación por defecto.
- Probar solo GET → PATCH, DELETE, exportaciones, GraphQL y descargas aún pueden filtrar o mutar datos → **Genera una
matriz negativa de múltiples cuentas a través de puntos de entrada y acciones.**
- Filtrar IDs denegados de un lote exitoso → Los conteos y contenidos se convierten en un oráculo de existencia, y el éxito parcial
es ambiguo → Predefine la semántica de todo o nada o por elemento y autoriza cada objeto.
- Asumir que RLS es seguridad automática → Los propietarios de tablas, superusuarios,
BYPASSRLS, contexto faltante y la composición
de políticas permisivas pueden romper el aislamiento → Verifica roles, contexto de transacción, USING/WITH CHECK y modos de falla.
- Afirmar solo 403 o 404 → El sistema puede haber escrito datos, enviado un mensaje o generado un archivo antes de la denegación →
Afirma que cada efecto secundario persistente y externo permanezca sin cambios.
- Registrar objetos completos y tokens para investigación → La telemetría de seguridad se convierte en otra fuga de datos → **Registra
identidad mínima, acción, motivo y un identificador de recurso controlado.**
Preguntas de seguimiento y respuestas
Pregunta de seguimiento 1: Si UUIDv4 es prácticamente imposible de adivinar, ¿sigue siendo necesaria la autorización de objetos?
Sí. Las referencias se filtran a través de enlaces compartidos, historial del navegador, registros, notificaciones, analíticas, otra API o un mensaje mal dirigido. Los UUIDs reducen la enumeración a ciegas; no expresan propietario, inquilino, acción ni expiración. Dale a la cuenta del atacante un UUID foráneo válido conocido en una prueba. El acceso exitoso demuestra inmediatamente la falta de autorización.
Pregunta de seguimiento 2: ¿Devolver 404 para cada objeto de otro inquilino hace que la depuración sea demasiado difícil?
Las respuestas externas pueden ser uniformes mientras que la auditoría interna mantiene motivos estables como RESOURCE_NOT_VISIBLE, ACTION_DENIED o TENANT_CONTEXT_INVALID. Los operadores investigan a través de registros controlados y un ID de rastreo; los llamadores no se enteran de si un objeto existe. Si la colaboración dentro del mismo inquilino necesita "sin permiso de edición", devuelve 403 solo después de establecer que el objeto es visible, bajo un contrato de API consistente.
Pregunta de seguimiento 3: ¿Qué sucede con las exportaciones en cola cuando un usuario es eliminado de un inquilino?
El envío exitoso no crea una autoridad de lectura permanente. Antes de la ejecución, recarga la membresía y el permiso export para cada recurso. Tras la revocación, deniega el trabajo, elimina los archivos temporales y no emitas ninguna URL de descarga. Si el cumplimiento normativo requiere derechos congelados en el momento del envío, crea una instantánea de autorización explícita y de corta duración con alcance, aprobador y expiración en lugar de preservar silenciosamente roles JWT obsoletos.
Pregunta de seguimiento 4: Si cada consulta de la aplicación ya incluye tenant_id, ¿qué aporta RLS?
Puede detener una nueva consulta que omita el predicado y algunas rutas directas a la base de datos, reduciendo el radio de impacto de una omisión. También agrega costos de contexto de pool, roles, migraciones y mantenimiento de políticas, y no puede proteger búsquedas, caché o almacenamiento de objetos. Las tablas compartidas de alta sensibilidad son buenas candidatas para ambas capas. Primero demuestra que el rol de la aplicación no puede omitir RLS, que la falta de contexto de inquilino deniega, que el contexto del pool no se filtra y que ambas capas coinciden con la misma matriz.
Pregunta de seguimiento 5: Los ingenieros de soporte necesitan acceso temporal a los documentos del cliente. ¿Cómo evitas una puerta trasera permanente?
Crea una autorización de soporte just-in-time separada y vinculada a un ticket, inquilino de destino, acciones permitidas, aprobador, expiración corta y motivo. Las acciones sensibles pueden requerir la aprobación de dos personas. Separa los endpoints normales de los de soporte, muestra un estado de sesión prominente, prohíbe la descarga masiva y audita cada acceso a objetos. La expiración revoca el acceso inmediatamente y el uso se revisa periódicamente. Los roles generales de la aplicación y los tokens de servicio no reciben ningún permiso entre inquilinos.