Instalación de Keycloak para Single Sign-On

Keycloak es la plataforma de gestión de identidades y acceso (IAM) open source más utilizada para implementar Single Sign-On (SSO) en aplicaciones modernas. Con soporte para OAuth2, OpenID Connect, SAML 2.0 y federación de identidades con LDAP o Active Directory, Keycloak centraliza la autenticación de múltiples aplicaciones en un único servidor. Esta guía cubre la instalación con Docker, la configuración de realms, clientes, OAuth2/OIDC y la integración con aplicaciones web.

Requisitos Previos

  • Servidor Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+)
  • Docker y Docker Compose instalados (para el método Docker)
  • Java 17+ (para instalación nativa)
  • Al menos 2 GB de RAM (4 GB recomendado en producción)
  • PostgreSQL (recomendado para producción en lugar de H2)
  • Dominio con SSL configurado

Instalación con Docker

Docker Compose con PostgreSQL

mkdir -p /opt/keycloak
cd /opt/keycloak
# /opt/keycloak/docker-compose.yml
services:
  postgres:
    image: postgres:15
    container_name: keycloak-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: clave-postgres-segura
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - keycloak-net

  keycloak:
    image: quay.io/keycloak/keycloak:24.0.3
    container_name: keycloak
    restart: unless-stopped
    depends_on:
      - postgres
    environment:
      # Credenciales del administrador inicial
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: cambia-esta-clave-admin

      # Configuración de la base de datos
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: clave-postgres-segura

      # URL pública del servidor (importante para los redirects OAuth2)
      KC_HOSTNAME: sso.tudominio.com
      KC_HOSTNAME_STRICT: "false"

      # Proxy inverso
      KC_PROXY: edge
      KC_HTTP_ENABLED: "true"

    ports:
      - "8080:8080"
    command: start
    networks:
      - keycloak-net

volumes:
  postgres-data:

networks:
  keycloak-net:
    driver: bridge
# Iniciar Keycloak
docker compose up -d

# Ver los logs
docker compose logs -f keycloak

# Esperar hasta ver el mensaje: "Keycloak 24.0.3 on JVM (powered by Quarkus)"
# La interfaz web estará disponible en: http://IP_SERVIDOR:8080

Instalación Nativa (JAR)

# Instalar Java 17
sudo apt-get update
sudo apt-get install -y openjdk-17-jdk

# Descargar Keycloak
wget https://github.com/keycloak/keycloak/releases/download/24.0.3/keycloak-24.0.3.tar.gz
tar -xzf keycloak-24.0.3.tar.gz -C /opt/
ln -s /opt/keycloak-24.0.3 /opt/keycloak

# Crear el usuario del sistema
sudo useradd -r -s /bin/false keycloak
sudo chown -R keycloak:keycloak /opt/keycloak-24.0.3 /opt/keycloak

# Configurar las variables de entorno
cat > /opt/keycloak/conf/keycloak.conf << 'EOF'
# Base de datos
db=postgres
db-url=jdbc:postgresql://localhost:5432/keycloak
db-username=keycloak
db-password=clave-postgres-segura

# Hostname
hostname=sso.tudominio.com
hostname-strict=false

# Proxy
proxy=edge
http-enabled=true
http-port=8080
EOF

# Crear el servicio systemd
sudo cat > /etc/systemd/system/keycloak.service << 'EOF'
[Unit]
Description=Keycloak SSO Server
After=network.target postgresql.service

[Service]
User=keycloak
Group=keycloak
WorkingDirectory=/opt/keycloak
Environment=KEYCLOAK_ADMIN=admin
Environment=KEYCLOAK_ADMIN_PASSWORD=cambia-esta-clave-admin
ExecStart=/opt/keycloak/bin/kc.sh start
Restart=on-failure
RestartSec=30

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable keycloak
sudo systemctl start keycloak

Configuración de Realms

Un realm es un espacio de nombres aislado que contiene usuarios, grupos, roles y aplicaciones. El realm master es para la administración de Keycloak y no debe usarse para aplicaciones.

Crear un realm para la organización

  1. Accede a la consola: https://sso.tudominio.com
  2. Haz clic en master en la esquina superior izquierda
  3. Selecciona Create Realm
  4. Configura:
    • Realm name: empresa (o el nombre de tu organización)
    • Enabled: ON

Configuración del realm mediante API

# Obtener el token de acceso del admin
TOKEN=$(curl -s -X POST "http://localhost:8080/realms/master/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=admin&password=TU_CLAVE_ADMIN&grant_type=password&client_id=admin-cli" | \
  python3 -c "import sys, json; print(json.load(sys.stdin)['access_token'])")

# Crear un nuevo realm via API REST
curl -X POST "http://localhost:8080/admin/realms" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "realm": "empresa",
    "enabled": true,
    "displayName": "Mi Empresa",
    "registrationAllowed": false,
    "resetPasswordAllowed": true,
    "loginWithEmailAllowed": true,
    "ssoSessionMaxLifespan": 36000,
    "accessTokenLifespan": 300
  }'

Gestión de Clientes OAuth2/OIDC

Un "client" en Keycloak representa una aplicación que delega la autenticación.

Crear un cliente para una aplicación web

  1. En el realm empresa, ve a Clients > Create client
  2. Configura:
    • Client type: OpenID Connect
    • Client ID: mi-aplicacion
    • Client authentication: ON (para apps con backend)
  3. En la siguiente pantalla:
    • Valid redirect URIs: https://app.tudominio.com/*
    • Web origins: https://app.tudominio.com

Crear cliente via CLI (kcadm.sh)

# Autenticar con kcadm
/opt/keycloak/bin/kcadm.sh config credentials \
  --server http://localhost:8080 \
  --realm master \
  --user admin \
  --password TU_CLAVE_ADMIN

# Crear el cliente
/opt/keycloak/bin/kcadm.sh create clients \
  -r empresa \
  -s clientId=mi-aplicacion \
  -s "name=Mi Aplicación Web" \
  -s protocol=openid-connect \
  -s publicClient=false \
  -s standardFlowEnabled=true \
  -s serviceAccountsEnabled=true \
  -s "redirectUris=[\"https://app.tudominio.com/*\"]" \
  -s "webOrigins=[\"https://app.tudominio.com\"]"

Obtener el Client Secret

# Via API
curl -s "http://localhost:8080/admin/realms/empresa/clients/{CLIENT_ID}/client-secret" \
  -H "Authorization: Bearer $TOKEN" | python3 -m json.tool

Flujo OAuth2 Authorization Code

# 1. Redirigir al usuario a la URL de autorización:
# https://sso.tudominio.com/realms/empresa/protocol/openid-connect/auth?
#   client_id=mi-aplicacion&
#   redirect_uri=https://app.tudominio.com/callback&
#   response_type=code&
#   scope=openid profile email

# 2. Intercambiar el código por un token
curl -X POST "https://sso.tudominio.com/realms/empresa/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=mi-aplicacion" \
  -d "client_secret=TU_CLIENT_SECRET" \
  -d "code=CODIGO_RECIBIDO" \
  -d "redirect_uri=https://app.tudominio.com/callback"

# 3. Obtener información del usuario
curl "https://sso.tudominio.com/realms/empresa/protocol/openid-connect/userinfo" \
  -H "Authorization: Bearer ACCESS_TOKEN"

Federación de Usuarios con LDAP

# Configurar la federación con OpenLDAP o Active Directory
# En el realm empresa: User Federation > Add provider > LDAP

Configuración para OpenLDAP:

  • Vendor: Other
  • Connection URL: ldap://ldap.empresa.com:389
  • Users DN: ou=usuarios,dc=empresa,dc=com
  • Bind DN: cn=admin,dc=empresa,dc=com
  • Bind Credential: contraseña del admin LDAP
  • Edit Mode: READ_ONLY (para no modificar el LDAP)
  • Sync mode: Force
# Probar la conexión LDAP desde la interfaz
# User Federation > Tu proveedor LDAP > Test connection
# User Federation > Tu proveedor LDAP > Test authentication

# Sincronizar todos los usuarios de LDAP
# User Federation > Tu proveedor LDAP > Sync all users

Configuración de SAML

Para integraciones con aplicaciones empresariales que usan SAML 2.0:

# Crear un cliente SAML
/opt/keycloak/bin/kcadm.sh create clients \
  -r empresa \
  -s clientId=https://app-saml.tudominio.com/saml \
  -s protocol=saml \
  -s "attributes.saml_assertion_consumer_url_post=https://app-saml.tudominio.com/saml/acs" \
  -s "attributes.saml.signing.certificate=CERTIFICADO_BASE64"

# Descargar los metadatos SAML del Identity Provider
curl -o idp-metadata.xml \
  "https://sso.tudominio.com/realms/empresa/protocol/saml/descriptor"

Proxy Inverso con Nginx

# /etc/nginx/sites-available/keycloak
server {
    listen 80;
    server_name sso.tudominio.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name sso.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/sso.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sso.tudominio.com/privkey.pem;

    client_max_body_size 10M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;

        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }
}
sudo certbot --nginx -d sso.tudominio.com
sudo ln -s /etc/nginx/sites-available/keycloak /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Solución de Problemas

Keycloak no inicia y los logs muestran errores de base de datos

# Verificar que PostgreSQL está activo y accesible
sudo systemctl status postgresql
psql -U keycloak -d keycloak -h localhost -c "SELECT 1;"

# Ver los logs de Keycloak
docker compose logs keycloak --tail 50
# O para instalación nativa:
sudo journalctl -u keycloak -n 50

Los redirects OAuth2 dan error

# Verificar que KC_HOSTNAME coincide con la URL pública
# El Client debe tener las URIs de redirect correctas configuradas

# Probar el endpoint de descubrimiento OIDC
curl https://sso.tudominio.com/realms/empresa/.well-known/openid-configuration

Keycloak detrás de Nginx muestra URLs con http en lugar de https

# Verificar que KC_PROXY=edge está configurado
# Y que Nginx envía el header X-Forwarded-Proto: https
grep -i "forwarded-proto" /etc/nginx/sites-available/keycloak

Alto consumo de memoria

# Ajustar la memoria de la JVM en Docker
# Añadir al docker-compose.yml en la sección environment:
KC_JAVA_OPTS: "-Xms512m -Xmx1024m"

Conclusión

Keycloak transforma la gestión de autenticación en una infraestructura dispersa en un sistema centralizado y estandarizado. Con un único servidor de SSO, todas las aplicaciones de la organización pueden delegar la autenticación, ofrecer inicio de sesión social, integrarse con el LDAP corporativo y gestionar roles y permisos de forma consistente. La compatibilidad con OAuth2, OIDC y SAML garantiza que cualquier aplicación moderna puede integrarse con mínimo esfuerzo de desarrollo.