89 lines
4.9 KiB
Markdown
89 lines
4.9 KiB
Markdown
# Configurar la aplicación de Microsoft Graph (MSAL)
|
|
|
|
El proyecto lee y envía correo con Microsoft Graph usando una **aplicación registrada en Microsoft Entra ID** (antes Azure AD) y el flujo *client credentials*: no hay usuario interactivo, la aplicación se autentica sola con un `CLIENT_ID` y un `CLIENT_SECRET`. Este documento explica cómo obtener cada valor del `.env`.
|
|
|
|
| Variable del `.env` | De dónde sale |
|
|
|---------------------|---------------|
|
|
| `CLIENT_ID` | *Application (client) ID* de la aplicación |
|
|
| `TENANT_ID` | *Directory (tenant) ID* de la aplicación |
|
|
| `CLIENT_SECRET` | **Value** de un *client secret* creado en esa misma aplicación |
|
|
| `EMAIL` | Dirección del buzón que se lee y desde el que se envía |
|
|
|
|
> Los pasos describen el portal de Azure tal como suele verse; los nombres de los menús cambian de vez en cuando.
|
|
|
|
## 1. Registrar la aplicación
|
|
|
|
1. Entra a <https://entra.microsoft.com> (o al portal de Azure) con una cuenta con permisos para registrar aplicaciones.
|
|
2. **Identity → Applications → App registrations → New registration**.
|
|
3. Nombre, por ejemplo `descarga-factura-transporte`. En *Supported account types* elige **Accounts in this organizational directory only** (un solo tenant). No hace falta *Redirect URI*.
|
|
4. En la página **Overview** de la aplicación copia:
|
|
- **Application (client) ID** → `CLIENT_ID`
|
|
- **Directory (tenant) ID** → `TENANT_ID`
|
|
|
|
Los dos tienen que salir de la **misma** aplicación. Un `CLIENT_ID` de una aplicación con el `TENANT_ID` de otro directorio da el error `AADSTS700016`.
|
|
|
|
## 2. Dar permisos
|
|
|
|
Con el flujo *client credentials* se usan permisos de **aplicación**, no delegados.
|
|
|
|
1. **API permissions → Add a permission → Microsoft Graph → Application permissions**.
|
|
2. Agrega solo lo que el código usa:
|
|
|
|
| Permiso | Para qué | Dónde se usa |
|
|
|---------|----------|--------------|
|
|
| `Mail.Read` | Listar la bandeja de entrada y descargar adjuntos | `get_emails`, `download_attachments` |
|
|
| `Mail.Send` | Enviar las notificaciones | `send_email` |
|
|
|
|
3. Pulsa **Grant admin consent for <tu organización>**. Sin el consentimiento de administrador los permisos de aplicación no tienen efecto, aunque aparezcan en la lista.
|
|
|
|
> **Ojo:** un permiso de aplicación de correo vale, por defecto, para **todos los buzones** del tenant. Conviene limitarlo al buzón del proyecto con una política de acceso de aplicaciones en Exchange Online (*Application Access Policy* o *RBAC for Applications*). Eso lo configura un administrador de Exchange.
|
|
|
|
## 3. Crear el client secret
|
|
|
|
1. **Certificates & secrets → Client secrets → New client secret**.
|
|
2. Descripción y vencimiento (el portal permite hasta 24 meses).
|
|
3. Al crearlo, copia la columna **Value** y guárdala de inmediato en `CLIENT_SECRET`. **Solo se muestra una vez.**
|
|
|
|
Se confunde con frecuencia: la columna **Secret ID** es un identificador, no sirve como secret. Si usas el *Secret ID* el error es `AADSTS7000215`.
|
|
|
|
Cada secret **vence**. Anota la fecha en un calendario: cuando vence, el demonio deja de poder autenticarse y no lee ni envía correo (error `AADSTS7000222`). Para renovar sin cortes, crea el secret nuevo antes, actualiza el `.env`, reinicia el demonio y recién entonces borra el viejo.
|
|
|
|
## 4. Completar el `.env`
|
|
|
|
```
|
|
CLIENT_ID = <Application (client) ID>
|
|
TENANT_ID = <Directory (tenant) ID>
|
|
CLIENT_SECRET = <Value del secret>
|
|
EMAIL = buzon@tu-dominio.com
|
|
```
|
|
|
|
El `.env` no se sube a git. No pegues el secret en chats, tickets ni commits.
|
|
|
|
## 5. Verificar
|
|
|
|
Pide un token sin enviar nada. Imprime solo el resultado, no el secret:
|
|
|
|
```bash
|
|
python -c "
|
|
import re, outlook_utilities as o
|
|
try:
|
|
o.get_access_token(); print('OK: token obtenido')
|
|
except Exception as e:
|
|
print('ERROR', re.findall(r'AADSTS\d+', str(e)) or e)"
|
|
```
|
|
|
|
Un `OK` confirma `CLIENT_ID`, `TENANT_ID` y `CLIENT_SECRET`. No confirma los permisos sobre el buzón: eso se comprueba al listar o enviar un correo, por ejemplo con `tools/previsualizar_plantillas.py --escenario aceptado_sin_pago --enviar tu@correo`.
|
|
|
|
## Errores frecuentes
|
|
|
|
| Código | Significa | Qué revisar |
|
|
|--------|-----------|-------------|
|
|
| `AADSTS7000222` | El client secret **venció** | Crear un secret nuevo (paso 3) |
|
|
| `AADSTS7000215` | Secret inválido | Se usó el *Secret ID* en vez del *Value*, o hay un error al copiarlo |
|
|
| `AADSTS700016` | La aplicación no existe en ese directorio | `CLIENT_ID` y `TENANT_ID` deben ser de la misma aplicación (paso 1) |
|
|
| `AADSTS90002` | El tenant no existe | `TENANT_ID` mal escrito |
|
|
| `403` / `ErrorAccessDenied` al leer o enviar | Faltan permisos o consentimiento, o una política de acceso excluye al buzón | Paso 2 y la política de Exchange |
|
|
| `404` / `MailboxNotFound` | El buzón de `EMAIL` no existe o no tiene licencia | Revisar `EMAIL` |
|
|
|
|
Para cualquier código `AADSTS`, el mensaje completo trae un *Trace ID* y una explicación; la lista oficial está en la documentación de Microsoft Entra, sección de códigos de error de autenticación.
|