docs(auth): two Pireon clients, production URLs and sign-in troubleshooting

- Registering clients: the authorization_code client is confidential and needs
  its secret; Pireon shows it once (rotate-secret if lost); containers must be
  recreated to read new environment variables.
- Production URLs (taskstream.pireon.dev, api.taskstream.pireon.dev) and their
  redirect URIs.
- "Si el login falla": each error seen while deploying (not configured,
  unauthorized_client, missing client_secret, invalid_client, redirect URI,
  expired code, wrong credentials, intermittent 404s) with cause and fix.
- READMEs mention both clients; Word/PDF regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 16:01:33 +02:00
parent b1002e6599
commit 6c3550ae9d
6 changed files with 36 additions and 5 deletions

View File

@@ -14,8 +14,9 @@ releases, comentarios y relaciones entre tickets, **en tiempo real**.
docker compose up -d --build # web en http://localhost:8080
```
Para entrar hace falta un cliente OAuth de Pireon en `.env` (`PIREON_CLIENT_ID` y `PIREON_CLIENT_SECRET`, ver
[Autenticación](docs/05-autenticacion.md#registrar-taskstream-como-cliente-en-pireon)). Para desarrollar:
Para entrar hacen falta los clientes OAuth de Pireon en `.env`: uno `authorization_code` (`PIREON_CLIENT_ID` /
`_SECRET`, «Entrar con Pireon») y uno `password` (`PIREON_PASSWORD_CLIENT_ID` / `_SECRET`, email y contraseña). Ver
[Autenticación](docs/05-autenticacion.md#registrar-taskstream-como-cliente-en-pireon). Para desarrollar:
```sh
npm install # @pi/ui necesita el token del Nexus de Pireon en ~/.npmrc

View File

@@ -64,17 +64,45 @@ Con un token tuyo de Pireon (scope `account:write`), `POST https://oauth.pireon.
`https://api.taskstream.pireon.dev/api/docs/oauth2-redirect.html` (ver
[API REST](03-api.md#33-rest-con-openapi-para-otras-apps))
→ `PIREON_CLIENT_ID` y `PIREON_CLIENT_SECRET`.
→ `PIREON_CLIENT_ID` y `PIREON_CLIENT_SECRET`. Al ser confidencial, **el secret es obligatorio**: sin él Pireon
rechaza el canje del código (ver la tabla de errores más abajo).
2. **Cliente para email y contraseña**: `{"name": "TaskStream (password)", "grant_type": "password"}`
→ `PIREON_PASSWORD_CLIENT_ID` y `PIREON_PASSWORD_CLIENT_SECRET`.
Ponlos en `.env` (o en el entorno del contenedor; en Dokploy, en _Environment_) y reinicia la API.
Pireon muestra el secret (`plain_secret`) **una sola vez**, en la respuesta de alta. Si se pierde, se genera otro con
`POST https://oauth.pireon.dev/api/clients/{client}/rotate-secret` (el anterior sigue valiendo 48 h).
Ponlos en `.env` (o en el entorno del contenedor; en Dokploy, en _Environment_) y reinicia la API; en Docker/Dokploy,
**recrea** el contenedor (redesplegar), porque un reinicio no relee el entorno.
En producción:
| Servicio | URL | Redirect URIs registradas en el cliente `authorization_code` |
| ---------- | ----------------------------------- | ----------------------------------------------------------------- |
| Web | `https://taskstream.pireon.dev` | `https://taskstream.pireon.dev/auth/callback` |
| API (REST) | `https://api.taskstream.pireon.dev` | `https://api.taskstream.pireon.dev/api/docs/oauth2-redirect.html` |
`GET /api/auth/config` le dice a la web qué formas de entrar hay: `clientId` del cliente `authorization_code` (o `null`:
la web oculta «Entrar con Pireon») y `passwordGrant`. Devuelve `null` si no hay ningún cliente; en ese caso el login
muestra el aviso y no deja entrar.
### Si el login falla
La API reenvía el error de Pireon con su `hint` entre paréntesis (lo que de verdad falla) y lo registra en su log como
`Pireon rejected <grant> for client <id>: … (hint: …)`.
| Error | Causa | Solución |
| ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| El login dice «Inicio de sesión no configurado» | `GET /api/auth/config` devuelve `null`: no hay ningún cliente en el entorno de la API | Define `PIREON_CLIENT_ID` y/o `PIREON_PASSWORD_CLIENT_ID` (con sus secrets) y recrea el contenedor |
| `unauthorized_client`: _not authorized to use this authorization grant type_ | El cliente no es del tipo que pide el flujo (p. ej. uno `password` en `PIREON_CLIENT_ID`) | Un cliente `authorization_code` en `PIREON_CLIENT_ID` y uno `password` en `PIREON_PASSWORD_CLIENT_ID` |
| `invalid_request` … _(Check the `client_secret` parameter)_ | El cliente es confidencial y la API no envía secret: la variable está vacía o no llega | Pon el secret en `PIREON_CLIENT_SECRET` (o `PIREON_PASSWORD_CLIENT_SECRET`) y redespliega |
| `invalid_client`: _Client authentication failed_ | El secret llega pero no es el de ese cliente | Revisa que id y secret sean del mismo cliente; si no lo tienes, rótalo |
| `invalid_request` … _(Invalid redirect URI)_ | La redirect URI del canje no es la de la autorización | Regístrala exactamente igual en el cliente (esquema, dominio y ruta, sin barra final) |
| `invalid_grant`: _Authorization code has expired / has been revoked_ | El código caducó o ya se usó (p. ej. al recargar `/auth/callback`) | Vuelve a «Entrar con Pireon» |
| `The user credentials were incorrect.` | Email o contraseña de Pireon incorrectos | — |
| Errores `404 Cannot GET/POST /api/…` intermitentes a través de la web | Otro `api` en la red compartida de Dokploy recibe parte de las peticiones | Ya resuelto con alias únicos (`task-stream-api`…), ver [Despliegue](07-despliegue.md#nombres-únicos-en-la-red) |
### Sesión en la web
- La sesión (`accessToken`, `refreshToken`, caducidad) se guarda en `localStorage` y se restaura al arrancar.

View File

@@ -92,3 +92,4 @@ exporta facades, una página tampoco puede tocar un store ni despachar eventos p
| La API no ve un evento nuevo al deserializar | La clase del evento no tiene `@AutowiredEvent` o no se importa |
| Un componente de `@pi/ui` lanza `Unable to find icon` | Falta registrar ese icono en `libs/web/shared/ui/src/lib/icons.ts` |
| Tablas antiguas (`projects`, `issues`, `outbox`) en tu Postgres local | Restos de una versión anterior sin event sourcing; `docker compose down -v` empieza de cero |
| El login con Pireon falla (`unauthorized_client`, `client_secret`…) | Configuración de los clientes OAuth: ver [Si el login falla](05-autenticacion.md#si-el-login-falla) |

View File

@@ -22,4 +22,5 @@ Cada librería de `libs/` tiene además su propio `README.md` con su responsabil
docker compose up -d --build # web en http://localhost:8080
```
Para entrar hace falta un cliente OAuth de Pireon en `.env` (ver [Autenticación](05-autenticacion.md#registrar-taskstream-como-cliente-en-pireon)).
Para entrar hacen falta dos clientes OAuth de Pireon en `.env` (`authorization_code` y `password`, ver
[Autenticación](05-autenticacion.md#registrar-taskstream-como-cliente-en-pireon)).

Binary file not shown.

Binary file not shown.