Conceptos clave
Esta guía ayudará a los desarrolladores a entender: a qué nivel de extensión perteneces, qué modo de integración vas a usar, qué contiene el token wsa y «hasta qué punto» vas a usarlo.
Dos modos de integración: push vs pull
La plataforma te entrega la identidad por dos caminos. Se trata del mismo contrato wsa; la diferencia está solo en «cómo obtienes la información de autenticación de identidad».
Push (Push handoff) — consulta 03
El usuario abre tu app desde la página «Extensiones» del espacio de trabajo, y la plataforma concatena el wsa a la URL de tu página de aterrizaje y te lo envía:
https://app.example.com/landing?wsa=<JWT>
- La entrada está dentro del espacio de trabajo.
- El desarrollador solo necesita consumir el
?wsa=en la página de aterrizaje; es lo más sencillo. - Adecuado para: una «app embebida» dentro de la barra lateral del espacio de trabajo.
Pull (Pull / M-Auth) — consulta 04
La app de extensión del desarrollador coloca por sí misma un botón «Login with Workspace»; al hacer clic, el usuario entra al inicio de sesión de GPTBots ➡️ selecciona el espacio de trabajo ➡️ y regresa con el estado de sesión. Utiliza código de autorización OAuth2 + PKCE:
- La entrada está en la página de inicio de sesión de la app de extensión del desarrollador.
- El navegador solo obtiene un
codede un solo uso; el verdaderowsalo canjea tu backend concode+ PKCE, y nunca entra en la URL del navegador. - Adecuado para: cuando la app de extensión del desarrollador es un sitio independiente y desea ofrecer «Iniciar sesión con la cuenta del espacio de trabajo de GPTBots».
| Push | Pull (M-Auth) | |
|---|---|---|
| Entrada de inicio de sesión | Página «Extensiones» del espacio de trabajo | La página de tu app (botón de inicio de sesión) |
| Cómo llega el token a tus manos | La URL ?wsa= se envía directamente a la página de aterrizaje |
El frontend obtiene el code, el backend canjea el wsa |
¿El navegador vio el wsa? |
Sí (debe eliminarse de inmediato tras el aterrizaje) | Nunca (más seguro) |
| ¿Requiere PKCE? | No | Sí (S256 obligatorio) |
| Método del SDK en el frontend | consumeHandoff |
startWorkspaceLogin + completeWorkspaceLogin |
Guía de uso de la información de autenticación de identidad
La plataforma solo se encarga de «transmitir la identidad»; el desarrollador decide de forma independiente si la usa:
| Nivel | Significado | Lo que debe hacer el desarrollador |
|---|---|---|
use |
Verificar la firma + establecer sesión + controlar el acceso a funciones según el role |
consumeHandoff / completeWorkspaceLogin, y verifyWsa en el backend |
receive-only |
Leer la identidad para mostrarla/hacer telemetría, pero sin crear sesión ni control de acceso; sigue usando tu propia autenticación o modo anónimo | Solo readHandoffToken() (función pura, sin efectos secundarios) |
ignore |
No leer nada, equivalente a auth_mode=none; es simplemente un enlace externo común |
No hacer nada |
Tanto
verifyWsacomoreadHandoffTokenson funciones puras, por lo que «recibir pero no usar» no tiene coste alguno.
Correspondencia con el auth_mode del registro:
auth_mode = workspace_account: la plataforma firma elwsay lo concatena a la URL (push) / admite M-Auth (pull), y puedes obtener la identidad.auth_mode = none: la plataforma redirige directamente, la URL no lleva ninguna información de autenticación y no recibes la identidad (corresponde aignore).
Contrato del token wsa (JWT)
El wsa es un JWT firmado con HS256 (HMAC-SHA256), con una validez de 5 minutos (exp = iat + 300).
Claims estándar
| Claim | Tipo | Descripción |
|---|---|---|
iss |
string | Fijo en gptbots-workspace, verificación obligatoria |
aud |
string | Host de la app de extensión del desarrollador (por ejemplo, app.example.com), obtenido a partir de la URL de registro, verificación obligatoria |
sub |
string | El accountId del usuario del espacio de trabajo, globalmente único, puede usarse como clave primaria del ID de usuario del lado del desarrollador |
iat |
number (segundos) | Momento de emisión |
exp |
number (segundos) | Momento de expiración, fijo en iat + 300, verificación obligatoria |
Claims de negocio
| Claim | Tipo | Descripción |
|---|---|---|
role |
string | OWNER / ADMIN / MEMBER — el rol del usuario en ese espacio de trabajo |
workspace_id |
string | ID del espacio de trabajo (es decir, projectId), clave de aislamiento multitenant |
username |
string | Apodo del usuario (puede estar ausente) |
email |
string | Correo del usuario (puede estar ausente) |
avatar |
string | URL del avatar (puede estar ausente) |
app_name |
string | Nombre de la app de extensión correspondiente a esa redirección (útil para auditoría, puede estar ausente) |
Campos ausentes:
username/avatar/app_nameno aparecerán en el payload cuando los datos de origen estén vacíos; asegúrate de gestionar los valores nulos y no des por hecho que siempre estarán presentes.
Ejemplo de payload
{
"iss": "gptbots-workspace",
"aud": "app.example.com",
"sub": "65f7c8a1d8f3a40012345678",
"iat": 1730000000,
"exp": 1730000300,
"username": "Juan Pérez",
"email": "juan.perez@example.com",
"avatar": "https://cdn.example.com/avatar/u123.png",
"role": "ADMIN",
"workspace_id": "65a0000000000000000abcde",
"app_name": "Sistema de Revisión de Contratos"
}
role≠ los permisos dentro de tu app. Elrolesolo refleja el rol del usuario en ese espacio de trabajo; se recomienda tratarlo como un «mapeo de permisos por defecto en el primer aterrizaje», mientras tu app mantiene su propio modelo de permisos.
Siguiente paso: según el modo que hayas elegido, lee 03-Integración push o 04-Inicio de sesión pull; sea cual sea, lee siempre 05-Verificación de token y seguridad.
