Feature: agregar login con Active Directory (LDAP) manteniendo JWT interno
Qué
Agrega POST /auth/ad, un método de login alternativo que autentica usuario y contraseña contra el controlador de dominio de Active Directory (LDAP) y, si el atributo mail de esa cuenta coincide con un funcionario o estudiante ya existente en SIENEP, emite el mismo JWT que el resto de los logins. No da de alta cuentas nuevas.
Por qué
A pedido del área de Infraestructura, que necesita que los usuarios puedan loguearse con sus credenciales del dominio en vez de (o además de) la contraseña local de SIENEP. Se siguió el mismo patrón ya usado para el login con Google (GoogleIdTokenVerifierService → Facade sobre el SDK externo, y AuthService solo resuelve la cuenta local por email) en vez de inventar un flujo nuevo: ActiveDirectoryVerifierService es un Facade equivalente sobre ActiveDirectoryLdapAuthenticationProvider, y la resolución de cuenta que antes vivía dentro de loginConGoogle() se extrajo a loginConIdentidadExterna() para que ambos flujos la compartan.
Un detalle donde sí se aparta de Google: acá un login exitoso saca a la cuenta de PENDIENTE_DE_ACTIVACION. Con Google eso no pasaba porque la contraseña temporal local podía seguir siendo relevante; con AD no tiene sentido, la contraseña temporal nunca interviene en este flujo, así que dejar la cuenta pendiente solo forzaría una pantalla de cambio de contraseña que un usuario de AD no va a usar nunca.
Cambios
-
ActiveDirectoryVerifierService(nuevo): recibe usuario/contraseña, autentica contra AD y devuelve elmailya verificado, o vacío si las credenciales son inválidas. Distingue credenciales rechazadas de AD no configurado/inalcanzable, lanzando503en este último caso en vez de disfrazarlo de contraseña incorrecta. -
AuthService.loginConAd()+loginConIdentidadExterna(): resuelve la cuenta local por email, valida que no esté bloqueada/inactiva, activa la cuenta si estaba pendiente (solo en el flujo de AD) y emite el JWT. Refactor comparte esta lógica conloginConGoogle(). -
AuthController: nuevo endpointPOST /auth/ad+AdLoginRequestDTO(usuario,contrasenia). -
pom.xml: nueva dependenciaspring-security-ldap. -
application.properties/.env.example: nuevas variablesAD_LDAP_URL,AD_DOMAIN,AD_ROOT_DN.
Acción requerida en el deploy
Ninguna migración de base de datos. Para habilitar el login por AD hay que cargar estas tres variables de entorno en el ambiente:
AD_LDAP_URL=ldap://10.0.50.19:389
AD_DOMAIN=corp.UTEC-Durazno.grupo01
AD_ROOT_DN=dc=corp,dc=UTEC-Durazno,dc=grupo01
Mientras no estén las tres cargadas, POST /auth/ad responde 503 sin romper nada del resto del sistema, se puede deployar antes de tener esos datos y activarlo después.
Cómo probar
Sin AD real (unit/integration, no necesita Docker):
./mvnw test -Dtest=ActiveDirectoryVerifierServiceTest,AuthServiceTest,AuthControllerTest
Cubre autenticación exitosa, credenciales rechazadas, AD no configurado (503), cuenta de AD sin atributo mail, cuenta local inactiva/bloqueada y la activación de cuentas PENDIENTE_DE_ACTIVACION.
Contra el AD real:
- Completar en
.env(copiado de.env.example) las tres variables de arriba. - Confirmar que exista un Funcionario o Estudiante en SIENEP cuyo email coincida (case-insensitive) con el atributo
mailde la cuenta de AD a usar. - Levantar la app y probar:
curl -X POST http://localhost:8080/auth/ad \ -H "Content-Type: application/json" \ -d '{"usuario": "<sAMAccountName>", "contrasenia": "<contraseña-del-dominio>"}' - Validar: credenciales correctas →
200+ JWT (y la cuenta pasa aACTIVOsi estaba pendiente); contraseña incorrecta →401; usuario de AD sin cuenta correspondiente en SIENEP →401; variables vacías o controlador inalcanzable →503; cuenta SIENEP bloqueada →403.