# Tutorial: Implementación de Keycloak con LDAP para Angular Este tutorial explica cómo configurar un sistema de autenticación completo utilizando Keycloak como proveedor de identidad, OpenLDAP como directorio de usuarios y una aplicación Angular que consume estos servicios. ## Índice 1. [Preparación del entorno Ubuntu](#1-preparaci%C3%B3n-del-entorno-ubuntu) 2. [Instalación y configuración de OpenLDAP](#2-instalaci%C3%B3n-y-configuraci%C3%B3n-de-openldap) 3. [Crear estructura LDAP para correos.com](#3-crear-estructura-ldap-para-correoscom) 4. [Instalación y configuración de Keycloak](#4-instalaci%C3%B3n-y-configuraci%C3%B3n-de-keycloak) 5. [Configuración de Keycloak en la interfaz web](#5-configuraci%C3%B3n-de-keycloak-en-la-interfaz-web) 6. [Configuración de una aplicación Angular](#6-configuraci%C3%B3n-de-una-aplicaci%C3%B3n-angular) 7. [Arquitectura del sistema](#7-arquitectura-del-sistema) 8. [Resolución de problemas comunes](#8-resoluci%C3%B3n-de-problemas-comunes) 9. [Verificación y prueba del sistema](#9-verificaci%C3%B3n-y-prueba-del-sistema) 10. [Resumen](#10-resumen) ## 1. Preparación del entorno Ubuntu Primero, actualizamos el sistema e instalamos Java: ```bash sudo apt update sudo apt upgrade -y sudo apt install openjdk-17-jdk -y ``` Verifica la instalación de Java: ```bash java -version ``` ## 2. Instalación y configuración de OpenLDAP ### Instalar OpenLDAP y utilidades ```bash sudo apt install slapd ldap-utils -y ``` Durante la instalación, se te pedirá configurar una contraseña de administrador para LDAP. ### Reconfigurar LDAP con el dominio correcto ```bash 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í ### Verificar que LDAP se esté ejecutando correctamente ```bash sudo systemctl status slapd ``` ### Comprobar la conexión LDAP básica ```bash ldapsearch -x -H ldap://localhost -b dc=correos,dc=com -D "cn=admin,dc=correos,dc=com" -W ``` ### Instalar phpLDAPadmin para la gestión gráfica ```bash sudo apt install phpldapadmin -y ``` ### Configurar phpLDAPadmin Edita el archivo de configuración: ```bash sudo nano /etc/phpldapadmin/config.php ``` Busca y modifica las siguientes líneas: ```php $servers->setValue('server','host','127.0.0.1'); $servers->setValue('server','base',array('dc=correos,dc=com')); $servers->setValue('login','bind_id','cn=admin,dc=correos,dc=com'); ``` Y cambia esta línea: ```php $servers->setValue('login','anon_bind',true); ``` por: ```php $servers->setValue('login','anon_bind',false); ``` Reinicia el servidor web: ```bash sudo systemctl restart apache2 ``` ## 3. Crear estructura LDAP para correos.com ### Crear unidades organizativas Crea un archivo para las unidades organizativas: ```bash nano ~/ou.ldif ``` Con el siguiente contenido: ```ldif dn: ou=grupos,dc=correos,dc=com objectClass: organizationalUnit ou: grupos dn: ou=usuarios,dc=correos,dc=com objectClass: organizationalUnit ou: usuarios ``` Aplica los cambios: ```bash ldapadd -x -D cn=admin,dc=correos,dc=com -W -f ~/ou.ldif ``` ### Crear grupos LDAP Crea un archivo para los grupos: ```bash nano ~/grupos.ldif ``` Con el siguiente contenido: ```ldif dn: cn=administradores,ou=grupos,dc=correos,dc=com objectClass: posixGroup cn: administradores gidNumber: 1000 dn: cn=desarrolladores,ou=grupos,dc=correos,dc=com objectClass: posixGroup cn: desarrolladores gidNumber: 1001 dn: cn=usuarios,ou=grupos,dc=correos,dc=com objectClass: posixGroup cn: usuarios gidNumber: 1002 ``` Aplica los cambios: ```bash ldapadd -x -D cn=admin,dc=correos,dc=com -W -f ~/grupos.ldif ``` ### Crear usuarios LDAP Primero, genera contraseñas encriptadas para los usuarios: ```bash slappasswd -s "password123" ``` Anota el hash resultante para usarlo en el siguiente archivo. Crea un archivo para los usuarios: ```bash nano ~/usuarios.ldif ``` Con el siguiente contenido (reemplazando {HASH} con el hash que generaste): ```ldif dn: uid=admin,ou=usuarios,dc=correos,dc=com objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: admin sn: Admin givenName: Admin cn: Admin User displayName: Admin User uidNumber: 1000 gidNumber: 1000 userPassword: {HASH} loginShell: /bin/bash homeDirectory: /home/admin mail: admin@correos.com dn: uid=developer,ou=usuarios,dc=correos,dc=com objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: developer sn: Developer givenName: Dev cn: Dev User displayName: Developer User uidNumber: 1001 gidNumber: 1001 userPassword: {HASH} loginShell: /bin/bash homeDirectory: /home/developer mail: developer@correos.com dn: uid=user,ou=usuarios,dc=correos,dc=com objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: user sn: User givenName: Normal cn: Normal User displayName: Normal User uidNumber: 1002 gidNumber: 1002 userPassword: {HASH} loginShell: /bin/bash homeDirectory: /home/user mail: user@correos.com ``` Aplica los cambios: ```bash ldapadd -x -D cn=admin,dc=correos,dc=com -W -f ~/usuarios.ldif ``` ### Asociar usuarios a grupos Crea un archivo para las membresías: ```bash nano ~/miembros.ldif ``` Con el siguiente contenido: ```ldif dn: cn=administradores,ou=grupos,dc=correos,dc=com changetype: modify add: memberUid memberUid: admin dn: cn=desarrolladores,ou=grupos,dc=correos,dc=com changetype: modify add: memberUid memberUid: developer dn: cn=usuarios,ou=grupos,dc=correos,dc=com changetype: modify add: memberUid memberUid: user ``` Aplica los cambios: ```bash ldapmodify -x -D cn=admin,dc=correos,dc=com -W -f ~/miembros.ldif ``` ### Verificar la estructura LDAP ```bash ldapsearch -x -H ldap://localhost -b dc=correos,dc=com -D "cn=admin,dc=correos,dc=com" -W ``` ## 4. Instalación y configuración de Keycloak ### Descargar e instalar Keycloak ```bash # Crear directorio para Keycloak mkdir -p ~/keycloak cd ~/keycloak # Descargar la última versión de Keycloak wget https://github.com/keycloak/keycloak/releases/download/21.1.1/keycloak-21.1.1.tar.gz # Extraer el archivo tar -xvzf keycloak-21.1.1.tar.gz # Mover a una ubicación más adecuada sudo mv keycloak-21.1.1 /opt/keycloak # Crear un usuario para Keycloak 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: ``` # Configuración básica http-port=8080 https-port=8443 hostname=localhost # Configuración de administrador inicial http-enabled=true ``` ### Iniciar Keycloak en modo desarrollo ```bash cd /opt/keycloak export KEYCLOAK_ADMIN=admin export KEYCLOAK_ADMIN_PASSWORD=admin sudo -u keycloak bin/kc.sh start-dev ``` Esto iniciará Keycloak con un usuario administrador "admin" y contraseña "admin". ### Configurar Keycloak como servicio En otra terminal, crea un archivo de servicio systemd: ```bash sudo nano /etc/systemd/system/keycloak.service ``` Con el siguiente contenido: ```ini [Unit] Description=Keycloak Application Server After=network.target [Service] Type=idle User=keycloak Group=keycloak Environment="KEYCLOAK_ADMIN=admin" Environment="KEYCLOAK_ADMIN_PASSWORD=admin" ExecStart=/opt/keycloak/bin/kc.sh start-dev TimeoutStartSec=600 TimeoutStopSec=600 [Install] WantedBy=multi-user.target ``` En el futuro, podrás habilitar e iniciar el servicio con: ```bash sudo systemctl daemon-reload sudo systemctl enable keycloak sudo systemctl start keycloak ``` ## 5. Configuración de Keycloak en la interfaz web Ahora puedes acceder a la consola de administración de Keycloak en http://localhost:8080/admin/ e iniciar sesión con: - Usuario: `admin` - Contraseña: `admin` ### Crear un nuevo Reino (Realm) 1. Haz clic en el menú desplegable superior izquierdo que dice "master" 2. Selecciona "Create Realm" 3. Ingresa el nombre: `angular-app` 4. Haz clic en "Create" ### Configurar la Federación de Usuarios LDAP 1. En el menú lateral izquierdo, selecciona "User Federation" 2. Haz clic en "Add provider" → "ldap" 3. Completa los siguientes campos: - Console Display Name: `LDAP` - Vendor: `Other` - Connection URL: `ldap://localhost:389` - Enable StartTLS: `OFF` - Bind Type: `simple` - Bind DN: `cn=admin,dc=correos,dc=com` - Bind Credential: (la contraseña de admin LDAP) - Edit Mode: `WRITABLE` - Users DN: `ou=usuarios,dc=correos,dc=com` - Username LDAP attribute: `uid` - RDN LDAP attribute: `uid` - UUID LDAP attribute: `entryUUID` - User Object Classes: `inetOrgPerson, posixAccount` - Custom User LDAP Filter: (dejar en blanco) - Search Scope: `One Level` 4. Haz clic en "Test connection" y "Test authentication" para verificar 5. Guarda la configuración 6. En la pantalla del proveedor LDAP, ve a la pestaña "Synchronization" 7. Haz clic en "Sync all users" ### Configurar el Mapeo de Grupos LDAP 1. En la pantalla del proveedor LDAP, ve a la pestaña "Mappers" 2. Haz clic en "Create" 3. Completa: - Name: `group-mapper` - Mapper Type: `group-ldap-mapper` - LDAP Groups DN: `ou=grupos,dc=correos,dc=com` - Group Object Classes: `posixGroup` - Membership LDAP Attribute: `memberUid` - Group Name LDAP Attribute: `cn` - User Roles Retrieve Strategy: `LOAD_GROUPS_BY_MEMBER_ATTRIBUTE` - Member-Of LDAP Attribute: `memberOf` - Mapped Group Attributes: (dejar en blanco) - Drop non-existing groups during sync: `ON` 4. Haz clic en "Save" 5. En la pantalla del mapper, haz clic en "Sync LDAP Groups to Keycloak" ### Crear un Cliente para Angular 1. En el menú lateral izquierdo, selecciona "Clients" 2. Haz clic en "Create client" 3. Completa: - Client type: `OpenID Connect` - Client ID: `angular-app` - Name: `Angular Application` - Haz clic en "Next" 4. En la siguiente pantalla: - Client authentication: `ON` - Authorization: `OFF` - Haz clic en "Next" 5. En la siguiente pantalla: - Root URL: `http://localhost:4200` - Home URL: `/` - Valid redirect URIs: `http://localhost:4200/*` - Web origins: `http://localhost:4200` - Haz clic en "Save" 6. En la pestaña "Credentials" del cliente, copia el "Client secret" (lo necesitarás para la aplicación Angular) ## 6. Configuración de una aplicación Angular Primero, instala Node.js y npm: ```bash curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs ``` ### Crear una aplicación Angular ```bash # Instalar Angular CLI npm install -g @angular/cli # Crear una nueva aplicación ng new angular-keycloak-app cd angular-keycloak-app # Instalar la biblioteca para integrar Keycloak npm install keycloak-angular keycloak-js ``` ### Configurar Keycloak en Angular Crea un archivo de configuración en `src/assets/keycloak.json`: ```json { "realm": "angular-app", "auth-server-url": "http://localhost:8080/", "resource": "angular-app", "credentials": { "secret": "TU_CLIENT_SECRET_AQUÍ" } } ``` Modifica el archivo `src/app/app.module.ts`: ```typescript import { NgModule, APP_INITIALIZER } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; function initializeKeycloak(keycloak: KeycloakService) { return () => keycloak.init({ config: { url: 'http://localhost:8080', realm: 'angular-app', clientId: 'angular-app' }, initOptions: { onLoad: 'check-sso', silentCheckSsoRedirectUri: window.location.origin + '/assets/silent-check-sso.html' } }); } @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, KeycloakAngularModule ], providers: [ { provide: APP_INITIALIZER, useFactory: initializeKeycloak, multi: true, deps: [KeycloakService] } ], bootstrap: [AppComponent] }) export class AppModule { } ``` Crea un archivo `src/assets/silent-check-sso.html`: ```html
``` ### Crear un servicio de autenticación ```bash ng generate service auth ``` Edita `src/app/auth.service.ts`: ```typescript import { Injectable } from '@angular/core'; import { KeycloakService } from 'keycloak-angular'; import { KeycloakProfile } from 'keycloak-js'; @Injectable({ providedIn: 'root' }) export class AuthService { constructor(private keycloak: KeycloakService) { } public getLoggedUser(): PromiseEmail: {{ userProfile?.email }}
Nombre de Usuario: {{ userProfile?.username }}
Por favor inicia sesión para acceder al sistema