Updates tutorial for clarity and consistency
Refines the tutorial document by standardizing list formatting, correcting minor typographical errors, and updating outdated references, thereby enhancing readability and ensuring technical accuracy for users setting up the authentication system.
This commit is contained in:
parent
6b351ff5b3
commit
04b7840341
@ -6,23 +6,23 @@ Este tutorial comprensivo explica cómo configurar un sistema de autenticación
|
||||
|
||||
## Índice
|
||||
|
||||
1. [Fundamentos de Autenticación Empresarial](#fundamentos-de-autenticación-empresarial-ldap-keycloak-y-angular)
|
||||
2. [Preparación del entorno](#1-preparación-del-entorno)
|
||||
3. [Instalación y configuración de OpenLDAP](#2-instalación-y-configuración-de-openldap)
|
||||
4. [Crear estructura LDAP para usuarios y grupos](#3-crear-estructura-ldap-para-usuarios-y-grupos)
|
||||
5. [Instalación y configuración de Keycloak](#4-instalación-y-configuración-de-keycloak)
|
||||
6. [Configuración de Keycloak en la interfaz web](#5-configuración-de-keycloak-en-la-interfaz-web)
|
||||
7. [Integración con Angular: Enfoque básico](#6-integración-con-angular-enfoque-básico)
|
||||
8. [Integración con Angular 19: Enfoque moderno](#7-integración-con-angular-19-enfoque-moderno)
|
||||
9. [Servicios de autenticación avanzados](#8-servicios-de-autenticación-avanzados)
|
||||
10. [Guardias de ruta e interceptores HTTP](#9-guardias-de-ruta-e-interceptores-http)
|
||||
11. [Componentes de UI para login/logout](#10-componentes-de-ui-para-loginlogout)
|
||||
12. [Arquitectura del sistema](#11-arquitectura-del-sistema)
|
||||
13. [Consideraciones de seguridad y buenas prácticas](#12-consideraciones-de-seguridad)
|
||||
14. [Resolución de problemas comunes](#13-resolución-de-problemas-comunes)
|
||||
15. [Verificación y prueba del sistema](#14-verificación-y-prueba-del-sistema)
|
||||
16. [Recursos adicionales](#15-recursos-adicionales)
|
||||
17. [Resumen](#16-resumen)
|
||||
1. [Fundamentos de Autenticación Empresarial](#fundamentos-de-autenticaci%C3%B3n-empresarial-ldap-keycloak-y-angular)
|
||||
2. [Preparación del entorno](#1-preparaci%C3%B3n-del-entorno)
|
||||
3. [Instalación y configuración de OpenLDAP](#2-instalaci%C3%B3n-y-configuraci%C3%B3n-de-openldap)
|
||||
4. [Crear estructura LDAP para usuarios y grupos](#3-crear-estructura-ldap-para-usuarios-y-grupos)
|
||||
5. [Instalación y configuración de Keycloak](#4-instalaci%C3%B3n-y-configuraci%C3%B3n-de-keycloak)
|
||||
6. [Configuración de Keycloak en la interfaz web](#5-configuraci%C3%B3n-de-keycloak-en-la-interfaz-web)
|
||||
7. [Integración con Angular: Enfoque básico](#6-integraci%C3%B3n-con-angular-enfoque-b%C3%A1sico)
|
||||
8. [Integración con Angular 19: Enfoque moderno](#7-integraci%C3%B3n-con-angular-19-enfoque-moderno)
|
||||
9. [Servicios de autenticación avanzados](#8-servicios-de-autenticaci%C3%B3n-avanzados)
|
||||
10. [Guardias de ruta e interceptores HTTP](#9-guardias-de-ruta-e-interceptores-http)
|
||||
11. [Componentes de UI para login/logout](#10-componentes-de-ui-para-loginlogout)
|
||||
12. [Arquitectura del sistema](#11-arquitectura-del-sistema)
|
||||
13. [Consideraciones de seguridad y buenas prácticas](#12-consideraciones-de-seguridad)
|
||||
14. [Resolución de problemas comunes](#13-resoluci%C3%B3n-de-problemas-comunes)
|
||||
15. [Verificación y prueba del sistema](#14-verificaci%C3%B3n-y-prueba-del-sistema)
|
||||
16. [Recursos adicionales](#15-recursos-adicionales)
|
||||
17. [Resumen](#16-resumen)
|
||||
|
||||
# Fundamentos de Autenticación Empresarial: LDAP, Keycloak y Angular
|
||||
|
||||
@ -34,17 +34,17 @@ LDAP (Lightweight Directory Access Protocol) es un protocolo estándar diseñado
|
||||
|
||||
### Características principales de LDAP:
|
||||
|
||||
- **Estructura jerárquica**: Organiza la información en forma de árbol (similar a un sistema de archivos)
|
||||
- **Optimizado para lectura**: Proporciona acceso rápido a datos que cambian con poca frecuencia
|
||||
- **Centralización de la información**: Almacena datos de usuarios, grupos, permisos y recursos en un solo lugar
|
||||
- **Estandarizado**: Compatible con múltiples plataformas y aplicaciones
|
||||
- **Estructura jerárquica**: Organiza la información en forma de árbol (similar a un sistema de archivos)
|
||||
- **Optimizado para lectura**: Proporciona acceso rápido a datos que cambian con poca frecuencia
|
||||
- **Centralización de la información**: Almacena datos de usuarios, grupos, permisos y recursos en un solo lugar
|
||||
- **Estandarizado**: Compatible con múltiples plataformas y aplicaciones
|
||||
|
||||
### ¿Por qué usar LDAP?
|
||||
|
||||
- **Gestión centralizada de identidades**: Permite mantener toda la información de usuarios en un solo lugar
|
||||
- **Reducción de complejidad administrativa**: Evita tener que gestionar usuarios en múltiples sistemas
|
||||
- **Autenticación unificada**: Los usuarios pueden acceder a múltiples servicios con las mismas credenciales
|
||||
- **Escalabilidad**: Puede manejar desde pequeñas organizaciones hasta grandes empresas con millones de usuarios
|
||||
- **Gestión centralizada de identidades**: Permite mantener toda la información de usuarios en un solo lugar
|
||||
- **Reducción de complejidad administrativa**: Evita tener que gestionar usuarios en múltiples sistemas
|
||||
- **Autenticación unificada**: Los usuarios pueden acceder a múltiples servicios con las mismas credenciales
|
||||
- **Escalabilidad**: Puede manejar desde pequeñas organizaciones hasta grandes empresas con millones de usuarios
|
||||
|
||||
En el contexto empresarial, LDAP se utiliza principalmente como directorio centralizado de usuarios, lo que facilita la gestión de identidades y permisos a nivel organizacional.
|
||||
|
||||
@ -54,51 +54,51 @@ Keycloak es una solución de código abierto para gestión de identidad y acceso
|
||||
|
||||
### Características principales de Keycloak:
|
||||
|
||||
- **SSO (Single Sign-On)**: Permite a los usuarios autenticarse una vez y acceder a múltiples aplicaciones
|
||||
- **Federation de identidades**: Puede integrar múltiples fuentes de usuarios (como LDAP, Active Directory, bases de datos)
|
||||
- **Autenticación multifactor**: Soporta verificación en dos pasos y otros métodos de autenticación avanzados
|
||||
- **Protocolos estándar**: Implementa OAuth 2.0, OpenID Connect, SAML 2.0
|
||||
- **Administración centralizada**: Interfaz web para gestionar usuarios, roles, permisos y aplicaciones
|
||||
- **Personalizable**: Temas, flujos de autenticación y políticas adaptables
|
||||
- **SSO (Single Sign-On)**: Permite a los usuarios autenticarse una vez y acceder a múltiples aplicaciones
|
||||
- **Federación de identidades**: Puede integrar múltiples fuentes de usuarios (como LDAP, Active Directory, bases de datos)
|
||||
- **Autenticación multifactor**: Soporta verificación en dos pasos y otros métodos de autenticación avanzados
|
||||
- **Protocolos estándar**: Implementa OAuth 2.0, OpenID Connect, SAML 2.0
|
||||
- **Administración centralizada**: Interfaz web para gestionar usuarios, roles, permisos y aplicaciones
|
||||
- **Personalizable**: Temas, flujos de autenticación y políticas adaptables
|
||||
|
||||
### ¿Por qué usar Keycloak?
|
||||
|
||||
- **Implementación rápida de seguridad**: Proporciona funcionalidades robustas sin necesidad de desarrollarlas
|
||||
- **Experiencia de usuario mejorada**: Los usuarios solo necesitan recordar una contraseña
|
||||
- **Cumplimiento normativo**: Ayuda a implementar políticas de seguridad requeridas por regulaciones
|
||||
- **Flexibilidad**: Puede funcionar como intermediario entre aplicaciones modernas y sistemas de identidad heredados
|
||||
- **Implementación rápida de seguridad**: Proporciona funcionalidades robustas sin necesidad de desarrollarlas
|
||||
- **Experiencia de usuario mejorada**: Los usuarios solo necesitan recordar una contraseña
|
||||
- **Cumplimiento normativo**: Ayuda a implementar políticas de seguridad requeridas por regulaciones
|
||||
- **Flexibilidad**: Puede funcionar como intermediario entre aplicaciones modernas y sistemas de identidad heredados
|
||||
|
||||
## Objetivo de la integración LDAP + Keycloak + Angular
|
||||
|
||||
El objetivo principal de esta arquitectura es implementar un sistema de autenticación empresarial completo y seguro que:
|
||||
|
||||
1. **Centralice la gestión de usuarios** en un directorio LDAP
|
||||
2. **Modernice el acceso** mediante Keycloak, que actúa como proveedor de identidad (IdP)
|
||||
3. **Integre aplicaciones modernas** (Angular) con esta infraestructura de autenticación
|
||||
1. **Centralice la gestión de usuarios** en un directorio LDAP
|
||||
2. **Modernice el acceso** mediante Keycloak, que actúa como proveedor de identidad (IdP)
|
||||
3. **Integre aplicaciones modernas** (Angular) con esta infraestructura de autenticación
|
||||
|
||||
Esta combinación crea una solución robusta donde LDAP almacena los datos de usuarios, Keycloak gestiona la autenticación/autorización y la aplicación Angular consume estos servicios de forma segura.
|
||||
|
||||
## Problemas que soluciona esta arquitectura
|
||||
|
||||
### 1. Fragmentación de identidades
|
||||
**Problema**: En organizaciones grandes, es común tener usuarios duplicados en diferentes sistemas.
|
||||
**Solución**: LDAP centraliza la información de usuarios, mientras Keycloak expone estos datos a aplicaciones modernas.
|
||||
|
||||
**Problema**: En organizaciones grandes, es común tener usuarios duplicados en diferentes sistemas. **Solución**: LDAP centraliza la información de usuarios, mientras Keycloak expone estos datos a aplicaciones modernas.
|
||||
|
||||
### 2. Experiencia de usuario deficiente
|
||||
**Problema**: Obligar a los usuarios a iniciar sesión en cada aplicación por separado.
|
||||
**Solución**: Single Sign-On a través de Keycloak permite autenticarse una sola vez para acceder a múltiples aplicaciones.
|
||||
|
||||
**Problema**: Obligar a los usuarios a iniciar sesión en cada aplicación por separado. **Solución**: Single Sign-On a través de Keycloak permite autenticarse una sola vez para acceder a múltiples aplicaciones.
|
||||
|
||||
### 3. Seguridad inconsistente
|
||||
**Problema**: Cada aplicación implementa su propia seguridad, con diferentes estándares y posibles vulnerabilidades.
|
||||
**Solución**: Keycloak implementa prácticas de seguridad modernas de forma centralizada.
|
||||
|
||||
**Problema**: Cada aplicación implementa su propia seguridad, con diferentes estándares y posibles vulnerabilidades. **Solución**: Keycloak implementa prácticas de seguridad modernas de forma centralizada.
|
||||
|
||||
### 4. Dificultad para implementar autenticación robusta
|
||||
**Problema**: Implementar OAuth2, OpenID Connect o SAML desde cero es complejo y propenso a errores.
|
||||
**Solución**: Keycloak proporciona estas implementaciones listas para usar.
|
||||
|
||||
**Problema**: Implementar OAuth2, OpenID Connect o SAML desde cero es complejo y propenso a errores. **Solución**: Keycloak proporciona estas implementaciones listas para usar.
|
||||
|
||||
### 5. Gestión compleja de accesos
|
||||
**Problema**: Administrar quién puede acceder a qué recursos en múltiples aplicaciones.
|
||||
**Solución**: Roles y grupos centralizados que se aplican consistentemente en todas las aplicaciones.
|
||||
|
||||
**Problema**: Administrar quién puede acceder a qué recursos en múltiples aplicaciones. **Solución**: Roles y grupos centralizados que se aplican consistentemente en todas las aplicaciones.
|
||||
|
||||
## Arquitectura general de la solución
|
||||
|
||||
@ -118,12 +118,13 @@ Esta combinación crea una solución robusta donde LDAP almacena los datos de us
|
||||
| (Recursos) |
|
||||
| |
|
||||
+-------------------+
|
||||
|
||||
```
|
||||
|
||||
1. **OpenLDAP** actúa como almacén principal de usuarios y grupos
|
||||
2. **Keycloak** se conecta a LDAP y expone sus datos a través de protocolos modernos
|
||||
3. **Angular** se comunica con Keycloak para autenticación y obtención de tokens
|
||||
4. Los **backends/APIs** verifican los tokens emitidos por Keycloak
|
||||
1. **OpenLDAP** actúa como almacén principal de usuarios y grupos
|
||||
2. **Keycloak** se conecta a LDAP y expone sus datos a través de protocolos modernos
|
||||
3. **Angular** se comunica con Keycloak para autenticación y obtención de tokens
|
||||
4. Los **backends/APIs** verifican los tokens emitidos por Keycloak
|
||||
|
||||
A continuación, veremos paso a paso cómo implementar esta arquitectura.
|
||||
|
||||
@ -133,11 +134,11 @@ A continuación, veremos paso a paso cómo implementar esta arquitectura.
|
||||
|
||||
Para seguir este tutorial, necesitarás:
|
||||
|
||||
- Un sistema Ubuntu Server o una distribución similar de Linux
|
||||
- Acceso de root o privilegios sudo
|
||||
- Node.js (versión 18.x o superior)
|
||||
- Angular CLI (versión 19.x o compatible)
|
||||
- Java JDK (OpenJDK 17 o superior)
|
||||
- Un sistema Ubuntu Server o una distribución similar de Linux
|
||||
- Acceso de root o privilegios sudo
|
||||
- Node.js (versión 18.x o superior)
|
||||
- Angular CLI (versión 19.x o compatible)
|
||||
- Java JDK (OpenJDK 17 o superior)
|
||||
|
||||
### Actualización del sistema e instalación de Java
|
||||
|
||||
@ -193,17 +194,16 @@ Durante la instalación, se te pedirá configurar una contraseña de administrad
|
||||
sudo dpkg-reconfigure slapd
|
||||
```
|
||||
|
||||
|
||||
En la configuración:
|
||||
|
||||
1. "¿Omitir configuración del servidor LDAP?" → No
|
||||
2. "Nombre de dominio DNS:" → **correos.com**
|
||||
3. "Nombre de la organización:" → Correos Org
|
||||
4. "Contraseña de administrador:" → [tu contraseña segura]
|
||||
5. "Confirmar contraseña:" → [repetir la contraseña]
|
||||
6. "Motor de base de datos:" → MDB
|
||||
7. "¿Quiere que se elimine la base de datos cuando se purgue slapd?" → No
|
||||
8. "¿Mover la base de datos antigua?" → Sí
|
||||
1. "¿Omitir configuración del servidor LDAP?" → No
|
||||
2. "Nombre de dominio DNS:" → **correos.com**
|
||||
3. "Nombre de la organización:" → Correos Org
|
||||
4. "Contraseña de administrador:" → [tu contraseña segura]
|
||||
5. "Confirmar contraseña:" → [repetir la contraseña]
|
||||
6. "Motor de base de datos:" → MDB
|
||||
7. "¿Quiere que se elimine la base de datos cuando se purgue slapd?" → No
|
||||
8. "¿Mover la base de datos antigua?" → Sí
|
||||
|
||||

|
||||
|
||||
@ -213,14 +213,13 @@ En la configuración:
|
||||
|
||||

|
||||
|
||||
|
||||
### Verificar que LDAP se esté ejecutando correctamente
|
||||
|
||||
```bash
|
||||
sudo systemctl status slapd
|
||||
```
|
||||

|
||||
|
||||

|
||||
|
||||
### Comprobar la conexión LDAP básica
|
||||
|
||||
@ -248,9 +247,8 @@ Busca y modifica las siguientes líneas:
|
||||
$servers->setValue('server','base',array('dc=correos,dc=com'));
|
||||
$servers->setValue('login','bind_id','cn=admin,dc=correos,dc=com');
|
||||
```
|
||||

|
||||

|
||||
|
||||
 
|
||||
|
||||
Y cambia descomenta y cambia esta línea:
|
||||
|
||||
@ -264,9 +262,7 @@ por:
|
||||
$servers->setValue('login','anon_bind',false);
|
||||
```
|
||||
|
||||

|
||||

|
||||
Reinicia el servidor web:
|
||||
  Reinicia el servidor web:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart apache2
|
||||
@ -336,12 +332,14 @@ ldapadd -x -D cn=admin,dc=correos,dc=com -W -f ~/grupos.ldif
|
||||
### Crear usuarios LDAP
|
||||
|
||||
Primero, genera contraseñas encriptadas para los usuarios:
|
||||
> Aca usaremos la misma contraseña para todos los usuarios para temas practicos
|
||||
|
||||
> Aquí usaremos la misma contraseña para todos los usuarios para temas prácticos
|
||||
|
||||
```bash
|
||||
slappasswd -s "password123"
|
||||
```
|
||||

|
||||
Anota el hash resultante para usarlo en el siguiente archivo.
|
||||
|
||||
 Anota el hash resultante para usarlo en el siguiente archivo.
|
||||
|
||||
Crea un archivo para los usuarios:
|
||||
|
||||
@ -430,6 +428,7 @@ dn: cn=usuarios,ou=grupos,dc=correos,dc=com
|
||||
changetype: modify
|
||||
add: memberUid
|
||||
memberUid: user
|
||||
|
||||
```
|
||||
|
||||
Aplica los cambios:
|
||||
@ -468,13 +467,13 @@ sudo useradd -r -s /sbin/nologin keycloak
|
||||
# Asignar permisos
|
||||
sudo chown -R keycloak:keycloak /opt/keycloak
|
||||
```
|
||||
|
||||
## Configurar usuario administrador inicial para Keycloak
|
||||
|
||||
Crea un archivo de propiedades:
|
||||
|
||||
```bash
|
||||
sudo nano /opt/keycloak/conf/keycloak.conf
|
||||
|
||||
```
|
||||
|
||||
Agrega estas líneas:
|
||||
@ -489,7 +488,6 @@ http-enabled=true
|
||||
|
||||
# Configuración de administrador inicial
|
||||
http-enabled=true
|
||||
|
||||
```
|
||||
|
||||

|
||||
@ -499,7 +497,6 @@ http-enabled=true
|
||||
```bash
|
||||
cd /opt/keycloak
|
||||
sudo -u keycloak /opt/keycloak/bin/kc.sh bootstrap-admin user --username admin
|
||||
|
||||
```
|
||||
|
||||
En este comando preguntará para crear la contraseña del usuario "admin" que usaremos como administrador.
|
||||
@ -510,7 +507,6 @@ Sin hacer cd, corremos el siguiente comando:
|
||||
|
||||
```bash
|
||||
sudo -u keycloak bin/kc.sh start-dev
|
||||
|
||||
```
|
||||
|
||||
## Iniciar Keycloak en modo productivo
|
||||
@ -564,14 +560,14 @@ sudo systemctl status keycloak
|
||||
|
||||
> **Nota**: si quieres ver el log del servicio usa el comando `sudo journalctl -u keycloak -f`
|
||||
|
||||
## Configuración de Keycloak en la interfaz web
|
||||
## 5. Configuración de Keycloak en la interfaz web
|
||||
|
||||
Ahora puedes acceder a la consola de administración de Keycloak en http://192.168.1.27:8080/admin/ e iniciar sesión con:
|
||||
|
||||
- Usuario: `admin`
|
||||
- Contraseña: la que configuraste anteriormente
|
||||
|
||||
> No necesariamente es ese login siempre, todo depende de qué usuario crearon anteriormente y su contraseña ademas de la IP del servidor.
|
||||
> No necesariamente es ese login siempre, todo depende de qué usuario crearon anteriormente y su contraseña además de la IP del servidor.
|
||||
|
||||

|
||||
|
||||
@ -624,10 +620,8 @@ Ahora puedes acceder a la consola de administración de Keycloak en http://192.1
|
||||

|
||||
|
||||
6. En la pantalla del proveedor LDAP, ve a la pestaña "Synchronization"
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
7. Haz clic en "Sync all users"
|
||||
|
||||
@ -694,6 +688,7 @@ Ahora puedes acceder a la consola de administración de Keycloak en http://192.1
|
||||

|
||||
|
||||
4. En la siguiente pantalla (para aplicaciones SPA modernas):
|
||||
|
||||
- Client authentication: `OFF` (para aplicaciones SPA)
|
||||
- Authorization: `OFF`
|
||||
- Marca la casilla "Direct access grants"
|
||||
@ -701,23 +696,24 @@ Ahora puedes acceder a la consola de administración de Keycloak en http://192.1
|
||||
|
||||
> **Importante**: La opción "Direct access grants" es esencial ya que permite realizar la autenticación directamente desde el cliente Angular mediante peticiones POST (enviando usuario y contraseña), sin necesidad de redirigir al usuario a través de la interfaz de inicio de sesión de Keycloak.
|
||||
|
||||

|
||||
|
||||
5. En la siguiente pantalla:
|
||||
|
||||
- Root URL: `http://localhost:4200`
|
||||
- Home URL: `/`
|
||||
- Valid redirect URIs: `http://localhost:4200/*`
|
||||
- Web origins: `http://localhost:4200` (o usar `+` para permitir todos los orígenes durante desarrollo)
|
||||
- Haz clic en "Save"
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
> **Nota**: Para aplicaciones que no son SPA, puedes habilitar "Client authentication" y obtener un client secret que deberás usar en la configuración.
|
||||
> **Nota**: Puedes descargar un ejemplo de una maquina virtual de virtual box en el siguiente [enlace](https://valposystemscom-my.sharepoint.com/:u:/g/personal/luis_cespedes_valposystems_com/EepH0pHrk8ZEgeU-RmVkopgBiN6LWoPm6P8MJEzt-qdxXw?e=IZFMMg) con todo ya configurado , solo importar y usar
|
||||
5. En la siguiente pantalla:
|
||||
|
||||
- Root URL: `http://localhost:4200`
|
||||
- Home URL: `/`
|
||||
- Valid redirect URIs: `http://localhost:4200/*`
|
||||
- Web origins: `http://localhost:4200` (o usar `+` para permitir todos los orígenes durante desarrollo)
|
||||
- Haz clic en "Save"
|
||||
|
||||

|
||||
|
||||
|
||||
> **Nota**: Para aplicaciones que no son SPA, puedes habilitar "Client authentication" y obtener un client secret que deberás usar en la configuración. **Nota**: Puedes descargar un ejemplo de una máquina virtual de VirtualBox en el siguiente [enlace](https://valposystemscom-my.sharepoint.com/:u:/g/personal/luis_cespedes_valposystems_com/EepH0pHrk8ZEgeU-RmVkopgBiN6LWoPm6P8MJEzt-qdxXw?e=IZFMMg) con todo ya configurado, solo importar y usar.
|
||||
|
||||
## Configurar cliente para incluir grupos
|
||||
|
||||
**Añadir un Protocol Mapper en el cliente de Keycloak:** a. Inicia sesión en la consola de administración de Keycloak b. Navega a "Clients" > selecciona tu cliente "angular-app" c. Ve a la pestaña "Client Scopes" > Selecciona el scope por defecto (normalmente es el nombre del cliente) d. Ve a la pestaña "Mappers" e. Haz clic en "Create" o "Add Mapper" y selecciona "Group Membership" f. Configura el mapper con los siguientes valores:
|
||||
|
||||
- Name: groups
|
||||
@ -733,52 +729,46 @@ Alternativamente, puedes crear un mapper de tipo "User Attribute" si prefieres a
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Que logramos con esto ? facil , que en el accestoken aparezcan los grupos que pertenece el usuario , tal cual lo configuramos en ldap, esto puede ayudar para crear politicas de acceso a paginas o rutas protegidas para algun grupo en especifico mas adelante
|
||||

|
||||
|
||||
|
||||
¿Qué logramos con esto? Fácil: que en el access token aparezcan los grupos a los que pertenece el usuario, tal cual los configuramos en LDAP. Esto puede ayudar para crear políticas de acceso a páginas o rutas protegidas para algún grupo en específico más adelante. 
|
||||
|
||||
## 11. Arquitectura del sistema
|
||||
|
||||
La arquitectura del sistema está compuesta por los siguientes componentes:
|
||||
|
||||
- **OpenLDAP**: Directorio de usuarios y grupos (puerto 389)
|
||||
- **phpLDAPadmin**: Interfaz gráfica para administrar LDAP (puerto 80)
|
||||
- **Keycloak**: Servidor de autenticación y autorización (puerto 8080)
|
||||
- **Aplicación Angular**: Cliente que utiliza el SSO de Keycloak (puerto 4200)
|
||||
- **OpenLDAP**: Directorio de usuarios y grupos (puerto 389)
|
||||
- **phpLDAPadmin**: Interfaz gráfica para administrar LDAP (puerto 80)
|
||||
- **Keycloak**: Servidor de autenticación y autorización (puerto 8080)
|
||||
- **Aplicación Angular**: Cliente que utiliza el SSO de Keycloak (puerto 4200)
|
||||
|
||||
La estructura del directorio LDAP para correos.com es:
|
||||
|
||||
- dc=correos,dc=com (raíz del directorio)
|
||||
- ou=usuarios (unidad organizativa para usuarios)
|
||||
- uid=admin (usuario administrador)
|
||||
- uid=developer (usuario desarrollador)
|
||||
- uid=user (usuario normal)
|
||||
- ou=grupos (unidad organizativa para grupos)
|
||||
- cn=administradores (grupo de administradores)
|
||||
- cn=desarrolladores (grupo de desarrolladores)
|
||||
- cn=usuarios (grupo de usuarios)
|
||||
- dc=correos,dc=com (raíz del directorio)
|
||||
- ou=usuarios (unidad organizativa para usuarios)
|
||||
- uid=admin (usuario administrador)
|
||||
- uid=developer (usuario desarrollador)
|
||||
- uid=user (usuario normal)
|
||||
- ou=grupos (unidad organizativa para grupos)
|
||||
- cn=administradores (grupo de administradores)
|
||||
- cn=desarrolladores (grupo de desarrolladores)
|
||||
- cn=usuarios (grupo de usuarios)
|
||||
|
||||
### Flujo de autenticación
|
||||
|
||||
El flujo de autenticación funciona de la siguiente manera:
|
||||
|
||||
1. El usuario accede a la aplicación Angular
|
||||
2. Si el usuario no ha iniciado sesión, es redirigido a Keycloak
|
||||
3. Keycloak autentica al usuario contra LDAP
|
||||
4. Si la autenticación es exitosa, Keycloak redirige al usuario de vuelta a la aplicación con un token JWT
|
||||
5. La aplicación Angular verifica el token y permite el acceso
|
||||
6. Los interceptores HTTP añaden automáticamente el token a las peticiones API
|
||||
7. Las rutas protegidas verifican los roles del usuario antes de permitir el acceso
|
||||
|
||||
1. El usuario accede a la aplicación Angular
|
||||
2. Si el usuario no ha iniciado sesión, es redirigido a Keycloak
|
||||
3. Keycloak autentica al usuario contra LDAP
|
||||
4. Si la autenticación es exitosa, Keycloak redirige al usuario de vuelta a la aplicación con un token JWT
|
||||
5. La aplicación Angular verifica el token y permite el acceso
|
||||
6. Los interceptores HTTP añaden automáticamente el token a las peticiones API
|
||||
7. Las rutas protegidas verifican los roles del usuario antes de permitir el acceso
|
||||
|
||||
## 12. Consideraciones de seguridad
|
||||
|
||||
@ -786,9 +776,9 @@ Al implementar este sistema de autenticación en un entorno de producción, es c
|
||||
|
||||
### TLS/HTTPS
|
||||
|
||||
- **Comunicaciones cifradas**: Todas las comunicaciones entre componentes deben estar protegidas con TLS/HTTPS
|
||||
- **Certificados válidos**: Utiliza certificados de confianza, evitando certificados autofirmados en producción
|
||||
- **Configuración de cipher suites**: Configura solo cipher suites seguros y actualizados
|
||||
- **Comunicaciones cifradas**: Todas las comunicaciones entre componentes deben estar protegidas con TLS/HTTPS
|
||||
- **Certificados válidos**: Utiliza certificados de confianza, evitando certificados autofirmados en producción
|
||||
- **Configuración de cipher suites**: Configura solo cipher suites seguros y actualizados
|
||||
|
||||
```bash
|
||||
# Ejemplo: Configurar HTTPS en Keycloak
|
||||
@ -803,9 +793,9 @@ http-enabled=false
|
||||
|
||||
### Endurecimiento de LDAP
|
||||
|
||||
- **Acceso restringido**: Limita el acceso al servidor LDAP solo a Keycloak y servicios de administración
|
||||
- **Contraseñas robustas**: Implementa políticas de contraseñas fuertes para las cuentas administrativas
|
||||
- **Auditoría**: Habilita el registro de eventos para todas las operaciones críticas
|
||||
- **Acceso restringido**: Limita el acceso al servidor LDAP solo a Keycloak y servicios de administración
|
||||
- **Contraseñas robustas**: Implementa políticas de contraseñas fuertes para las cuentas administrativas
|
||||
- **Auditoría**: Habilita el registro de eventos para todas las operaciones críticas
|
||||
|
||||
```bash
|
||||
# Configurar políticas de contraseñas en OpenLDAP
|
||||
@ -821,24 +811,24 @@ ldapadd -Y EXTERNAL -H ldapi:/// -f ~/password-policy.ldif
|
||||
|
||||
### Seguridad de Keycloak
|
||||
|
||||
- **Actualizaciones regulares**: Mantén Keycloak actualizado con las últimas versiones de seguridad
|
||||
- **Límites de sesión**: Configura tiempos de expiración adecuados para tokens y sesiones
|
||||
- **Autenticación de dos factores**: Habilita MFA para cuentas privilegiadas
|
||||
- **Alertas de seguridad**: Configura notificaciones para eventos de seguridad importantes
|
||||
- **Actualizaciones regulares**: Mantén Keycloak actualizado con las últimas versiones de seguridad
|
||||
- **Límites de sesión**: Configura tiempos de expiración adecuados para tokens y sesiones
|
||||
- **Autenticación de dos factores**: Habilita MFA para cuentas privilegiadas
|
||||
- **Alertas de seguridad**: Configura notificaciones para eventos de seguridad importantes
|
||||
|
||||
Para configurar MFA en Keycloak:
|
||||
|
||||
1. Ve a Authentication > Flows
|
||||
2. Duplica el flujo de browser
|
||||
3. Añade un requerimiento de autenticación OTP
|
||||
4. Configura este flujo como el predeterminado para autenticación de navegador
|
||||
1. Ve a Authentication > Flows
|
||||
2. Duplica el flujo de browser
|
||||
3. Añade un requerimiento de autenticación OTP
|
||||
4. Configura este flujo como el predeterminado para autenticación de navegador
|
||||
|
||||
### Seguridad en aplicaciones Angular
|
||||
|
||||
- **HttpOnly cookies**: Para almacenamiento seguro de tokens de sesión
|
||||
- **CSP (Content Security Policy)**: Implementa políticas restrictivas para prevenir XSS
|
||||
- **CSRF protection**: Implementa protección contra falsificación de solicitudes entre sitios
|
||||
- **Sanitización de entrada**: Valida y limpia todas las entradas de usuario
|
||||
- **HttpOnly cookies**: Para almacenamiento seguro de tokens de sesión
|
||||
- **CSP (Content Security Policy)**: Implementa políticas restrictivas para prevenir XSS
|
||||
- **CSRF protection**: Implementa protección contra falsificación de solicitudes entre sitios
|
||||
- **Sanitización de entrada**: Valida y limpia todas las entradas de usuario
|
||||
|
||||
```typescript
|
||||
// Ejemplo: Configurar interceptor HTTP para tokens en Angular
|
||||
@ -863,17 +853,17 @@ export class AuthInterceptor implements HttpInterceptor {
|
||||
|
||||
### Auditoría y monitoreo
|
||||
|
||||
- **Centralización de logs**: Implementa un sistema centralizado de gestión de logs
|
||||
- **Alertas de seguridad**: Configura alertas para patrones de autenticación sospechosos
|
||||
- **Monitoreo de disponibilidad**: Implementa health checks para todos los componentes
|
||||
- **Revisiones periódicas**: Establece un calendario de revisiones de seguridad
|
||||
- **Centralización de logs**: Implementa un sistema centralizado de gestión de logs
|
||||
- **Alertas de seguridad**: Configura alertas para patrones de autenticación sospechosos
|
||||
- **Monitoreo de disponibilidad**: Implementa health checks para todos los componentes
|
||||
- **Revisiones periódicas**: Establece un calendario de revisiones de seguridad
|
||||
|
||||
### Backups y recuperación
|
||||
|
||||
- **Backup regular de LDAP**: Programa backups completos del directorio LDAP
|
||||
- **Backup de configuración**: Mantén respaldos de la configuración de Keycloak
|
||||
- **Pruebas de recuperación**: Verifica regularmente que los backups son utilizables
|
||||
- **Documentación**: Mantén documentación actualizada de los procedimientos de recuperación
|
||||
- **Backup regular de LDAP**: Programa backups completos del directorio LDAP
|
||||
- **Backup de configuración**: Mantén respaldos de la configuración de Keycloak
|
||||
- **Pruebas de recuperación**: Verifica regularmente que los backups son utilizables
|
||||
- **Documentación**: Mantén documentación actualizada de los procedimientos de recuperación
|
||||
|
||||
```bash
|
||||
# Ejemplo: Backup de OpenLDAP
|
||||
@ -891,9 +881,9 @@ La implementación adecuada de estas medidas de seguridad es tan importante como
|
||||
|
||||
Este error ocurre cuando intentas conectarte a LDAP con credenciales incorrectas. Para resolverlo:
|
||||
|
||||
1. Verifica que estás usando el dominio correcto: `dc=correos,dc=com`
|
||||
2. Asegúrate de usar el DN correcto: `cn=admin,dc=correos,dc=com`
|
||||
3. Comprueba que la contraseña de administrador es correcta
|
||||
1. Verifica que estás usando el dominio correcto: `dc=correos,dc=com`
|
||||
2. Asegúrate de usar el DN correcto: `cn=admin,dc=correos,dc=com`
|
||||
3. Comprueba que la contraseña de administrador es correcta
|
||||
|
||||
Si olvidaste la contraseña, puedes restablecerla:
|
||||
|
||||
@ -941,86 +931,88 @@ sudo ls -la /opt/keycloak
|
||||
|
||||
Este error suele ocurrir cuando hay problemas con la configuración del cliente en Keycloak:
|
||||
|
||||
1. Verifica que el realm y el clientId sean correctos en la configuración de Angular
|
||||
2. Asegúrate de que el cliente en Keycloak tenga la configuración correcta:
|
||||
- Web Origins: debe incluir `http://localhost:4200` o `+` para desarrollo
|
||||
- Valid redirect URIs: debe incluir `http://localhost:4200/*`
|
||||
- Client authentication debe estar OFF para aplicaciones SPA
|
||||
- Access Type debe ser "public"
|
||||
1. Verifica que el realm y el clientId sean correctos en la configuración de Angular
|
||||
2. Asegúrate de que el cliente en Keycloak tenga la configuración correcta:
|
||||
- Web Origins: debe incluir `http://localhost:4200` o `+` para desarrollo
|
||||
- Valid redirect URIs: debe incluir `http://localhost:4200/*`
|
||||
- Client authentication debe estar OFF para aplicaciones SPA
|
||||
- Access Type debe ser "public"
|
||||
|
||||
### Problema: Redireccionamiento circular
|
||||
|
||||
Si ves redirecciones constantes entre tu aplicación y Keycloak:
|
||||
|
||||
1. Verifica la lógica en el componente app.component.ts y login.component.ts
|
||||
2. Asegúrate de que no haya múltiples redirecciones activándose a la vez
|
||||
3. Usa el parámetro `replaceUrl: true` en las navegaciones para evitar acumular entradas en el historial
|
||||
4. Maneja correctamente las rutas especiales como '/' redirigiendo a una ruta válida como '/inicio'
|
||||
1. Verifica la lógica en el componente app.component.ts y login.component.ts
|
||||
2. Asegúrate de que no haya múltiples redirecciones activándose a la vez
|
||||
3. Usa el parámetro `replaceUrl: true` en las navegaciones para evitar acumular entradas en el historial
|
||||
4. Maneja correctamente las rutas especiales como '/' redirigiendo a una ruta válida como '/inicio'
|
||||
|
||||
### Problema: "Can't resolve 'keycloak-angular'"
|
||||
|
||||
Si encuentras este error al compilar:
|
||||
|
||||
1. Asegúrate de haber instalado correctamente las dependencias:
|
||||
```bash
|
||||
npm install keycloak-angular keycloak-js
|
||||
```
|
||||
2. Verifica que las versiones sean compatibles con tu versión de Angular
|
||||
3. Limpia la caché de npm y reinstala:
|
||||
```bash
|
||||
npm cache clean --force
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
```
|
||||
1. Asegúrate de haber instalado correctamente las dependencias:
|
||||
|
||||
```bash
|
||||
npm install keycloak-angular keycloak-js
|
||||
```
|
||||
|
||||
2. Verifica que las versiones sean compatibles con tu versión de Angular
|
||||
3. Limpia la caché de npm y reinstala:
|
||||
|
||||
```bash
|
||||
npm cache clean --forcerm -rf node_modulesnpm install
|
||||
```
|
||||
|
||||
|
||||
### Problema: El token no se adjunta a las peticiones HTTP
|
||||
|
||||
1. Verifica que estés utilizando el interceptor correcto
|
||||
2. Asegúrate de que las condiciones de URL para el token sean correctas
|
||||
3. Revisa si estás usando `provideHttpClient` con `withInterceptors([includeBearerTokenInterceptor])`
|
||||
4. Comprueba los patrones en `createInterceptorCondition` para asegurarte de que coincidan con tus URLs
|
||||
1. Verifica que estés utilizando el interceptor correcto
|
||||
2. Asegúrate de que las condiciones de URL para el token sean correctas
|
||||
3. Revisa si estás usando `provideHttpClient` con `withInterceptors([includeBearerTokenInterceptor])`
|
||||
4. Comprueba los patrones en `createInterceptorCondition` para asegurarte de que coincidan con tus URLs
|
||||
|
||||
### Problema: No puedes ver los miembros de un grupo en Keycloak
|
||||
|
||||
Este error ocurre cuando hay una configuración incorrecta en el mapeo de grupos LDAP:
|
||||
|
||||
1. **Causa principal**: El tipo de atributo de membresía (Membership Attribute Type) está configurado como `DN` cuando debería ser `UID`.
|
||||
2. **Solución**: En User Federation → LDAP → group-mapper → Edit, cambia "Membership Attribute Type" de `DN` a `UID`.
|
||||
3. **Explicación**: En la estructura LDAP creada, los valores de `memberUid` contienen sólo el uid simple (admin, developer, user) y no el DN completo.
|
||||
4. Después de hacer el cambio, vuelve a ejecutar "Sync LDAP Groups to Keycloak".
|
||||
1. **Causa principal**: El tipo de atributo de membresía (Membership Attribute Type) está configurado como `DN` cuando debería ser `UID`.
|
||||
2. **Solución**: En User Federation → LDAP → group-mapper → Edit, cambia "Membership Attribute Type" de `DN` a `UID`.
|
||||
3. **Explicación**: En la estructura LDAP creada, los valores de `memberUid` contienen sólo el uid simple (admin, developer, user) y no el DN completo.
|
||||
4. Después de hacer el cambio, vuelve a ejecutar "Sync LDAP Groups to Keycloak".
|
||||
|
||||
## 14. Verificación y prueba del sistema
|
||||
|
||||
### Verificar que Keycloak esté sincronizando correctamente con LDAP
|
||||
|
||||
1. Inicia sesión en la consola de administración de Keycloak (http://localhost:8080/admin/)
|
||||
2. Navega a "Users" en el reino "angular-app"
|
||||
3. Deberías ver los usuarios de LDAP: admin, developer y user
|
||||
4. Navega a "Groups" y verifica que los grupos de LDAP estén presentes
|
||||
5. Haz clic en cada grupo y verifica que los miembros aparezcan correctamente
|
||||
- Si no aparecen, revisa la sección "Resolución de problemas" sobre el tipo de atributo de membresía
|
||||
1. Inicia sesión en la consola de administración de Keycloak (http://localhost:8080/admin/)
|
||||
2. Navega a "Users" en el reino "angular-app"
|
||||
3. Deberías ver los usuarios de LDAP: admin, developer y user
|
||||
4. Navega a "Groups" y verifica que los grupos de LDAP estén presentes
|
||||
5. Haz clic en cada grupo y verifica que los miembros aparezcan correctamente
|
||||
- Si no aparecen, revisa la sección "Resolución de problemas" sobre el tipo de atributo de membresía
|
||||
|
||||
### Probar la aplicación Angular
|
||||
|
||||
1. Asegúrate de que Keycloak esté ejecutándose
|
||||
2. Inicia la aplicación Angular con `ng serve`
|
||||
3. Navega a http://localhost:4200
|
||||
4. Haz clic en "Iniciar Sesión"
|
||||
5. Deberías ser redirigido a la pantalla de inicio de sesión de Keycloak
|
||||
6. Inicia sesión con uno de los usuarios LDAP:
|
||||
- Usuario: admin, Contraseña: password123
|
||||
- Usuario: developer, Contraseña: password123
|
||||
- Usuario: user, Contraseña: password123
|
||||
7. Después de iniciar sesión, serás redirigido de vuelta a la aplicación
|
||||
8. La aplicación mostrará tu perfil y roles
|
||||
1. Asegúrate de que Keycloak esté ejecutándose
|
||||
2. Inicia la aplicación Angular con `ng serve`
|
||||
3. Navega a http://localhost:4200
|
||||
4. Haz clic en "Iniciar Sesión"
|
||||
5. Deberías ser redirigido a la pantalla de inicio de sesión de Keycloak
|
||||
6. Inicia sesión con uno de los usuarios LDAP:
|
||||
- Usuario: admin, Contraseña: password123
|
||||
- Usuario: developer, Contraseña: password123
|
||||
- Usuario: user, Contraseña: password123
|
||||
7. Después de iniciar sesión, serás redirigido de vuelta a la aplicación
|
||||
8. La aplicación mostrará tu perfil y roles
|
||||
|
||||
## 15. Recursos adicionales
|
||||
|
||||
- [Documentación oficial de Keycloak](https://www.keycloak.org/documentation)
|
||||
- [Documentación oficial de OpenLDAP](https://www.openldap.org/doc/)
|
||||
- [Documentación oficial de keycloak-angular](https://github.com/mauriciovigolo/keycloak-angular)
|
||||
- [Guía de migración para Keycloak-Angular v19](https://www.keycloak.org/securing-apps/v19.0.2/angular)
|
||||
- [Ejemplos de implementación en GitHub](https://github.com/mauriciovigolo/keycloak-angular/tree/main/examples/standalone-app)
|
||||
- [Documentación oficial de Keycloak](https://www.keycloak.org/documentation)
|
||||
- [Documentación oficial de OpenLDAP](https://www.openldap.org/doc/)
|
||||
- [Documentación oficial de keycloak-angular](https://github.com/mauriciovigolo/keycloak-angular)
|
||||
- [Guía de migración para Keycloak-Angular v19](https://www.keycloak.org/securing-apps/v19.0.2/angular)
|
||||
- [Ejemplos de implementación en GitHub](https://github.com/mauriciovigolo/keycloak-angular/tree/main/examples/standalone-app)
|
||||
|
||||
## 16. Resumen
|
||||
|
||||
@ -1028,41 +1020,40 @@ En este tutorial comprensivo, hemos explorado la implementación de un sistema d
|
||||
|
||||
### Beneficios principales de esta implementación:
|
||||
|
||||
- **Centralización de usuarios**: A través de OpenLDAP, toda la información de usuarios se mantiene en un único lugar, facilitando la administración y evitando duplicidades.
|
||||
|
||||
- **Seguridad robusta**: Keycloak proporciona implementaciones probadas de protocolos de seguridad modernos, reduciendo la superficie de ataque y centralizando políticas de seguridad.
|
||||
|
||||
- **Experiencia de usuario mejorada**: Single Sign-On permite a los usuarios acceder a múltiples aplicaciones con una sola autenticación, reduciendo fricción y mejorando la productividad.
|
||||
|
||||
- **Modularidad y escalabilidad**: La arquitectura permite añadir nuevas aplicaciones o servicios sin modificar la infraestructura de autenticación central.
|
||||
|
||||
- **Flexibilidad**: La capacidad de federación de identidades de Keycloak facilita la integración con sistemas existentes y la migración gradual.
|
||||
- **Centralización de usuarios**: A través de OpenLDAP, toda la información de usuarios se mantiene en un único lugar, facilitando la administración y evitando duplicidades.
|
||||
|
||||
- **Seguridad robusta**: Keycloak proporciona implementaciones probadas de protocolos de seguridad modernos, reduciendo la superficie de ataque y centralizando políticas de seguridad.
|
||||
|
||||
- **Experiencia de usuario mejorada**: Single Sign-On permite a los usuarios acceder a múltiples aplicaciones con una sola autenticación, reduciendo fricción y mejorando la productividad.
|
||||
|
||||
- **Modularidad y escalabilidad**: La arquitectura permite añadir nuevas aplicaciones o servicios sin modificar la infraestructura de autenticación central.
|
||||
|
||||
- **Flexibilidad**: La capacidad de federación de identidades de Keycloak facilita la integración con sistemas existentes y la migración gradual.
|
||||
|
||||
|
||||
### Aplicaciones prácticas:
|
||||
|
||||
Esta arquitectura es particularmente valiosa en:
|
||||
|
||||
- **Grandes organizaciones** con múltiples aplicaciones y departamentos
|
||||
- **Entornos regulados** donde la trazabilidad y control de acceso son críticos
|
||||
- **Transformaciones digitales** donde coexisten aplicaciones heredadas y modernas
|
||||
- **Empresas en crecimiento** que necesitan una solución de autenticación que escale
|
||||
- **Grandes organizaciones** con múltiples aplicaciones y departamentos
|
||||
- **Entornos regulados** donde la trazabilidad y control de acceso son críticos
|
||||
- **Transformaciones digitales** donde coexisten aplicaciones heredadas y modernas
|
||||
- **Empresas en crecimiento** que necesitan una solución de autenticación que escale
|
||||
|
||||
### Próximos pasos recomendados:
|
||||
|
||||
Después de implementar esta solución básica, considera:
|
||||
|
||||
1. **Implementar autenticación multifactor** para usuarios privilegiados
|
||||
2. **Configurar alta disponibilidad** para Keycloak y LDAP
|
||||
3. **Integrar análisis de comportamiento de usuario** para detección de anomalías
|
||||
4. **Automatizar procesos de aprovisionamiento** con flujos de trabajo personalizados
|
||||
5. **Implementar monitoreo y alertas de seguridad** para detectar intentos de intrusión
|
||||
1. **Implementar autenticación multifactor** para usuarios privilegiados
|
||||
2. **Configurar alta disponibilidad** para Keycloak y LDAP
|
||||
3. **Integrar análisis de comportamiento de usuario** para detección de anomalías
|
||||
4. **Automatizar procesos de aprovisionamiento** con flujos de trabajo personalizados
|
||||
5. **Implementar monitoreo y alertas de seguridad** para detectar intentos de intrusión
|
||||
|
||||
El ecosistema moderno de autenticación está en constante evolución, pero esta implementación proporciona una base sólida sobre la cual construir soluciones de seguridad adaptadas a las necesidades específicas de cada organización.
|
||||
|
||||
Con la configuración y conocimientos adquiridos en este tutorial, estarás bien posicionado para implementar y mantener un sistema de autenticación empresarial robusto, seguro y centrado en el usuario.
|
||||
|
||||
---
|
||||
|
||||
*Nota final: Recuerda que la seguridad es un proceso continuo, no un estado. Mantén todos los componentes actualizados y revisa regularmente las configuraciones y políticas de seguridad para adaptarte a nuevas amenazas y requisitos.*
|
||||
|
||||
----------
|
||||
|
||||
_Nota final: Recuerda que la seguridad es un proceso continuo, no un estado. Mantén todos los componentes actualizados y revisa regularmente las configuraciones y políticas de seguridad para adaptarte a nuevas amenazas y requisitos._
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user