Files
SnapOtter/apps/docs/es/guide/scim.md
T
SnapOtterandGitHub d10d0f544f fix: release QA hardening across processing, media, security, and CI gates (#649)
A release-readiness QA pass over the whole product. The commits split into
defects a user would hit and gates that were reporting green while measuring
nothing.

## Fixes that change behaviour

Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so
request.ip came from a client-set header and a forged X-Forwarded-For got past
the login limiter. The default is now a private-network trust list.

A transient Postgres outage stranded in-flight jobs, leaving finished output on
disk with no row pointing at it. A reconciler now resolves those rows and adopts
the bytes rather than dropping the work.

A Redis connection that moved to a new address wedged every read-blocked
consumer, so completions stopped signalling while health still answered 200.
Socket timeouts plus subscriber pings recover it.

Installing more than one AI bundle left the shared venv multi-versioned and
silently broke three tools. The installer now reconciles distributions to one
version each.

Converting an image to JXL at quality 1 through 4 returned a 500, because
libjxl 0.7 rejects the distance those values compute. The quality is floored at
what the encoder honours. A missing ffmpeg was also reported to the user as a
corrupt upload; it now says the engine is unavailable.

RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at
0.22.2, and the release scan was split so it can fail on an unfixed critical
instead of hiding it behind ignore-unfixed.

## Gates that could not fail

Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs
build; coverage discarded its whole report on any failing test; the lint gate
skipped root tests, scripts, and two workspaces; and several generated matrices
counted a host missing ffmpeg as a passing tool. Each now measures what it
claims.

Full evidence and the outstanding release items are tracked locally and are not
part of this branch.
2026-07-27 15:37:30 +08:00

14 KiB

description, i18n_source_hash, i18n_provenance, i18n_output_hash, i18n_hash_version
description i18n_source_hash i18n_provenance i18n_output_hash i18n_hash_version
Configura el aprovisionamiento SCIM 2.0 para sincronizar usuarios y grupos desde tu proveedor de identidad hacia SnapOtter. Cubre Okta, Azure AD / Entra ID e integraciones personalizadas. 06ee702b386e human db9c6e0b36c9 2

Aprovisionamiento SCIM

SnapOtter implementa SCIM 2.0 (System for Cross-domain Identity Management) para el aprovisionamiento automatizado de usuarios y grupos. Tu proveedor de identidad puede crear, actualizar, desactivar y reactivar cuentas de usuario y sincronizar la pertenencia a grupos automáticamente.

::: tip Función enterprise El aprovisionamiento SCIM requiere una licencia enterprise con la función scim. No está disponible en el plan team. Sin la función, todos los endpoints SCIM (excepto discovery) devuelven 403. :::

Requisitos previos

  • Una instancia de SnapOtter en ejecución accesible en una URL pública
  • Una clave de licencia enterprise con la función scim
  • Una cuenta SnapOtter admin integrada con su conjunto completo de permisos efectivos. Una función personalizada delegada o una clave API de administrador a la que le falta algún permiso de administrador no pueden generar ni revocar el token SCIM global.
  • Acceso de administrador a la configuración de aprovisionamiento de tu proveedor de identidad

Inicio rápido

  1. Genera un token bearer de SCIM:
curl -X POST https://photos.example.com/api/v1/enterprise/scim/token \
  -H "Cookie: snapotter-session=YOUR_SESSION" \
  -H "Content-Type: application/json"

La respuesta contiene el token. Guárdalo de inmediato; no se puede recuperar de nuevo.

{
  "token": "so_scim_v2_a1b2c3d4e5f6...",
  "message": "Save this token - it cannot be retrieved again"
}
  1. En tu proveedor de identidad, configura el aprovisionamiento SCIM con:
    • Base URL: https://photos.example.com/api/v1/scim/v2
    • Autenticación: token bearer (pega el token del paso 1)

Autenticación

Los endpoints SCIM usan un token Bearer dedicado, independiente de las sesiones de usuario y de las claves de API.

Generar un token

POST /api/v1/enterprise/scim/token genera un nuevo token SCIM. Debido a que el token puede aprovisionar y mutar usuarios en la instancia, este punto final requiere el rol admin integrado con el conjunto completo de permisos de administrador efectivo. Mantener a users:manage en una función personalizada no es suficiente.

El token se devuelve en texto plano exactamente una vez. SnapOtter almacena solo un hash scrypt. Si pierdes el token, revócalo y genera uno nuevo.

Solo hay un token SCIM activo a la vez. Generar un token nuevo reemplaza al anterior.

::: warning Reemisión de token después de la actualización Los tokens SCIM heredados y no versionados se rechazan. Después de actualizar a una versión que emite tokens so_scim_v2_..., genere un token nuevo y actualice su proveedor de identidad antes de reanudar el aprovisionamiento. :::

Revocar un token

DELETE /api/v1/enterprise/scim/token revoca el token SCIM actual. Tiene los mismos requisitos de administración integrados que la generación de tokens.

Limitación de tasa

Los endpoints SCIM están limitados a 1000 solicitudes por minuto por token. Superar este límite devuelve HTTP 429.

Recursos admitidos

Recurso SCIM Concepto de SnapOtter Crear Leer Actualizar Eliminar
User Cuenta de usuario Eliminación lógica
Group Equipo

::: warning Los Groups de SCIM se corresponden con los equipos de SnapOtter, no con roles. SCIM no puede establecer el rol de un usuario. Todos los usuarios creados vía SCIM reciben el rol user. Para cambiar el rol de un usuario, usa la interfaz de administración de SnapOtter. :::

Operaciones de usuario

Crear usuario

POST /api/v1/scim/v2/Users

Crea una nueva cuenta de usuario con authProvider establecido en scim y el rol user. El usuario se asigna al equipo Default. Si active es false, el rol se establece en disabled en su lugar.

Atributos obligatorios: userName. Opcionales: externalId, emails, active (por defecto true).

Listar y filtrar usuarios

GET /api/v1/scim/v2/Users

Devuelve una lista paginada de usuarios. Admite los parámetros de consulta startIndex y count (máximo 200 resultados por página).

El filtrado admite solo eq (igual), sobre estos atributos:

  • userName eq "jane"
  • externalId eq "ext-12345"

Otros operadores de filtro y atributos devuelven HTTP 400.

Obtener usuario

GET /api/v1/scim/v2/Users/:id

Devuelve un único usuario por su ID de usuario de SnapOtter.

Reemplazar usuario

PUT /api/v1/scim/v2/Users/:id

Reemplaza los atributos del usuario. Admite userName, externalId, emails y active. Los cambios de nombre de usuario se comprueban en busca de conflictos (409 si otro usuario ya usa el nuevo nombre de usuario).

Aplicar patch a un usuario

PATCH /api/v1/scim/v2/Users/:id

Actualización parcial mediante SCIM PatchOp. Operaciones admitidas:

Operación Rutas
replace active, userName, externalId, emails, emails[type eq "work"].value, name.formatted, displayName
add Igual que replace
remove externalId, emails

Las rutas name.formatted y displayName se aceptan por compatibilidad, pero no tienen efecto persistente (SnapOtter no almacena un nombre para mostrar por separado).

Las operaciones replace sin valor (donde el valor es un objeto sin un path) también se admiten, con las claves userName, externalId, emails y active.

Desactivar usuario (eliminación lógica)

DELETE /api/v1/scim/v2/Users/:id

SnapOtter no elimina usuarios de forma definitiva vía SCIM. En su lugar, DELETE realiza una desactivación lógica:

  1. El rol del usuario se cambia de su valor actual (p. ej. editor) a disabled:editor, preservando el rol original.
  2. Se borra la contraseña del usuario.
  3. Se revocan todas las sesiones activas.
  4. Se revocan todas las claves de API.

El usuario ya no puede iniciar sesión ni usar ninguna clave de API. Sus datos (archivos, historial) se conservan.

Reactivar usuario

Para reactivar un usuario previamente desactivado, envía una solicitud PUT o PATCH con active: true. SnapOtter restaura el rol original de antes de la desactivación (p. ej. disabled:editor vuelve a ser editor). Si no se puede determinar el rol original, se recurre a user.

::: details Ejemplo: desactivar y reactivar vía PATCH

// Deactivate
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "active", "value": false }
  ]
}

// Reactivate
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "active", "value": true }
  ]
}

:::

Operaciones de grupo

Los Groups de SCIM se corresponden con los equipos de SnapOtter. Crear un grupo crea un equipo. La pertenencia al grupo controla a qué equipo pertenece un usuario.

Crear grupo

POST /api/v1/scim/v2/Groups

Obligatorio: displayName. Opcional: members (array de { value: userId }).

Listar y filtrar grupos

GET /api/v1/scim/v2/Groups

El filtrado admite solo displayName eq "...". Paginado con startIndex y count (máximo 200 resultados por página).

Obtener grupo

GET /api/v1/scim/v2/Groups/:id

Reemplazar grupo

PUT /api/v1/scim/v2/Groups/:id

Reemplaza el nombre del grupo y la lista completa de miembros. Los miembros existentes que no estén en la nueva lista se trasladan al equipo Default.

Aplicar patch a un grupo

PATCH /api/v1/scim/v2/Groups/:id

Admite estas operaciones:

Operación Ruta Efecto
add members Añade usuarios al equipo
remove members[value eq "userId"] Traslada al usuario al equipo Default
replace displayName Renombra el equipo
replace members Reemplaza todos los miembros (los miembros eliminados pasan al equipo Default)

Eliminar grupo

DELETE /api/v1/scim/v2/Groups/:id

Elimina el equipo. Todos los miembros del equipo eliminado se trasladan al equipo Default. Los usuarios no se desactivan ni se eliminan.

Configuración del IdP

Okta

  1. En la consola de administración de Okta, abre tu aplicación de SnapOtter (o crea una).
  2. Ve a la pestaña Provisioning y haz clic en Configure API Integration.
  3. Marca Enable API Integration e introduce:
    • Base URL: https://photos.example.com/api/v1/scim/v2
    • API Token: el token bearer de SCIM generado anteriormente
  4. Haz clic en Test API Credentials y luego en Save.
  5. En Provisioning > To App, habilita:
    • Create Users
    • Update User Attributes
    • Deactivate Users
  6. En Push Groups, configura qué grupos de Okta sincronizar como equipos de SnapOtter.

Azure AD / Entra ID

  1. En el portal de Azure, ve a tu aplicación empresarial de SnapOtter.
  2. Ve a Provisioning y establece Provisioning Mode en Automatic.
  3. En Admin Credentials, introduce:
    • Tenant URL: https://photos.example.com/api/v1/scim/v2
    • Secret Token: el token bearer de SCIM generado anteriormente
  4. Haz clic en Test Connection y luego en Save.
  5. En Mappings, configura las asignaciones de atributos de usuario y de grupo. Los valores por defecto suelen funcionar, pero verifica que userName se asigne a userPrincipalName o mail según prefieras.
  6. Establece Provisioning Status en On y guarda.

Azure aprovisiona usuarios y grupos en un ciclo de sincronización fijo (normalmente cada 40 minutos).

Endpoints de discovery

Estos tres endpoints están disponibles sin autenticación y describen las capacidades del servidor SCIM:

Endpoint Descripción
GET /api/v1/scim/v2/ServiceProviderConfig Capacidades del servidor y funciones admitidas
GET /api/v1/scim/v2/Schemas Definiciones de esquema de User y Group
GET /api/v1/scim/v2/ResourceTypes Tipos de recurso disponibles (User, Group)

El ServiceProviderConfig anuncia estas capacidades:

Función Admitida
Patch
Bulk No
Filter Sí (máx. 200 resultados, solo el operador eq)
Change password No
Sort No
ETag No

Limitaciones

  • Filtrado: solo se admite el operador eq. Los filtros complejos, los operadores and/or, co (contiene) y sw (empieza por) no están implementados.
  • Operaciones bulk: no se admiten.
  • Sort y ETag: no se admiten.
  • Roles: SCIM no puede asignar roles de SnapOtter. Todos los usuarios aprovisionados reciben el rol user.
  • MAX_USERS: el límite de la variable de entorno MAX_USERS no se aplica en la creación de usuarios vía SCIM. Si necesitas limitar el número de usuarios, gestiona las asignaciones en tu IdP.
  • Un solo token: solo puede haber un token SCIM activo a la vez. Si varios IdP necesitan acceso SCIM, deben compartir el token.
  • Los grupos son equipos: los Groups de SCIM se corresponden con equipos, no con roles ni grupos de permisos.

Solución de problemas

403 "SCIM provisioning requires an enterprise license with the scim feature"

Tu licencia no incluye la función scim, o no hay ninguna licencia configurada. SCIM requiere una licencia de plan enterprise. Verifica que SNAPOTTER_LICENSE_KEY esté establecido y que la licencia incluya la función scim.

401 "Bearer token required"

La solicitud SCIM no incluía una cabecera Authorization: Bearer <token>. Comprueba la configuración de aprovisionamiento de tu IdP.

401 "Invalid token"

El token tiene un formato incorrecto, utiliza el formato no versionado retirado o no coincide con el hash almacenado. Genere un token so_scim_v2_... actual y actualícelo en la configuración de aprovisionamiento de su IdP.

401 "SCIM not configured"

Aún no se ha generado ningún token SCIM. Usa el endpoint POST /api/v1/enterprise/scim/token para crear uno.

409 "User already exists" / "userName already taken"

Ya existe un usuario con el mismo nombre de usuario. Esto puede ocurrir cuando un IdP reintenta una creación fallida. Comprueba si hay nombres de usuario duplicados en el panel de administración de SnapOtter.

429 "SCIM rate limit exceeded"

El IdP está enviando más de 1000 solicitudes por minuto. Esto suele ocurrir durante una gran sincronización inicial. La mayoría de los IdP reintentan automáticamente cuando se reinicia la ventana de límite de tasa. Si el problema persiste, comprueba el intervalo de sincronización de aprovisionamiento de tu IdP.

Usuarios desaprovisionados pero no eliminados de la interfaz

DELETE de SCIM es una desactivación lógica. Los usuarios desactivados siguen apareciendo en la lista de usuarios del administrador con un estado deshabilitado. Esto es intencionado para preservar sus datos. Su rol se muestra como disabled:<original-role>.