07 · Preguntas frecuentes y solución de problemas
Tabla general de códigos de error
El WsaVerificationError.code que lanza verifyWsa
| code | Causa común | Cómo diagnosticarlo |
|---|---|---|
InvalidSignature |
Clave incorrecta, token manipulado, uso de la clave equivocada Tier1/Tier2 | Confirma que la clave que usa el backend coincide con la registrada/distribuida; pasa la clave per-app tal cual, en formato de cadena, sin decodificar en hex |
WrongAudience |
El audience no coincide con el aud del token |
El audience debe ser exactamente igual al host de la URL registrada (como app.example.com), sin puerto/protocolo |
WrongIssuer |
La configuración del issuer ha sido modificada |
Mantén el valor por defecto gptbots-workspace |
Expired |
El token supera los 5 minutos, desfase del reloj del servidor | Sincroniza el reloj del servidor por NTP; el wsa es un token de arranque de un solo uso, no lo caches para reutilizarlo |
NotYetValid |
iat/nbf en el futuro |
Normalmente es una desincronización grave del reloj entre el emisor y el verificador |
MissingClaim |
Falta exp/sub/role/workspace_id |
Un token normal de la plataforma no carece de ellos; si aparece, indica que el origen del token es sospechoso |
UnsupportedAlgorithm |
El alg no está en la lista blanca |
Por defecto solo HS256; RS256 requiere explícitamente algorithms:['RS256'] + publicKey |
InvalidToken |
Token vacío/estructura inválida/truncado | Comprueba si el frontend obtiene correctamente el wsa completo y si la URL ha sido reescrita por una capa intermedia |
Fase de canje de /token (pull)
| code | Significado | Condición de activación |
|---|---|---|
403209 |
Invalid grant | El code falta, ha expirado o ya ha sido usado (reproducción). El code solo puede usarse una vez |
403210 |
Invalid verifier | El codeVerifier de PKCE no coincide con el code_challenge del inicio |
sign-token del modo push (invocado por el frontend del espacio de trabajo, solo a título informativo)
| code | Significado | Condición de activación |
|---|---|---|
40000 |
Parameter error | La URL no está registrada, o el auth_mode no es workspace_account |
40100 |
Permission deny | No autenticado o sesión caducada |
40105 |
Require member of project | Quien hace clic no es miembro de ese espacio de trabajo |
40320 |
Member not found | La cuenta ha sido dada de baja/eliminada |
FAQ
P: ¿Debo elegir push o pull?
R: Si la entrada está en la página «Extensiones» del espacio de trabajo y quieres hacer una «app embebida» → push (lo más sencillo). Si tu app es un sitio independiente y quieres colocar un botón «Iniciar sesión con GPTBots» → pull (M-Auth, más seguro, el wsa no entra en el navegador). Consulta 02.
P: ¿Puedo decodificar el JWT directamente en el frontend para obtener la información del usuario?
R: Puedes decodificarlo para verlo, pero no puedes tomarlo como identidad de confianza: sin la clave no se puede verificar la firma, y el payload puede falsificarse. Cualquier decisión de autorización debe basarse en el resultado de verifyWsa del backend. Consulta 05 §5.
P: ¿Qué hago si el wsa ha expirado?
R: El wsa es solo un token de arranque de un solo uso (5 minutos). Verifícalo una vez en el aterrizaje, canjéalo por tu propia sesión y, a partir de entonces, usa siempre tu sesión y no vuelvas a depender del wsa. La próxima vez que el usuario abra la app desde la página de extensiones, obtendrá un nuevo wsa.
P: ¿El consumeHandoff de la página de aterrizaje lanza «no handoff token present»?
R: Significa que la URL actual no tiene ?wsa=: puede que el usuario haya accedido directamente, o que el wsa ya haya sido eliminado por un intercambio exitoso anterior. Distingue entre «primer aterrizaje con token» y «acceso normal»; para el segundo, sigue tu propia rama de inicio de sesión/modo anónimo.
P: ¿El callback del inicio de sesión pull devuelve StateMismatch / MissingRequest?
R: MissingRequest = no invocaste antes startWorkspaceLogin en la misma sesión del navegador (el verifier de PKCE se guarda en sessionStorage, y se pierde al cambiar de pestaña o borrar el almacenamiento). StateMismatch = el state del callback no coincide con el almacenado (protección CSRF); confirma que no cambias de dispositivo/sesión.
P: ¿El inicio de sesión pull devuelve CryptoUnavailable?
R: PKCE requiere Web Crypto, que solo está disponible en un contexto seguro (HTTPS o localhost). Usa HTTPS o localhost local para depurar.
P: ¿El redirect_uri devuelve invalid_request / vuelve a la página de selección de organización?
R: El scheme + host del redirect_uri debe ser exactamente igual al de client_id (la URL registrada). Una app https no puede configurar un callback http; el host debe coincidir. La plataforma jamás redirige a una dirección no verificada, por lo que vuelve a la página de selección de organización con ?error=invalid_request.
P: ¿Cómo se usa la clave per-app como clave HMAC? ¿Hay que decodificarla en base64/hex?
R: Pásala tal cual, en formato de cadena (tanto el SDK como la plataforma usan directamente los bytes UTF-8 como clave HMAC). La clave de Tier 2 tiene la forma wext_+64 hex; la cadena completa es la clave, no la vuelvas a decodificar.
P: ¿Puedo usar el SDK en un proyecto CommonJS?
R: El SDK es ESM. En un proyecto CJS, usa import() dinámico, o migra los módulos correspondientes a ESM.
P: ¿Cómo cambio el icono/nombre?
R: En Tier 2 se edita en la gestión del espacio; en Tier 1, contacta con el equipo de operaciones de la plataforma para modificar la entrada del diccionario.
P: ¿Qué pasa si el administrador desactiva mi app?
R: El administrador de la organización puede desactivar la app en la gestión del espacio (incluida la visibilidad de las apps públicas de la plataforma en esa organización). Tras la desactivación, los miembros de esa organización dejan de ver la entrada en la página de extensiones, y la plataforma tampoco volverá a emitir un wsa para esa organización (se rechaza tanto en push como en pull).
Lista de comprobación de la integración
-
audience== host de la URL registrada (la causa más común deWrongAudience) - La clave del backend coincide con la registrada/distribuida, y está solo en el backend
- El reloj del servidor está sincronizado por NTP (
Expired/NotYetValidsuelen deberse al reloj) - Tras el aterrizaje, elimina el
wsa/codeconhistory.replaceState - Canjéalo por la sesión propia, y las peticiones posteriores no transmiten el
wsa - Pull: contexto seguro HTTPS/localhost;
redirect_uridel mismo dominio queclient_id - Aislamiento multitenant por
workspace_id
Referencias
- Cada documento de esta guía: 01 Inicio rápido · 02 Conceptos clave · 03 Push · 04 Pull · 05 Verificación y seguridad · 06 API
