<!-- review: finished -->

<a id="oidc-config"></a>

# Configuración de Autenticación OIDC

Esta guía explica cómo configurar la autenticación OpenID Connect (OIDC)
utilizando Google como proveedor de identidad
y el servidor web Angie con scripting Lua.

La implementación protege endpoints internos con autenticación OAuth2/OIDC
y demuestra una forma de restringir el acceso basándose en dominios de correo electrónico.
Este es solo un ejemplo de enfoque; puede implementar el control de acceso como prefiera,
como mantener listas de usuarios específicos permitidos, verificar la pertenencia a un dominio
o atributos de grupo en la respuesta del proveedor, o utilizar claims personalizados de su
sistema IAM privado.

<a id="architecture"></a>

## Arquitectura

La configuración de OIDC sugerida aquí consiste en:

- Angie - con soporte de módulo Lua para procesamiento OIDC
- [lua-resty-openidc](https://github.com/zmartzone/lua-resty-openidc) - Biblioteca Lua de OpenResty para autenticación OIDC
- Google OAuth2 - Proveedor de identidad para autenticación de usuarios
- Docker Compose - Utilizado en este ejemplo solo para inicio rápido;
  use el enfoque de despliegue que prefiera en producción

<a id="prerequisites"></a>

## Requisitos Previos

Antes de configurar la autenticación OIDC, asegúrese de tener:

1. Servidor web Angie con soporte del [módulo Lua](https://es.angie.software//angie/docs/installation/external-modules/lua.md#external-lua)
2. Docker y Docker Compose (para despliegue)
3. Un proyecto en Google Cloud Console
4. Credenciales OAuth2 de Google

<a id="google-oauth2-setup"></a>

## Configuración de Google OAuth2

Para configurar Google como su proveedor OIDC:

1. Navegue a la [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
2. Cree un nuevo proyecto o seleccione uno existente
3. Configure la pantalla de consentimiento OAuth para su proyecto (Externa o Interna) y publíquela para que los usuarios puedan autenticarse
4. Cree credenciales OAuth2:
   - Tipo de aplicación: Aplicación web
   - URIs de redirección autorizadas: `http://localhost/auth/callback`
5. Guarde su `client_id` y `client_secret` para la configuración

#### NOTE
Los servicios estándar de Google Identity ya soportan OIDC; no se requiere la API heredada de Google+.
Habilite APIs adicionales de Google solo si su aplicación necesita sus datos.

<a id="configuration-setup"></a>

## Configuración Inicial

Comencemos con los archivos de configuración necesarios para la configuración de OIDC.

<a id="docker-compose-configuration"></a>

### Configuración de Docker Compose

El despliegue de Docker utiliza el siguiente archivo de configuración:

```yaml
services:
  angie:
    image: docker.angie.software/angie:templated
    environment:
      ANGIE_LOAD_MODULES: "lua"
    ports:
      - 80:80
    volumes:
      - ./files/etc/angie/http.d:/etc/angie/http.d
```

Esta configuración hace lo siguiente:

- Utiliza la [imagen templated de Angie](https://es.angie.software//angie/docs/installation/docker.md#docker-templated) con soporte del módulo Lua
- Carga el [módulo Lua](https://es.angie.software//angie/docs/installation/external-modules/lua.md#external-lua) para funcionalidad OIDC
- Mapea el puerto 80 para acceso HTTP
- Monta archivos de configuración desde el directorio local

Para una demostración plug-and-play,
descargue el [`paquete de inicio rápido OIDC`](https://es.angie.software//angie/docs/configuration/oidc-sample-config.zip),
establezca su `client_id` y `client_secret` en `files/etc/angie/http.d/oidc.lua`,
y todo funcionará de inmediato.

<a id="oidc-authentication-script"></a>

### Script de Autenticación OIDC

Cree un script de autenticación OIDC
que maneje la lógica de autenticación utilizando la biblioteca `lua-resty-openidc`:

```lua
access_by_lua_block {
    local res, err = require("resty.openidc").authenticate({
        redirect_uri = "http://localhost/auth/callback",
        discovery = "https://accounts.google.com/.well-known/openid-configuration",
        logout_path = "/auth/logout",
        redirect_after_logout_uri = "/auth/logged-out",
        revoke_tokens_on_logout = true,
        client_id = "YOUR_CLIENT_ID",
        client_secret = "YOUR_CLIENT_SECRET"
    })
}
```

Parámetros de configuración:

- `redirect_uri`: URL de callback después de autenticación exitosa
- `discovery`: Endpoint de descubrimiento OIDC de Google
- `logout_path`: Ruta para cierre de sesión del usuario
- `redirect_after_logout_uri`: Destino de redirección después del cierre de sesión
- `revoke_tokens_on_logout`: Revocar tokens al cerrar sesión por seguridad
- `client_id` y `client_secret`: Sus credenciales OAuth2 de Google

<a id="angie-configuration"></a>

### Configuración de Angie

Configure Angie con los bloques [location](https://es.angie.software//angie/docs/configuration/modules/http/index.md#location) necesarios
para la autenticación OIDC.

<a id="protected-resources"></a>

#### Recursos Protegidos

Para proteger recursos con autenticación OIDC:

```nginx
location /internal/ {
    include /etc/angie/http.d/oidc.lua;
    proxy_pass http://127.0.0.1/status/;
}
```

Esta configuración hace lo siguiente:

- Protege la ruta `/internal/` con autenticación OIDC
- Redirige las solicitudes autenticadas a la [API interna](https://es.angie.software//angie/docs/configuration/modules/http/http_api.md#http-api)
  en `/status/`

<a id="authentication-endpoints"></a>

#### Endpoints de Autenticación

Configure los endpoints del flujo OAuth2:

```nginx
location /auth/callback {
    include /etc/angie/http.d/oidc.lua;
}

location /auth/logout {
    include /etc/angie/http.d/oidc.lua;
}

location /auth/logged-out {
    default_type text/plain;
    return 200 "Ha cerrado sesión. ¡Adiós!";
}
```

Funciones de los endpoints:

- `/auth/callback`: Maneja el callback OAuth2 de Google
- `/auth/logout`: Inicia el cierre de sesión del usuario
- `/auth/logged-out`: Página de destino después del cierre de sesión exitoso

<a id="internal-api-access"></a>

#### Acceso a la API Interna

Configure el acceso restringido a la API interna:

```nginx
location /status/ {
    api     /status/;
    allow   127.0.0.1;
    deny    all;
}
```

Esto proporciona:

- Acceso a la [API de estado](https://es.angie.software//angie/docs/configuration/modules/http/http_api.md#http-api) de Angie
- Acceso solo desde localhost (127.0.0.1)
- Protección OIDC cuando se accede a través de `/internal/`

<a id="deployment-steps"></a>

## Pasos de Despliegue

Siga estos pasos para desplegar la autenticación OIDC:

<a id="configuration-update"></a>

### Actualización de Configuración

1. Actualice las credenciales OAuth2 en su script Lua OIDC:

   Reemplace los valores de marcador de posición en `oidc.lua`:
   - `client_id` con su ID de cliente OAuth2 de Google
   - `client_secret` con su secreto de cliente OAuth2 de Google

<a id="service-startup"></a>

### Inicio del Servicio

1. Inicie los servicios de Docker:
   ```console
   $ docker-compose up -d
   ```
2. Verifique el despliegue:
   - Navegue a `http://localhost/internal/`
   - Debería ser redirigido a Google para autenticación
   - Después del inicio de sesión exitoso, accederá al contenido protegido

<a id="security-configuration"></a>

## Configuración de Seguridad

<a id="email-domain-restriction"></a>

### Restricción de Dominio de Correo Electrónico

Implemente validación de dominio para restringir el acceso por dominio de correo electrónico:

```lua
if not string.match(res.user.email, "gmail.com$") then
    ngx.exit(ngx.HTTP_FORBIDDEN)
end
```

Para entornos de producción, considere lo siguiente:

- Reemplazar `gmail.com` con el dominio de su organización
- Implementar una lista blanca de direcciones de correo electrónico permitidas
- Agregar control de acceso basado en roles

<a id="token-management"></a>

### Gestión de Tokens

La implementación de OIDC incluye características de seguridad:

- Los tokens se revocan automáticamente al cerrar sesión (`revoke_tokens_on_logout = true`)
- Las sesiones son gestionadas de forma segura por la biblioteca lua-resty-openidc
- Todos los flujos de autenticación siguen las mejores prácticas de seguridad OAuth2/OIDC

#### WARNING
Para despliegues en producción:

- Utilice siempre HTTPS para callbacks OAuth2
- Almacene los secretos de cliente de forma segura, nunca en control de versiones
- Implemente políticas adecuadas de tiempo de espera y renovación de sesiones
- Monitoree los registros de autenticación para eventos de seguridad

<a id="authentication-flow"></a>

## Flujo de Autenticación

El flujo de autenticación OIDC sigue los procedimientos estándar OAuth2/OIDC:

1. El usuario accede a una URL protegida (por ejemplo, `http://localhost/internal/`)
2. Si no está autenticado, el usuario es redirigido a Google OAuth2
3. El usuario se autentica con credenciales de Google
4. Google redirige de vuelta a `/auth/callback` con código de autorización
5. El servidor intercambia el código por token de acceso y token de ID
6. La información del usuario es validada (incluyendo verificación de dominio de correo electrónico)
7. Se concede acceso al usuario al recurso protegido

El proceso de cierre de sesión asegura la terminación segura de la sesión:

1. El usuario navega a `http://localhost/auth/logout`
2. Los tokens se revocan en el endpoint OAuth2 de Google
3. Los datos de sesión local se eliminan
4. El usuario es redirigido a `/auth/logged-out`

<a id="advanced-configuration"></a>

## Configuración Avanzada

Para restringir el acceso a un dominio de organización específico:

```lua
if not string.match(res.user.email, "suempresa.com$") then
    ngx.exit(ngx.HTTP_FORBIDDEN)
end
```

Para organizaciones con múltiples dominios permitidos:

```lua
local allowed_domains = {"empresa1.com", "empresa2.com", "gmail.com"}
local email_valid = false

for _, domain in ipairs(allowed_domains) do
    if string.match(res.user.email, domain .. "$") then
        email_valid = true
        break
    end
end

if not email_valid then
    ngx.exit(ngx.HTTP_FORBIDDEN)
end
```

<a id="user-information-access"></a>

### Acceso a Información del Usuario

Acceda a claims adicionales del usuario desde el proveedor OIDC:

```lua
-- Acceder a información del usuario desde el token de ID
local user_name = res.user.name
local user_picture = res.user.picture
local user_locale = res.user.locale
local user_email = res.user.email
```

Estos valores se pueden utilizar para registro, personalización o decisiones adicionales de control de acceso.
