Sign inSign up

vviudez/user-selfservice-ldap

By vviudez

Updated 14 days ago

Image
Security
Integration & delivery
API management
0

972

vviudez/user-selfservice-ldap repository overview

Autoservicio de cuenta (LDAP Self-Service)

SPA ligera (React + Vite + TypeScript) que consume la API de Autenticación LDAP para que cualquier usuario pueda, sin intervención de IT:

  • iniciar sesión (usuario/contraseña o API key),
  • ver sus datos autenticado (atributos LDAP + grupos),
  • editar los atributos de perfil que el servidor permita,
  • cambiar su contraseña,
  • crear y revocar sus propias API keys,
  • y recuperar el acceso si ha olvidado la contraseña, vía email.

Estado

Todos los flujos funcionan de extremo a extremo contra la API real (https://hub.docker.com/repository/docker/vviudez/api-ldap): login, perfil, API keys, cambio de contraseña y también el reseteo por email ("¿Olvidaste tu contraseña?").

Estructura

frontend/                  SPA React + Vite + TypeScript
  src/api/client.ts         cliente HTTP tipado (todos los endpoints, existentes + reset)
  src/context/AuthContext   sesión en memoria/sessionStorage, login/logout
  src/pages/                Login, ForgotPassword, ResetPassword, Perfil, ApiKeys, CambiarContraseña
  nginx/default.conf.template   config de nginx para producción (proxy /api configurable)
  Dockerfile                 build multi-stage -> imagen nginx
docker-compose.yml
.env.example

Desarrollo local

Requisitos: Node.js ≥ 20.

cd frontend
npm install
cp .env.example .env          # ajusta VITE_DEV_API_PROXY_TARGET a la URL real de tu API
npm run dev                   # http://localhost:5173, con proxy /api -> la API real

El frontend siempre llama a rutas relativas (/api/v1/...); en desarrollo Vite las reenvía a VITE_DEV_API_PROXY_TARGET, en producción lo hace nginx (ver más abajo). Así el mismo código y el mismo build sirven para cualquier entorno sin recompilar ni sufrir problemas de CORS.

Build de producción (sin Docker)

cd frontend
npm run build          # genera frontend/dist (~185 KB JS, ~60 KB gzip; ~7 KB CSS)
npm run preview         # sirve dist/ localmente para comprobarlo

dist/ es un conjunto de ficheros estáticos: puedes servirlos con cualquier servidor web, pero necesitarás reproducir tú mismo el reverse proxy hacia /api (ver frontend/nginx/default.conf.template como referencia) para evitar CORS.

Docker

La imagen empaqueta la SPA ya compilada servida por nginx, que además hace de reverse proxy hacia la API real — así el navegador solo habla con un origen y el backend no necesita configurar CORS. La URL de la API se configura en el arranque del contenedor, no en el build, así que la misma imagen sirve para cualquier despliegue.

Build + run manual
cd frontend
docker build -t user-selfservice-ldap .
docker run -d --name user-selfservice-ldap \
  -p 8080:8080 \
  -e API_UPSTREAM=http://API-IP:8000 \
  user-selfservice-ldap

Abre http://localhost:8080.

docker-compose (recomendado para un servidor local)
cp .env.example .env      # ajusta API_UPSTREAM / HOST_PORT
docker compose up -d --build     # o `docker-compose up -d --build` según tu versión de Docker
Redesplegar cambios (tras un git pull, un rebuild, etc.)

Como el docker-compose.yml fija siempre el mismo tag (user-selfservice-ldap:latest), reconstruir la imagen puede dejar el contenedor en marcha "huérfano": sigue referenciando el sha256 exacto de la imagen anterior, que deja de existir. Si ves un error como No such image: sha256:... al hacer up, no es un problema de la app — solo hay que forzar la recreación del contenedor:

docker compose down            # (o docker-compose down)
docker compose up -d --build

down antes de up evita el problema por completo porque no deja ningún contenedor a medio recrear.

Variables de entorno del contenedor
VariableDóndePor defectoDescripción
API_UPSTREAMcontenedor / composehttp://API_IP:8000URL base (sin barra final) de la API de Autenticación LDAP real.
LISTEN_PORTcontenedor8080Puerto interno en el que escucha nginx.
HOST_PORTsolo compose (.env)8080Puerto del host mapeado al contenedor.

Verificación rápida tras levantar el contenedor:

curl http://localhost:8080/healthz        # "ok" — nginx vivo
curl http://localhost:8080/api/v1/health  # respuesta real de la API vía proxy

Decisiones de diseño relevantes

  • Sesión en el cliente: el access_token devuelto por /login se guarda en sessionStorage (no localStorage) y se envía como Authorization: Bearer. Se descarta solo, sin esperar un 401, cuando llega session_expires_at. Se pierde al cerrar la pestaña — es la opción más conservadora para una app de gestión de credenciales.
  • Edición de perfil: como PATCH /me exige current_password en el cuerpo (para que LDAP autorice el cambio vía sus propias ACL, no la API), la UI pide la contraseña actual en un paso de confirmación justo antes de guardar, nunca la mantiene en memoria más tiempo del necesario.
  • Qué atributos son editables: la API no expone una lista explícita; se infiere en runtime: el atributo cuyo valor coincide con el username de la sesión (típicamente uid) se muestra de solo lectura, el resto se ofrece editable y es el propio servidor (ldap.self_service_editable_attributes + ACL de LDAP) quien acepta o rechaza cada cambio.
  • Mensaje de "olvidé mi contraseña": siempre se muestra el mismo mensaje genérico, exista o no el email, para no ayudar a enumerar cuentas — coherente con el comportamiento anti-enumeración del backend.
  • Ligereza: sin frameworks de UI pesados, CSS propio (~7 KB), bundle JS ~60 KB gzip. Sirve bien para uso local en un servidor pequeño.

Tag summary

Content type

Image

Digest

sha256:69ae9e08b

Size

20.1 MB

Last updated

14 days ago

docker pull vviudez/user-selfservice-ldap