Resumen
Las conexiones son credenciales que un usuario posee para un servicio externo (Linear, GitHub, Slack, …). Tu aplicación declara cómo se obtienen esas credenciales — un proveedor de conexión — y las consume en tiempo de ejecución para realizar llamadas autenticadas a la API de terceros. OAuth 2.0 está integrado. Los servicios con su propio flujo de conexión — una página de inicio de sesión alojada, un identificador de cuenta entregado mediante webhook — utilizan un proveedorcustom, donde tu aplicación controla el flujo y Twenty conserva el usuario, el espacio de trabajo y la conexión guardada. Los futuros tipos de credenciales (tokens de acceso personal, claves de API, autenticación básica) se integrarán en la misma interfaz — las aplicaciones que ya usan defineConnectionProvider({ type: 'oauth', ... }) no necesitarán migrar.
defineConnectionProvider
Declara cómo se obtienen las conexiones de tu aplicación
defineConnectionProvider
Declara cómo se obtienen las conexiones de tu aplicación
WORKSPACE (el predeterminado), un miembro hace clic en “Agregar conexión” en la configuración de tu aplicación, completa la pantalla de consentimiento del proveedor y se crea una fila ConnectedAccount en su espacio de trabajo. Consulta “Conexiones de espacio de trabajo o personales” para los proveedores USER.Una configuración funcional necesita dos archivos — el proveedor de conexión y una declaración serverVariables correspondiente en defineApplication que contiene las credenciales del cliente OAuth.namees la cadena de identificador única utilizada enlistConnections({ providerName })(kebab-case, debe coincidir con^[a-z][a-z0-9-]*$).displayNamese muestra en la pestaña General de la aplicación y en la lista de herramientas de IA.scopedetermina quién se conecta:'WORKSPACE'(el predeterminado) para las conexiones compartidas con todo el espacio de trabajo,'USER'para las conexiones que cada miembro realiza por sí mismo. Consulta “Conexiones de espacio de trabajo o personales” a continuación.logoes una ruta a un recurso incluido en la carpetapublic/de tu aplicación, que se sirve a través de los recursos públicos de la aplicación. Cuando se omite, la pestaña General usa un marcador de posición creado a partir dedisplayName.clientIdVariable/clientSecretVariableson nombres, no valores — deben coincidir con las claves declaradas endefineApplication.serverVariables. Losclient_idyclient_secretreales los introduce el administrador del servidor a través de la interfaz de registro de la aplicación; nunca se incluyen en tu repositorio.- Usa
serverVariables(noapplicationVariables) — las credenciales de OAuth son a nivel de servidor y hay una aplicación OAuth por servidor de Twenty. - Hasta que ambas
serverVariablesestén completas, la pestaña General de la aplicación muestra un aviso de “requiere administrador del servidor” y el botón “Agregar conexión” está deshabilitado. typees'oauth'(con un bloqueoauth) o'custom'(con un bloquecustom, consulta “Flujos de conexión personalizados”). El discriminador es compatible hacia adelante: tipos futuros ('pat','api-key', …) agregará nuevos bloques de subconfiguración junto a estos.
Flujos de conexión personalizados
Conecta servicios que no son proveedores de OAuth
Flujos de conexión personalizados
Conecta servicios que no son proveedores de OAuth
type: 'custom' y dos funciones lógicas:authorizeLogicFunction con una callbackUrl que lo contiene. Devuelve a dónde enviar al usuario:callbackUrl al servicio sin cambios. Twenty la acepta como una redirección del navegador (GET) y como una notificación del servidor (POST), y ejecuta callbackLogicFunction para cada solicitud con su método, parámetros de consulta (sin state), encabezados, cuerpo analizado y rawBody (los bytes exactos de la solicitud, null en GET). Devuelve la cuenta que demuestra la solicitud o null cuando no contiene ninguna; normalmente, el navegador regresa mientras el id de la cuenta se envía mediante una notificación:callbackUrl solo demuestra que la solicitud contiene esa URL, no que el servicio la envió. Cuando el servicio firma sus notificaciones, verifica la firma sobre rawBody antes de confiar en el cuerpo. Los encabezados están en minúsculas, y cookie, authorization y proxy-authorization nunca se transmiten:onConnectLogicFunction no se ejecuta. onConnectLogicFunction se ejecuta cuando se crea, reconecta o restaura una conexión, pero no de nuevo cuando el servicio informa de una cuenta que ya está conectada. El estado caduca después de una hora, por lo que se rechaza una notificación que llegue más tarde. Los servicios suelen reintentar las notificaciones: una repetición para una cuenta ya conectada actualiza esa conexión, por lo que es seguro devolver de nuevo la misma cuenta.Twenty no actualiza ni revoca las conexiones personalizadas. Libera lo que el servicio retiene para la cuenta en onDisconnectLogicFunction.El type de un proveedor, al igual que su scope, no puede cambiar una vez sincronizado: para mover un servicio entre oauth y custom, declara un nuevo proveedor con un nuevo universalIdentifier.Los proveedores personalizados se incluyen con Twenty 2.52.0.Identifica la cuenta conectada
Evita que una reconexión cambie silenciosamente las cuentas de origen
Identifica la cuenta conectada
Evita que una reconexión cambie silenciosamente las cuentas de origen
identifyAccountLogicFunction en una función de lógica de la misma aplicación que devuelva un identificador estable para la cuenta asociada al token recién emitido:timeoutSeconds de la función a 10, independientemente de lo que declare el manifiesto; limítalo a una única solicitud al endpoint «quién soy» del proveedor. El hook de conexión, si lo hay, se sigue ejecutando después, una vez guardada la conexión.Carga útil. El controlador recibe el token de acceso provisional. Aún no se ha guardado, por lo que getConnection no puede devolverlo; úsalo directamente y no lo registres.externalAccountIddebe ser estable durante toda la vida de la cuenta ascendente (un id de equipo, un id de organización o un id de usuario), nunca un nombre que el usuario pueda cambiar. Twenty lo recorta y lo almacena en la conexión durante la primera conexión.handle, cuando se devuelve, sustituye al handle que Twenty determinaría de otro modo (el correo electrónico delid_tokende OIDC o el correo electrónico del usuario que se conecta). Devuelve algo que un usuario reconozca, como el nombre del espacio de trabajo de Slack.- Devuelve
{ externalAccountId: null }cuando el proveedor no tiene un id estable que ofrecer. Twenty se comporta entonces como si no se hubiera declarado ninguna función de identificación: no se almacena ningún id, una reconexión borra cualquier id almacenado anteriormente y no se comprueban las reconexiones. Unnullsin más o la ausencia de un retorno se tratan como un error, por lo que un controlador que olvide devolver algo no puede desactivar silenciosamente la comprobación. - Si la función lanza una excepción, agota el tiempo de espera o devuelve cualquier otra cosa, la conexión no se guarda y el usuario vuelve a la página de configuración con un error. Lanza una excepción solo cuando realmente no puedas identificar la cuenta.
externalAccountId devuelto con el almacenado en la conexión. Si difieren, se rechaza la devolución de llamada antes de que se escriba nada: los tokens, el identificador y el ámbito existentes permanecen como estaban, el hook de conexión no se ejecuta y el usuario ve qué cuenta autorizó y a cuál pertenece la conexión. Las conexiones creadas antes de que tu aplicación declarara la función aún no tienen un id almacenado; su próxima reconexión lo almacenará.Twenty no elimina duplicados según externalAccountId: conectar dos veces la misma cuenta upstream mediante Agregar conexión crea dos conexiones. El id se expone en listConnections y getConnection, por lo que una aplicación que quiera una conexión por cuenta ascendente puede detectar los duplicados por sí misma (por ejemplo, en su hook al conectar).Cómo escribir la función. La mayoría de los proveedores exponen un único endpoint que describe el token actual. Para Slack es auth.test, que devuelve el espacio de trabajo (team_id, team) y el usuario detrás del token:String(id).La identificación está disponible a partir de Twenty 2.48.0. Si tu aplicación depende de ella, declara "engines": { "twenty": ">=2.48.0" } en su package.json.Ejecutar una función de lógica al conectar
Reaccionar en el momento en que se establece una conexión
Ejecutar una función de lógica al conectar
Reaccionar en el momento en que se establece una conexión
team_id del espacio de trabajo con el que se asociarán los eventos entrantes. Establece onConnectLogicFunction para que haga referencia a una función de lógica en la misma aplicación (por su universalIdentifier), y se ejecutará justo después de que se cree el ConnectedAccount.getConnection(connectedAccountId) para leer el token de acceso reciente y llamar a la API del proveedor (por ejemplo, Slack auth.test) o para conservar un mapeo con el almacenamiento de pares clave-valor.Ejecutar una función de lógica al desconectar
Limpieza cuando se desconecta o se elimina una conexión.
Ejecutar una función de lógica al desconectar
Limpieza cuando se desconecta o se elimina una conexión.
team_id al conectarse, por ejemplo, debe liberar esa reserva para que otro espacio de trabajo pueda conectar ese mismo espacio de trabajo de Slack. Configura onDisconnectLogicFunction para que haga referencia a una función de lógica en la misma aplicación; se ejecuta cuando se desconecta la conexión y de nuevo cuando se elimina.ConnectedAccount y su token siguen presentes, por lo que getConnection(connectedAccountId) se resuelve y el controlador puede liberar todo lo que registró de forma remota. Al eliminar, es posible que las credenciales ya no estén disponibles (un miembro puede eliminar una conexión que desconectó anteriormente), así que haz que el controlador sea idempotente y conserva el estado que necesita (un team_id, un ID de suscripción externa) en el almacén de clave-valor, escrito en el momento de la conexión y con la clave connectedAccountId. Que sea breve: se ejecuta dentro de la solicitud, por lo que su timeoutSeconds es el límite máximo de duración de esa solicitud.El hook se dispara cuando una conexión se desconecta o se elimina por sí sola. Desinstalar la app elimina sus conexiones mediante una cascada de base de datos, por lo que el hook no se ejecuta en ese caso. Declara una uninstallLogicFunction en defineApplication para esa ruta: se ejecuta antes de que se eliminen los metadatos de la app, por lo que todavía puede llamar a listConnections y limpiar lo que quede.listConnections / getConnection
Usa conexiones desde una función de lógica
listConnections / getConnection
Usa conexiones desde una función de lógica
listConnections({ providerName }) devuelve las filas ConnectedAccount de esta aplicación para el proveedor indicado, con tokens de acceso actualizados.- Pasa
{ providerName }para filtrar por proveedor; omítelo para obtener todas las conexiones que posee esta aplicación en todos los proveedores. - El servidor actualiza de forma transparente el token de acceso antes de devolver la respuesta. Tu controlador siempre ve un token utilizable (o
authFailedAtestablecido). getConnection(id)es el equivalente de una sola fila.
reportConnectionAuthFailure
Indica a la plataforma que una credencial ya no es válida
reportConnectionAuthFailure
Indica a la plataforma que una credencial ya no es válida
authFailedAt por sí sola únicamente cuando falla una actualización de OAuth. Los proveedores cuyos tokens nunca se actualizan (por ejemplo, un token de bot de Slack) fallan únicamente en el momento de la llamada dentro de tus controladores, por lo que la fila de conexión en la configuración seguiría mostrando Conectada mientras falla cada llamada. Cuando tu código recibe un rechazo de autenticación definitivo, infórmalo:authFailedAt y el motivo opcional en la conexión. La fila de configuración cambia a Se necesita reconectar con un botón Reconectar, la página de detalles de la conexión muestra el motivo y getConnection comienza a lanzar AppConnectionAuthFailedError para esa fila. La marca y el motivo se borran automáticamente cuando el usuario se reconecta. Se rechaza un reason de más de 1000 caracteres, así que trunca las cargas útiles del proveedor antes de pasarlas.Informa únicamente los fallos que una reconexión realmente corregiría (un rechazo de la clase invalid_auth del proveedor), nunca los errores transitorios de red. Una aplicación solo puede informar de sus propias conexiones, y un usuario de solicitud solo puede informar de sus propias credenciales personales.La mutación detrás de este asistente se incluye con Twenty 2.40.0, por lo que llamarla en un servidor anterior falla. Si tu aplicación la usa, declara la dependencia en tu package.json: "engines": { "twenty": ">=2.40.0" }.Conexiones de espacio de trabajo o personales
Elige quién se conecta con el ámbito del proveedor
Conexiones de espacio de trabajo o personales
Elige quién se conecta con el ámbito del proveedor
- Compartida en el espacio de trabajo (
'WORKSPACE') — cualquier miembro del espacio de trabajo puede usar la credencial. Los activadores de cron y de base de datos también la ven, ya que no tienen usuario de la solicitud. - Solo para mí (
'USER') — la credencial pertenece al miembro que se conecta. En las ejecuciones realizadas en nombre de un miembro (activador de ruta HTTP conisAuthRequired: true),listConnectionsdevuelve las conexiones compartidas más las propias de ese miembro, yfindConnectionForRequestselecciona la conexión personal del miembro, recurriendo a una compartida cuando no tiene ninguna. En las ejecuciones sin un usuario de solicitud (por ejemplo, activadores cron),listConnectionsdevuelve todas las conexiones, incluidas las personales de cada miembro.
scope del proveedor determina cuál reciben sus nuevas conexiones:scope: 'WORKSPACE'(el predeterminado) — la aplicación funciona con conexiones compartidas con el espacio de trabajo. Agregar conexión en la configuración del espacio de trabajo de la aplicación crea una conexión compartida con el espacio de trabajo.scope: 'USER'— cada miembro conecta su propia cuenta, creando conexiones personales. Los miembros las añaden, reconectan y eliminan desde la página de la aplicación en Configuración > Usuario > Preferencias de aplicaciones, lo que requiere el permiso Aplicaciones de usuario. La configuración del espacio de trabajo de la aplicación no tiene un botón Agregar conexión para un proveedorUSER.
USER, así que no dependas de una para
una función que todos los espacios de trabajo necesitan ahora.scope de un proveedor existente, y la actualización se rechaza si lo intenta. Para mover un servicio de un ámbito a otro, declare un proveedor nuevo con un universalIdentifier nuevo y elimine el anterior. La actualización elimina entonces el proveedor anterior y todas las conexiones realizadas con él mediante la ruta de desconexión habitual (onDisconnectLogicFunction, revocación de tokens, limpieza de canales), y los miembros se conectan de nuevo mediante el proveedor nuevo.Para añadir o reconectar una conexión Solo para mí se requiere el permiso Aplicaciones de usuario, y para añadir o reconectar una conexión Compartida en el espacio de trabajo se requiere el permiso Aplicaciones del espacio de trabajo.Usa la conexión adecuada para cada controlador:scope, declara "engines": { "twenty": ">=2.49.0" } en su package.json. En la misma versión, el scope de una conexión reemplaza su visibility, que sigue disponible como un alias en minúsculas en desuso. listConnections y getConnection de twenty-sdk 2.49.0 leen scope, por lo que las aplicaciones creadas con él necesitan un servidor 2.49.0.Configuración única del proveedor
Registra tu aplicación OAuth con el servicio de terceros
Configuración única del proveedor
Registra tu aplicación OAuth con el servicio de terceros
- Ve a la configuración de desarrollador del proveedor (p. ej., https://linear.app/settings/api/applications/new).
- Configura el URI de redirección en
\<SERVER_URL>/auth/apps/callback. - Copia el Client ID y el Client Secret generados.
- Abre la aplicación instalada en Twenty como administrador del servidor → establece los valores en los
serverVariablescorrespondientes. - Luego, los miembros del espacio de trabajo pueden agregar conexiones a proveedores
WORKSPACEdesde la sección Conexiones de cada aplicación.