Authagonal

Documentación

Todo lo que necesitas para empezar con Authagonal — desde crear tu primer inquilino hasta configurar SSO, SCIM y personalización de marca.

Primeros pasos

Authagonal proporciona a cada inquilino un servidor OIDC totalmente compatible con estándares. Cada inquilino obtiene su propia URL de emisor, documento de descubrimiento y endpoints de token — sin infraestructura compartida entre inquilinos. Puedes pasar de cero a un flujo de inicio de sesión funcional en menos de 5 minutos.

Crear un inquilino

Regístrate en authagonal.io y elige un slug para tu inquilino. El slug se convierte en tu dominio de emisor: {slug}.authagonal.io. Después de crear tu cuenta, verifica tu dirección de correo electrónico para activar el inquilino.

Authagonal signup page showing tenant slug input and email verification

Elige un slug único para tu inquilino durante el registro

Registrar un cliente

Navega a Clientes en la barra lateral del portal y haz clic en Nuevo cliente. Ingresa un clientId y un clientName para tu aplicación. Luego, en la pestaña URIs del cliente, añade al menos una URI de redirección; aquí es donde se envían los usuarios después de autenticarse. Por ejemplo: https://app.example.com/callback. Los clientes nuevos requieren un secreto de cliente por defecto, así que para una aplicación de navegador sin backend desactiva Requerir secreto en la pestaña General.

New client form with Client ID and Client Name fields

Registrar un nuevo cliente OAuth en el portal

Desarrollo local

Usa http://localhost:3000/callback como URI de redirección para desarrollo local. Authagonal permite URIs de redirección sin HTTPS para orígenes localhost.

Tu primer inicio de sesión

La forma más rápida de integrar es con oidc-client-ts, una biblioteca de cliente OIDC ligera para aplicaciones JavaScript y TypeScript.

oidc-client-ts integration
import { UserManager } from 'oidc-client-ts';

const mgr = new UserManager({
  authority: 'https://acme.authagonal.io',
  client_id: 'my-app',
  redirect_uri: 'https://app.example.com/callback',
  response_type: 'code',
  scope: 'openid profile email',
});

// Redirect to login
mgr.signinRedirect();

// On callback page
const user = await mgr.signinRedirectCallback();
console.log(user.profile); // { sub, email, name, ... }

Si prefieres un enfoque mínimo sin biblioteca, puedes usar el flujo estándar de código de autorización OAuth 2.0 con fetch simple:

Minimal fetch-based flow
// 1. Redirect the user to the authorization endpoint
const authorizeUrl = new URL('https://acme.authagonal.io/connect/authorize');
authorizeUrl.searchParams.set('client_id', 'my-app');
authorizeUrl.searchParams.set('redirect_uri', 'https://app.example.com/callback');
authorizeUrl.searchParams.set('response_type', 'code');
authorizeUrl.searchParams.set('scope', 'openid profile email');
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
window.location.href = authorizeUrl.toString();

// 2. On the callback page, exchange the code for tokens
const res = await fetch('https://acme.authagonal.io/connect/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: new URLSearchParams(window.location.search).get('code')!,
    redirect_uri: 'https://app.example.com/callback',
    client_id: 'my-app',
    code_verifier: codeVerifier,
  }),
});

const tokens = await res.json();
// tokens.id_token, tokens.access_token (refresh_token only when offline_access is requested and allowed)
Authagonal login page with email and password fields, branded with tenant logo

La página de inicio de sesión predeterminada para tu inquilino

Modo sandbox

Prueba tu integración primero en un entorno sandbox. Crea uno en Entornos en el portal: cada sandbox tiene su propia URL ({env}-{slug}.authagonal.io, p. ej. test1-acme.authagonal.io) y puede restablecerse a vacío en cualquier momento sin afectar a los usuarios activos.

Panel de control

El panel de control del portal te ofrece una visión en tiempo real de tu inquilino. Presenta las métricas más importantes — crecimiento de usuarios, actividad de autenticación y navegación rápida a todas las funcionalidades del portal.

Resumen

En la parte superior del panel de control verás un mensaje de bienvenida y un enlace Abrir página de inicio de sesión al inicio de sesión alojado de tu inquilino. Debajo de las tarjetas de estadísticas, un medidor de Usuarios activos mensuales sigue el uso frente al límite de tu plan y enlaza a las opciones de plan cuando superas el 80%. Un gráfico de Actividad de inicio de sesión y una lista de Actividad reciente con las últimas entradas de auditoría completan la página.

Full dashboard view showing the welcome banner, stat cards, monthly active users meter, and sign-in activity chart

La pantalla principal del panel de control con tarjetas de estadísticas y actividad de inicio de sesión

Métricas de actividad

Seis tarjetas de estadísticas resumen tu inquilino de un vistazo:

  • Usuarios activos: el número total de usuarios de tu inquilino
  • Inicios de sesión (24h): inicios de sesión correctos en las últimas 24 horas
  • MFA registrado: el porcentaje de usuarios con MFA inscrita, con los recuentos de inscritos y del total
  • Intentos fallidos (24h): inicios de sesión fallidos en las últimas 24 horas, como credenciales incorrectas, cuentas bloqueadas o rechazos por política
  • Sincronización SCIM: actividad de aprovisionamiento desde IdPs conectados, mostrada como Inactivo o como un recuento de operaciones
  • Gasto mensual: el gasto acumulado este mes, con una cifra proyectada para final de mes

Las tarjetas de 24 horas comparan las últimas 24 horas con las 24 horas anteriores. El gráfico de Actividad de inicio de sesión representa los inicios de sesión correctos y fallidos por día durante 14, 30 o 90 días. El panel de control se actualiza cada minuto.

Six stat cards showing active users, sign-ins, MFA enrolment, failed attempts, SCIM sync, and monthly spend

Tarjetas de estadísticas que resumen las últimas 24 horas

Navegación rápida

Debajo de las métricas, las tarjetas de navegación enlazan directamente a Clientes, SSO, Usuarios, SCIM, Marca, Configuración, Facturación, Dominios y Registro de auditoría. Cada tarjeta muestra una breve descripción para que los nuevos miembros del equipo puedan orientarse rápidamente.

Clientes

Los clientes OAuth representan las aplicaciones que autentican usuarios a través de tu inquilino. Cada cliente tiene su propia configuración de URIs de redirección, alcances, tipos de concesión, duraciones de tokens y política de MFA.

Lista de clientes

La página de Clientes muestra una tabla con todos los clientes registrados. Cada fila muestra el clientId, nombre para mostrar, tipos de concesión permitidos como insignias de colores y si PKCE está habilitado. Haz clic en cualquier fila para abrir el editor de configuración completo.

Clients table showing clientId, name, grant type badges, and PKCE status for each registered application

Lista de clientes con insignias de tipo de concesión e indicadores de PKCE

Crear un cliente

Haz clic en Nuevo cliente para registrar una nueva aplicación. Necesitas proporcionar dos campos:

  • clientId — un identificador único para el cliente (por ejemplo, my-spa)
  • clientName — un nombre para mostrar legible por humanos
New client form with Client ID and Client Name input fields

Registrar un nuevo cliente OAuth

Eliminar un cliente

Para eliminar un cliente, haz clic en el icono de papelera de su fila en la tabla de clientes y escribe el ID del cliente para confirmar. El cliente se elimina permanentemente y ya no puede autenticar usuarios ni renovar tokens. Los tokens de acceso ya emitidos no se revocan y siguen siendo válidos hasta que expiran.

Referencia de configuración de cliente

Cada cliente tiene un conjunto completo de opciones de configuración organizadas en cinco pestañas: General, URIs, Scopes & Grants, Tokens y Seguridad.

Configuración general

ConfiguraciónDescripciónPredeterminado
clientNameNombre para mostrar en las pantallas de consentimiento y el portal–
requirePkceRequerir Proof Key for Code Exchange en los flujos de código de autorizaciónActivado
requireClientSecretRequerir un secreto de cliente para solicitudes de token (deshabilitar para clientes públicos como SPAs)Activado
allowOfflineAccessPermitir que el cliente solicite tokens de actualización a través del alcance offline_accessDesactivado
alwaysIncludeUserClaimsInIdTokenIncluir las reclamaciones de perfil, correo electrónico, roles y grupos en el token de ID incluso cuando no se solicitaron los ámbitos correspondientesDesactivado
includeGroupsInTokensIncluir los nombres de los grupos SCIM del usuario como una reclamación groups, en los tokens emitidos cuando se solicita el ámbito groupsDesactivado

Seguridad PKCE

Deshabilitar PKCE reduce la seguridad para los flujos de código de autorización. Solo deshabilita esto para clientes heredados que no soportan PKCE. Todas las aplicaciones modernas deben dejar PKCE habilitado.

URIs

Los campos de URI utilizan una entrada de etiquetas — escribe un valor y presiona Enter o coma para añadirlo. Haz clic en la X de cualquier etiqueta para eliminarla.

ConfiguraciónDescripción
redirectUrisURLs de callback permitidas después de la autenticación. Deben coincidir exactamente con el parámetro redirect_uri en las solicitudes de autorización.
postLogoutRedirectUrisURLs permitidas para redirigir después del cierre de sesión.
allowedCorsOriginsOrígenes permitidos para solicitudes de origen cruzado a los endpoints de token y UserInfo.
URI configuration section showing tag inputs for redirect URIs, post-logout URIs, and CORS origins

Campos de entrada de etiquetas para configurar URIs

Alcances y tipos de concesión

ConfiguraciónOpciones
allowedScopesopenid profile email offline_access phone roles groups
allowedGrantTypesauthorization_code client_credentials refresh_token urn:ietf:params:oauth:grant-type:device_code urn:ietf:params:oauth:grant-type:token-exchange

Duraciones de tokens

ConfiguraciónDescripciónPredeterminado
accessTokenLifetimeSecondsCuánto tiempo son válidos los tokens de acceso1800 (30 min)
identityTokenLifetimeSecondsCuánto tiempo son válidos los tokens de ID300 (5 min)
authorizationCodeLifetimeSecondsCuánto tiempo son válidos los códigos de autorización para el intercambio300 (5 min)
absoluteRefreshTokenLifetimeSecondsDuración máxima de un token de actualización independientemente de la actividad2592000 (30 días)
slidingRefreshTokenLifetimeSecondsLa expiración del token de actualización se reinicia con cada uso, hasta la duración absoluta1296000 (15 días)
Token lifetime configuration fields with numeric inputs for each lifetime setting

Configurar duraciones de tokens por cliente

URIs de logout

Los clientes pueden registrar URIs de logout tanto back-channel como front-channel. Ambas son opcionales — configura las que coincidan con cómo tu aplicación limpia su sesión.

ConfiguraciónDescripción
backChannelLogoutUriPOST servidor a servidor con un token de logout firmado. Fiable incluso si el navegador está offline.
frontChannelLogoutUriSe carga en un iframe oculto durante el logout para que el navegador limpie cookies y almacenamiento local.
frontChannelLogoutSessionRequiredSi está activo, la URL de logout recibe los parámetros iss y sid para que tu app correlacione el logout con la sesión específica.

Usa ambos juntos

Back-channel garantiza que el servidor sea notificado; front-channel limpia el navegador. La mayoría de apps se benefician de configurar ambos.

Política de MFA

Cada cliente tiene su propia política de MFA, configurada en la pestaña <strong>Seguridad</strong> del cliente. El menú desplegable de política de MFA ofrece tres opciones:

PolíticaComportamiento
DeshabilitadoMFA nunca se solicita para este cliente
HabilitadoLos usuarios pueden inscribirse opcionalmente en MFA; se les solicitará si están inscritos
ObligatorioTodos los usuarios deben completar MFA para autenticarse a través de este cliente
MFA policy dropdown showing Disabled, Enabled, and Required options on the client configuration page

Política de MFA por cliente

SSO empresarial

El SSO empresarial permite que tus clientes traigan su propio proveedor de identidad. Authagonal soporta tanto la federación SAML 2.0 como OIDC con enrutamiento basado en dominio, para que los usuarios sean dirigidos automáticamente al IdP correcto según su dirección de correo electrónico.

SSO domain routing flow: shows how email domains are matched to SAML or OIDC identity providers

Enrutamiento SSO basado en dominio

Conexiones SAML 2.0

Para crear una conexión SAML, navega a la página de SSO y selecciona la pestaña SAML. Proporciona lo siguiente:

CampoDescripción
connectionNameUn nombre legible para esta conexión (por ejemplo, "Acme Corp Okta")
entityIdSu ID de entidad del SP. Registre exactamente este valor en su IdP como identificador (Entity ID) de la aplicación; las aserciones deben nombrarlo como Audience
metadataLocationURL del documento XML de metadatos SAML del IdP
metadataXmlXML de metadatos del IdP pegado, para IdP sin URL de metadatos (Google Workspace) o cuya URL no es accesible desde Internet. Proporcione esto o metadataLocation, no ambos
nameIdFormatFormato de NameID opcional solicitado al IdP. Omítalo para el valor predeterminado emailAddress, o use "none" para omitir NameIDPolicy por completo (recomendado para ADFS)
allowedDomainsDominios de correo electrónico enrutados a esta conexión (p. ej. acme.com). Se configuran mediante la API; el portal los muestra en la tarjeta de la conexión y en la pestaña Enrutamiento de dominio

Cuando guardas la conexión, Authagonal obtiene el documento de metadatos e importa el certificado de firma del IdP, la URL del endpoint SSO y el formato del identificador de nombre. Los metadatos se actualizan periódicamente para incorporar las rotaciones de certificados.

SAML connection creation form with fields for connection name, SP entity ID, and IdP metadata

Crear una conexión SSO SAML 2.0

Conexiones OIDC

Para crear una conexión de federación OIDC, selecciona la pestaña OIDC y proporciona:

CampoDescripción
connectionNameUn nombre legible para esta conexión
metadataLocationLa URL de descubrimiento OpenID Connect (por ejemplo, https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration)
clientIdEl client ID registrado con el IdP externo para esta federación
clientSecretEl client secret para el registro del IdP externo
allowedDomainsDominios de correo electrónico enrutados a esta conexión (p. ej. acme.com). Se configuran mediante la API; el portal los muestra en la tarjeta de la conexión y en la pestaña Enrutamiento de dominio
OIDC connection creation form with fields for connection name, discovery URL, client ID, and client secret

Crear una conexión de federación OIDC

Enrutamiento de dominio

El enrutamiento de dominio redirige automáticamente a los usuarios al proveedor de identidad correcto según el dominio de su correo electrónico. Cuando un usuario ingresa su correo en la página de inicio de sesión, Authagonal verifica si la parte del dominio (por ejemplo, acme.com) coincide con los allowedDomains de alguna conexión SSO. Si coincide, el usuario es redirigido de forma transparente al IdP de su organización.

Dominio de correo electrónicoProveedor SSOProtocolo
acme.comAcme Corp OktaSAML 2.0
contoso.comContoso Azure ADOIDC
example.orgExample OneLoginSAML 2.0
Domain routing table showing email domains mapped to SSO connections with protocol type

El enrutamiento de dominio mapea dominios de correo electrónico a proveedores de identidad

Flujo iniciado por SP

El flujo iniciado por SP es el predeterminado — los usuarios comienzan en tu página de inicio de sesión y son dirigidos al IdP correcto automáticamente. Los usuarios también pueden ser enlazados directamente a una conexión específica a través de /saml/{connectionId}/login o /oidc/{connectionId}/login.

Aprovisionamiento JIT

Cuando un usuario inicia sesión a través de SSO por primera vez y no existe ya en tu inquilino, Authagonal puede crear su cuenta automáticamente (aprovisionamiento Just-In-Time). El aprovisionamiento JIT está desactivado por defecto: actívalo por conexión marcando Activar aprovisionamiento JIT al crear la conexión.

Cuando el aprovisionamiento JIT está deshabilitado, solo los usuarios que han sido pre-aprovisionados — a través de SCIM, la página de Usuarios del portal o la API — pueden iniciar sesión a través de esa conexión. Los usuarios desconocidos reciben un error access_denied y son dirigidos a contactar a su administrador.

Configuración por conexión

El aprovisionamiento JIT se controla por conexión SSO, no a nivel de inquilino. Puedes tener una conexión que permite JIT (por ejemplo, para una organización asociada que gestiona sus propios usuarios) y otra que requiere pre-aprovisionamiento (por ejemplo, para un cliente empresarial que usa sincronización SCIM).

Probar antes de implementar

Prueba las conexiones SSO con el modo sandbox antes de implementarlas para usuarios de producción. Esto te permite verificar la configuración del IdP, el mapeo de atributos y el enrutamiento de dominio sin afectar los flujos de autenticación en vivo.

Conexiones con alcance de organización

Una conexión también puede pertenecer a una organización de tu inquilino en lugar de a todo el inquilino. Solo se ofrece cuando esa organización ya se ha resuelto: mediante un dominio personalizado fijado a ella, un parámetro organization en el enlace de inicio de sesión o un cliente registrado para esa única organización. Nunca se ofrece en una página de inicio de sesión de todo el inquilino. El orden en que se comprueban esas vías es el indicado, de mayor a menor prioridad.

Iniciar sesión crea la membresía

Un usuario que inicia sesión a través de una conexión con alcance de organización pasa a ser automáticamente miembro de esa organización, del mismo modo que el aprovisionamiento JIT crea su cuenta: no hay un paso de invitación aparte.

La unicidad del dominio es por alcance

Un dominio de correo puede reclamarse una vez en todo el inquilino y, de forma independiente, una vez más dentro de cada organización: acme.com puede dirigirse a una conexión de todo el inquilino y también, una vez seleccionada ya una organización, a la conexión propia de esa organización. Lo que no puede es pertenecer a dos conexiones dentro del mismo alcance; Authagonal lo rechaza al guardar la conexión.

Usuarios

La página de Usuarios te permite gestionar todos los usuarios finales en tu inquilino. Puedes buscar usuarios, ver sus detalles, invitar a nuevos usuarios y ver cómo fue aprovisionado cada usuario.

La barra de búsqueda encuentra coincidencias exactas de ID de usuario o de correo electrónico, o por prefijo del correo electrónico, el nombre o el apellido, y los filtros Todos, Activos e Inactivos acotan la lista por estado. La búsqueda tiene un retardo de 300ms para que los resultados se actualicen mientras escribes sin sobrecargar la API. Los resultados están paginados a 50 usuarios por página; usa los controles de navegación en la parte inferior de la tabla para moverte entre páginas.

Tabla de usuarios

La tabla de usuarios muestra las siguientes columnas para cada usuario:

ColumnaDescripción
UsuarioEl nombre del usuario (o su correo electrónico si no tiene nombre), con su correo debajo y una insignia Sin verificar hasta que se confirme el correo
EstadoActive o Inactive — indica si la cuenta está habilitada
OrigenSCIM o Local — cómo fue creado el usuario
RolesLos roles asignados al usuario
MFAEnabled cuando la autenticación multifactor está inscrita; en caso contrario, un guion
CreadoLa fecha en que se creó la cuenta de usuario
User list table with columns for user, status, source, roles, MFA, and created date

La lista de usuarios con barra de búsqueda y paginación

Invitar usuarios

Haz clic en Invitar usuario para invitar a alguien a tu inquilino. Recibirá un correo electrónico para establecer su propia contraseña. El formulario admite:

CampoDescripción
emailLa dirección de correo electrónico del usuario (debe ser única dentro del inquilino)
firstNameEl nombre del usuario
lastNameEl apellido del usuario
localeIdioma preferido. Define el idioma de la interfaz y de los correos del usuario; opcional, recurre al inglés.
organizationIdOrganización opcional a la que añadir al usuario, con sus roles en ella. Se muestra cuando tu inquilino tiene organizaciones
Invite user form with email, first name, last name, and Language fields

Invitar a un nuevo usuario

Usuarios aprovisionados por SCIM

Los usuarios creados a través de SCIM están marcados con una insignia "SCIM" en la columna Origen. Su ciclo de vida (creación, actualizaciones y desactivación) lo gestiona el proveedor de identidad ascendente.

Idioma preferido

Cada usuario tiene un idioma preferido que controla tanto su interfaz alojada como los correos transaccionales que Authagonal le envía (verificación, restablecimiento de contraseña, bienvenida y más). Puedes definirlo al invitar a un usuario y cambiarlo en cualquier momento desde su página de detalle. Si un usuario no tiene un idioma preferido definido, Authagonal recurre al inglés. El selector ofrece todos los idiomas soportados: inglés, chino (simplificado), alemán, francés, español, vietnamita, portugués, japonés, árabe, hindi y afrikáans.

User detail edit form with profile fields including a preferred Language selector

Definir el idioma preferido de un usuario en su página de detalle

Detalle del usuario

Haz clic en cualquier fila de la lista de usuarios para abrir su página de detalle. Desde ahí puedes editar datos de perfil, gestionar roles, restablecer MFA, revisar atributos personalizados y eliminar al usuario.

User detail page showing profile fields, status, assigned roles, and custom attributes

Perfil

Edita correo electrónico, nombre/apellidos, teléfono, empresa, idioma, ID externo y el indicador de activo del usuario. Cambiar el correo electrónico o el indicador de correo confirmado requiere el rol de administrador o de propietario. Los cambios de correo deben permanecer únicos en el inquilino; la API devuelve email_already_in_use si ya está en uso.

Roles

Asigna y retira roles definidos en la página Roles. Los roles asignados se emiten como la reclamación roles en los tokens ID y de acceso cuando el cliente solicita el ámbito roles.

Autenticación multifactor

Consulta todas las credenciales MFA registradas para el usuario (aplicación autenticadora (TOTP), WebAuthn/passkeys y códigos de recuperación), cada una con marcas de tiempo de registro y último uso. Elimina credenciales individuales o restablece todo MFA; ambas acciones requieren el rol de administrador o de propietario. Restablecer obliga al usuario a volver a registrarse en el próximo inicio de sesión.

Atributos personalizados

Datos clave/valor arbitrarios asociados al usuario. Las claves deben ser únicas. Los atributos se exponen vía la API de perfil de usuario y SCIM, y pueden mapearse a reclamaciones del token de acceso configurando los userClaims de un ámbito personalizado.

Organización

La organización a la que pertenece este usuario. Es un identificador de texto libre propio, emitido como reclamación org_id en sus tokens y en /connect/userinfo bajo el ámbito profile. Authagonal nunca lo deriva: lo define tu aplicación de aprovisionamiento, el token SCIM que creó al usuario, o tú mismo a mano aquí.

El enlace junto al campo lista a todos los que comparten ese valor, y el mismo filtro está disponible en la API como GET /api/v1/users?organizationId=. Úsalo para saber quién pertenece a un cliente final concreto sin paginar todo el directorio.

Eliminar usuario

Elimina permanentemente al usuario y todas sus credenciales MFA. Escribe el correo del usuario para confirmar — no hay deshacer.

Grupos

Los grupos te permiten organizar usuarios e incluir la membresía de grupo en los tokens. Los grupos pueden crearse manualmente en el portal o aprovisionarse automáticamente a través de SCIM desde un proveedor de identidad externo.

Lista de grupos

Los grupos se listan en la pestaña Grupos de la página SCIM, con la siguiente información:

ColumnaDescripción
Nombre del grupoEl nombre para mostrar del grupo
MiembrosEl número de usuarios actualmente en el grupo
OrigenSCIM o Manual — cómo fue creado el grupo
CreadoLa fecha en que se creó el grupo
Groups list table showing group name, member count, source badge, granted roles, and created date

Lista de grupos con indicadores de origen

Crear un grupo

Haz clic en Nuevo grupo e ingresa un Nombre para mostrar para el grupo. Los nombres de grupo deben ser descriptivos y únicos dentro de tu inquilino (por ejemplo, "Engineering", "Billing Admins", "Beta Testers").

Detalle del grupo y miembros

Haz clic en cualquier grupo para abrir la vista de detalle. Aquí puedes ver todos los miembros actuales y gestionar la membresía:

  • Añadir miembros: busca un usuario por correo electrónico o nombre y añádelo al grupo.
  • Eliminar miembros: haz clic en el botón de eliminar junto a cualquier miembro y confirma. Se revocan los roles concedidos a través del grupo.
Group detail view showing the member list, a user search to add members, and the roles the group grants

Gestionar la membresía del grupo en la vista de detalle

Grupos en tokens

Cuando Grupos en los tokens está habilitado en un cliente y se solicita el ámbito groups, los tokens emitidos incluyen una reclamación groups que lista los nombres para mostrar de los grupos del usuario:

groups claim
{
  "sub": "user-123",
  "email": "[email protected]",
  "groups": ["Engineering", "Beta Testers"]
}

Habilitar por cliente

La configuración Grupos en los tokens se establece en cada cliente individualmente, en la pestaña General del cliente. El cliente también debe permitir el ámbito groups.

Roles

Los roles soportan el control de acceso basado en roles (RBAC) en tu aplicación. Define roles en Authagonal, asígnalos a usuarios y usa la reclamación roles en los tokens para aplicar la autorización en la lógica de tu aplicación.

Gestionar roles

La página de Roles muestra una tabla con todos los roles definidos con edición en línea. Cada rol tiene:

ColumnaDescripción
NombreUn identificador único para el rol (por ejemplo, "admin", "editor", "viewer")
DescripciónUna descripción legible de lo que otorga el rol
CreadoLa fecha en que se creó el rol

Crear un rol

Haz clic en Nuevo rol y proporciona un nombre y una descripción. Los nombres de los roles deben ser concisos y seguir una convención de nomenclatura consistente en tu aplicación (por ejemplo, minúsculas con guiones: billing-admin).

Edición en línea

Los roles soportan edición en línea directamente en la tabla. Haz clic en el icono de lápiz en cualquier rol para entrar en modo de edición — los campos de nombre y descripción se vuelven editables. Modifica los valores y luego haz clic en el icono de marca de verificación para guardar. Los cambios entran en vigor inmediatamente.

Eliminar un rol

Haz clic en el icono de eliminar en cualquier rol para eliminarlo. Se te pedirá confirmar antes de que el rol sea eliminado permanentemente. Eliminar un rol no invalida retroactivamente los tokens existentes — el rol estará ausente de los nuevos tokens emitidos después de la eliminación.

Roles table with inline editing active, showing editable name and description fields with save and cancel icons

Edición en línea de roles en la tabla de roles

Roles en tokens

Los roles asignados a un usuario se incluyen como una reclamación roles en los tokens de ID y de acceso cuando el cliente solicita el ámbito roles. Tu aplicación puede leer esta reclamación para tomar decisiones de autorización:

roles claim in ID token
{
  "sub": "user-123",
  "email": "[email protected]",
  "roles": ["admin", "billing-admin"]
}

Aprovisionamiento SCIM

SCIM 2.0 (System for Cross-domain Identity Management) permite el aprovisionamiento automático de usuarios y grupos desde proveedores de identidad empresariales como Okta, Azure AD, OneLogin y JumpCloud. Una vez configurado, las cuentas de usuario y las membresías de grupo se sincronizan automáticamente desde el IdP ascendente a tu inquilino de Authagonal.

SCIM provisioning flow: shows user lifecycle events flowing from enterprise IdP through Authagonal SCIM API to your app via TCC webhooks

Sincronización del ciclo de vida de usuarios SCIM con aprovisionamiento descendente

Pasos de configuración

Sigue estos pasos para habilitar el aprovisionamiento SCIM para un cliente:

  1. Selecciona la aplicación cliente — Elige el cliente OAuth con el que se asociará el aprovisionamiento SCIM.
  2. Genera un token SCIM — Proporciona una descripción y un período de expiración en días, luego genera el token.
  3. Copia el token inmediatamente — El valor del token sin procesar se muestra solo una vez. Cópialo antes de cerrar el diálogo.
  4. Configura tu IdP — En la configuración SCIM de tu proveedor de identidad, ingresa la URL base y el token bearer.
  5. Prueba la sincronización de usuarios — Activa una sincronización de prueba desde tu IdP y verifica que los usuarios aparezcan en el portal de Authagonal.

URL base de SCIM

Configura tu proveedor de identidad con la siguiente URL base:

SCIM Base URL
https://{slug}.authagonal.io/scim/v2

Reemplaza {slug} con el slug de tu inquilino.

SCIM configuration page showing client selector, token generation form, and base URL

Página de configuración SCIM con generación de tokens

Gestión de tokens

Los tokens SCIM autentican las solicitudes de aprovisionamiento desde tu IdP. Puedes gestionar múltiples tokens por cliente:

CampoDescripción
DescripciónUna etiqueta para identificar el token (por ejemplo, "Okta Production SCIM")
ExpiraciónDuración del token en días (1 a 3650, 365 por defecto).
EstadoLos tokens activos están en uso. Los tokens revocados muestran una Revoked insignia y ya no pueden autenticar solicitudes.

Para revocar un token, haz clic en el botón Revocar junto a él. Los tokens revocados permanecen visibles en la lista con fines de auditoría pero dejan de aceptar solicitudes inmediatamente.

SCIM token list showing active and revoked tokens with description, expiry date, and revoke button

Gestión de tokens con indicadores de tokens activos y revocados

Copia el token inmediatamente

El token SCIM sin procesar se muestra solo una vez al crearlo. Cópialo inmediatamente — no se puede recuperar posteriormente. Si pierdes el token, necesitarás generar uno nuevo y actualizar la configuración de tu IdP.

Probar la conectividad

Verifica que tu integración SCIM está funcionando consultando el endpoint ServiceProviderConfig:

Test SCIM connectivity
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://acme.authagonal.io/scim/v2/ServiceProviderConfig

Una respuesta exitosa devuelve un documento JSON que describe las funcionalidades SCIM soportadas: PATCH y el filtrado están soportados, mientras que las operaciones masivas, los cambios de contraseña, la ordenación y los ETags no lo están.

Idioma preferido

El atributo SCIM preferredLanguage (con recurso a locale) se asigna al idioma almacenado del usuario. Los usuarios SSO aprovisionados mediante SCIM reciben automáticamente correos localizados en el idioma que envía su IdP.

Qué puede ver un token

Un token SCIM solo ve los usuarios y grupos que él mismo aprovisionó. Leer, actualizar o eliminar un usuario creado por otro conector responde 404, el listado devuelve solo los propios y la membresía de un grupo solo puede nombrar usuarios aprovisionados por ese mismo conector. Las cuentas creadas de cualquier otra forma, por un administrador, por registro de autoservicio o por aprovisionamiento justo a tiempo mediante SSO, son completamente invisibles para SCIM.

Ese límite es por cliente OAuth, no por token. Dos tokens emitidos sobre el mismo cliente OAuth son una sola identidad con dos secretos, y cada uno puede modificar lo que creó el otro. Da a cada conector que no confíe en los demás su propio cliente OAuth. externalId tiene el mismo alcance, así que dos conectores pueden usar cada uno ext-001 para personas distintas sin colisionar.

Desaprovisionamiento

DELETE /scim/v2/Users/{id} desactiva la cuenta y la marca como eliminada. El registro se conserva, tal como permite RFC 7644, pero responde 404 a cualquier operación posterior y se omite de los listados. Sus inscripciones MFA y sus membresías de grupo se purgan, su asignación de externalId se libera y todos los tokens emitidos se revocan, de modo que el acceso termina de inmediato y no en la siguiente expiración de token.

Si más adelante se vuelve a contratar a la misma persona y se crea de nuevo, recibe un nuevo ID de usuario. Los identificadores nunca se reutilizan: el ID es el sujeto de cada token que has emitido, así que reutilizarlo daría de forma silenciosa al nuevo empleado el historial del titular anterior en todas las aplicaciones que confían en él.

Etiquetar usuarios sincronizados con una organización

SCIM no ofrece a un conector ninguna forma de indicar cuál de tus clientes finales está sincronizando. El SCIM básico no define ningún atributo de organización, así que una creación de usuario simple te da el nombre y el correo de la persona y nada sobre a quién pertenece. Si varios clientes finales aprovisionan en tu inquilino, sus usuarios llegan indistinguibles.

Es el token el que lo responde, no la solicitud. Cuando creas un token SCIM, elige una de las organizaciones de tu inquilino en Organización (el selector aparece en cuanto tu inquilino tiene organizaciones). Cada usuario aprovisionado mediante ese token se convierte en miembro activo de esa organización y la lleva como reclamación org_id en sus tokens a partir de entonces. Emite un token por cada cliente final sobre el mismo cliente OAuth y sus usuarios sincronizados quedan correctamente atribuidos sin necesidad de registrar un cliente OAuth para cada uno. Déjalo en blanco y los usuarios quedan sin etiquetar.

Etiquetar no es aislar

La propiedad se aplica por cliente OAuth, no por token. Dos tokens sobre el mismo cliente OAuth son una sola identidad con dos secretos: cada uno puede leer, renombrar, desactivar y eliminar los usuarios que creó el otro. Eso no supone ningún problema mientras seas tú quien conserva todos los tokens. Si el equipo de TI de cada cliente final conserva el suyo, dales un cliente OAuth a cada uno y define también la organización en su token.

La etiqueta se aplica cuando se crea el usuario y nunca en una actualización posterior, de modo que una sincronización incremental rutinaria no puede mover de forma silenciosa una cuenta existente. Si además ejecutas una aplicación de aprovisionamiento, la etiqueta explícita del token prevalece: una respuesta de /try solo rellena una organización que todavía está vacía.

Esquemas soportados

Implementamos los esquemas básicos User y Group de SCIM 2.0 (RFC 7643). Los atributos de usuario soportados son userName, name.givenName, name.familyName, displayName, emails, active, externalId y preferredLanguage / locale.

La extensión enterprise user no está implementada, por lo que department, manager, employeeNumber, costCenter, division y organization se aceptan y se ignoran en lugar de almacenarse, tanto en la creación como en el reemplazo y en PATCH. Entra y Okta mapean algunos de ellos por defecto, así que no necesitas quitarlos de tu mapeo de atributos. Para atribuir un usuario a uno de tus clientes finales, define la organización en el token SCIM: el atributo enterprise organization lo afirma el proveedor de identidad de tu cliente final, y deliberadamente no se convierte en la org_id del usuario.

Ámbitos de OAuth

Los ámbitos permiten a los clientes solicitar porciones específicas de los datos o permisos de un usuario. Authagonal admite tanto los ámbitos estándar de OIDC como los ámbitos personalizados que definas para tus API.

Ámbitos integrados

ÁmbitoDescripción
openidObligatorio para cualquier flujo de OpenID Connect. Emite un token de identidad.
profileDevuelve reclamaciones estándar de perfil (name, given_name, family_name, locale, org_name).
emailDevuelve el correo electrónico del usuario y su estado de verificación.
phoneDevuelve el número de teléfono del usuario (phone_number).
offline_accessEmite un token de actualización junto al token de acceso.
rolesEntrega la reclamación roles del usuario. Sin este ámbito, no se emiten los roles.
groupsEntrega la reclamación groups del usuario (pertenencia a grupos SCIM). Sin este ámbito, no se emiten los grupos.

Ámbitos personalizados

Define tus propios ámbitos en la página Ámbitos. Cada ámbito describe un permiso o recurso que un cliente puede solicitar (por ejemplo, billing.read, orders.write).

Custom scope creation form with name, display name, description and User Claims fields
CampoDescripción
nameEl identificador del ámbito enviado en las solicitudes de token (p. ej. billing.read).
displayNameEtiqueta legible mostrada en la pantalla de consentimiento.
descriptionExplicación más larga mostrada bajo el nombre en el consentimiento.
userClaimsReclamaciones adicionales añadidas al token de acceso y al token de ID cuando se concede este ámbito.
showInDiscoveryDocumentSi está activo, el ámbito aparece en /.well-known/openid-configuration.
emphasizeDestaca el ámbito en la pantalla de consentimiento como sensible.
requiredImpide que el usuario deseleccione el ámbito durante el consentimiento.
groupGrupo de consentimiento: los ámbitos que comparten un encabezado aparecen juntos en la pantalla de consentimiento bajo una sola casilla. Solo afecta a la presentación.
allowedRolesRoles que debe tener un usuario para que se le conceda este ámbito. Vacío permite a todos; a un usuario sin ninguno de estos roles se le quita el ámbito de su token en lugar de rechazarlo.

Integración con el consentimiento

Los clientes con RequireConsent: true piden consentimiento al usuario en la primera solicitud. Eliminar un ámbito no revoca los tokens ya emitidos — revócalos explícitamente si es necesario.

Reclamaciones personalizadas en los tokens

Las reclamaciones personalizadas tienen dos mitades. La fuente son los datos por usuario: cada AuthUser tiene un diccionario customAttributes que puedes poblar desde el Portal (Usuarios → usuario → Atributos personalizados), vía SCIM o mediante un hook de aprovisionamiento TCC. La liberación es por ámbito: la lista userClaims de cada ámbito nombra las claves que pueden salir del servidor.

Cuando un cliente solicita ámbitos, Authagonal recorre los ámbitos concedidos, une sus listas userClaims y emite solo esas claves de los customAttributes del usuario. Las claves desconocidas se descartan silenciosamente — un cliente no puede leer un atributo adivinando su nombre. Las reclamaciones OIDC estándar (sub, email, name, etc.) siguen la especificación y no están sujetas a la lista de permitidos.

Example: project-scope claims on an access token
# 1. On the user (Portal → Users → {user} → Custom Attributes)
department = "engineering"
employee_id = "E-1042"
seat_tier = "enterprise"

# 2. On a custom scope (Portal → Scopes → projects.read)
name        = "projects.read"
userClaims  = ["department", "seat_tier"]   # <-- whitelist

# 3. Client requests scope=openid projects.read
# Decoded access token (relevant fields only):
{
  "sub": "u-9b…",
  "scope": "openid projects.read",
  "department": "engineering",
  "seat_tier":  "enterprise"
  // employee_id is NOT emitted; it's not in the whitelist for any granted scope.
}

Las reclamaciones de federación completan huecos por sesión

Cuando un usuario inicia sesión vía un IdP de origen (SAML/OIDC SSO), las reclamaciones por sesión que llegan del IdP, por ejemplo un atributo department mapeado desde una aserción SAML, pasan por la misma lista de permitidos de ámbitos pero solo completan huecos: en una colisión de claves gana el valor persistido de customAttributes. Se emiten en los tokens de esta sesión (y sobreviven a las rotaciones de refresh) sin escribirse de vuelta en el registro del usuario.

Asignar ámbitos a clientes

Añade los ámbitos permitidos en la pestaña Clientes → Ámbitos y Concesiones. Un cliente solo puede solicitar ámbitos que se le hayan concedido; los ámbitos desconocidos se rechazan con invalid_scope.

Marca

Personaliza la apariencia de las páginas de inicio de sesión de tu inquilino. La configuración de marca te permite hacer coincidir la experiencia de autenticación con la identidad visual de tu producto — desde logotipos y colores hasta personalizaciones avanzadas de CSS.

Apariencia

ConfiguraciónDescripción
appNameEl nombre de la aplicación mostrado en el encabezado de la página de inicio de sesión (cuando no hay logotipo configurado) y en los correos transaccionales
logoUrlURL de la imagen de tu logotipo. Se muestra en la parte superior de la página de inicio de sesión. Tamaño recomendado: 200x60px o relación de aspecto similar.
primaryColorEl color primario de marca utilizado para botones, enlaces y estados de enfoque. Se establece a través de un selector de color o entrada hexadecimal. Una vista previa en vivo se actualiza a medida que cambias el valor.
customCssUrlURL de un archivo CSS cargado después de los estilos predeterminados. Debe servirse desde el mismo origen que la página de inicio de sesión; una URL en cualquier otro origen se ignora.
Branding appearance settings with app name input, logo URL field, color picker with hex input, and custom CSS URL field

Configuración de apariencia con vista previa de color en vivo

Información de contacto

ConfiguraciónDescripción
supportEmailUna dirección de correo electrónico de soporte mostrada en las páginas de inicio de sesión. Los usuarios la ven cuando necesitan ayuda con su cuenta.

Controles de la página de inicio de sesión

Controla qué elementos aparecen en la página de inicio de sesión de tu inquilino:

InterruptorDescripciónPredeterminado
showForgotPasswordMostrar el enlace "¿Olvidaste tu contraseña?" en el formulario de inicio de sesiónActivado
showRegistrationMostrar el enlace "Registrarse" para el registro de usuarios de autoservicioActivado
poweredByMostrar la insignia "Powered by Authagonal" en la parte inferior de la página de inicio de sesiónActivado
A customized login page showing a branded logo, custom primary color on the sign-in button, and support email in the footer

Ejemplo de página de inicio de sesión con marca personalizada aplicada

CSS personalizado

Para un control total sobre la apariencia de la página de inicio de sesión, proporciona la URL de un archivo CSS en tus ajustes de marca. El archivo se carga después de los estilos por defecto, por lo que tus reglas tienen prioridad. La URL debe estar en el mismo origen que la página de inicio de sesión; las hojas de estilo de otros orígenes no se cargan.

Propiedades personalizadas CSS

La página de inicio de sesión admite propiedades personalizadas CSS (variables) para sobrescrituras comunes. Establécelas en tu archivo CSS para cambiar colores, fuentes y formas sin escribir selectores complejos.
/* your-custom-styles.css */
:root {
--auth-bg: #1a1a2e;
--auth-card-bg: #16213e;
--auth-heading: #e0e0e0;
--auth-radius: 12px;
--auth-font: 'Inter', sans-serif;
}
VariableDescripciónPredeterminado
--auth-bgColor de fondo de la página#f3f4f6
--auth-card-bgFondo de la tarjeta de inicio de sesiónwhite
--auth-headingColor del texto del encabezado#111827
--auth-radiusRadio del borde de la tarjeta0.5rem
--auth-fontFamilia de fuenteinherit

Modo oscuro

La app de inicio de sesión incluye temas claro, oscuro y del sistema. El ajuste Modo oscuro de la página Marca elige el valor predeterminado: desactivado, auto (sigue la preferencia del sistema; es el valor predeterminado) o forzado. Los usuarios pueden seguir eligiendo desde un conmutador en la página de login; la elección se mantiene entre sesiones. Cuando está en system, la SPA sigue prefers-color-scheme en tiempo real.

Los valores claros se declaran en :root; las anulaciones oscuras están limitadas a .dark. El branding del inquilino mediante customCssUrl siempre prevalece — tus colores se mantienen sin importar el tema del usuario.

Selectores de elementos

Para un control más granular, apunta a elementos específicos usando los atributos data-auth. Estos selectores son estables entre actualizaciones — no se romperán cuando cambiemos los nombres de clase internos.
SelectorElemento
[data-auth="page"]Contenedor de fondo de página completa
[data-auth="header"]Área de logo y nombre de la app
[data-auth="logo"]Imagen del logo
[data-auth="app-name"]Encabezado del nombre de la app (cuando no hay logo)
[data-auth="content"]Área de contenido principal (formularios, mensajes)
[data-auth="login-form"]Elemento de formulario de inicio de sesión
[data-auth="email-field"]Contenedor del campo de correo
[data-auth="password-field"]Contenedor del campo de contraseña
[data-auth="submit-button"]Botón de inicio de sesión
[data-auth="languages"]Barra de selector de idioma

Configuración

Configura las políticas de seguridad, webhooks y configuración del entorno a nivel de inquilino. Estas configuraciones se aplican globalmente a todos los clientes a menos que se anulen a nivel de cliente.

Política de contraseñas

Define los requisitos de complejidad de contraseña para todos los usuarios en tu inquilino, en Usuarios → Configuración:

ConfiguraciónRangoPredeterminado
minPasswordLength6 – 1288
requireUppercaseActivado / DesactivadoActivado
requireLowercaseActivado / DesactivadoActivado
requireDigitActivado / DesactivadoActivado
requireSpecialCharActivado / DesactivadoActivado
Password policy settings showing minimum length slider and toggle switches for character requirements

Configuración de la política de contraseñas

Política de MFA

La política de MFA a nivel de inquilino, configurada en Usuarios → Configuración, establece el comportamiento predeterminado de autenticación multifactor. Los clientes individuales pueden anular esta configuración.

PolíticaComportamiento
DisabledMFA no está disponible. Los usuarios no pueden inscribirse en MFA.
EnabledMFA es opcional. Los usuarios pueden elegir inscribirse y se les solicitará al iniciar sesión si están inscritos.
RequiredMFA es obligatorio. Todos los usuarios deben inscribirse en MFA y completar un segundo factor en cada inicio de sesión.

Sesión y bloqueo

Controla la duración de la sesión y el comportamiento de bloqueo de cuenta:

ConfiguraciónRangoPredeterminado
sessionLifetimeMinutes5 – 43.200 (30 días)60
maxFailedAttempts1 – 1005
lockoutDurationMinutes1 – 1.440 (24 horas)10
Session and lockout settings with numeric inputs for session lifetime, max failed attempts, and lockout duration

Configuración de sesión y bloqueo

Webhooks

Los webhooks te permiten reaccionar a eventos de autenticación en tiempo real. Dos eventos (onUserAuthenticated, onTokenIssued) son aplicables — por defecto se disparan de forma asíncrona y no bloquean al usuario, pero puedes activar la aplicación por evento para que una respuesta no 2xx o un cuerpo {"allow": false} rechace la acción. El resto de eventos son notificaciones — siempre fire-and-forget, nunca bloquean.

EventoTipoDescripción
onUserAuthenticatedAplicableDisparado tras un inicio de sesión exitoso. Por defecto es fire-and-forget para que la latencia del login no se vea afectada. Activa <code>webhookEnforceUserAuthenticated</code> para hacerlo bloqueante — una respuesta no 2xx o un cuerpo <code>{"allow": false}</code> rechazará entonces el inicio de sesión.
onTokenIssuedAplicableDisparado antes de emitir tokens (authorization_code, refresh_token, client_credentials). Por defecto es fire-and-forget. Activa <code>webhookEnforceTokenIssued</code> para hacerlo bloqueante — una respuesta no 2xx o un cuerpo <code>{"allow": false}</code> impedirá entonces la emisión del token.
onUserCreatedNotificaciónNotificación de tipo dispara y olvida cuando un nuevo usuario se registra o es aprovisionado a través de SCIM.
onUserUpdatedNotificaciónNotificación fire-and-forget cuando se actualiza un registro de usuario (cambios de perfil, cambios de rol, actualizaciones SCIM).
onUserDeletedNotificaciónNotificación fire-and-forget cuando se elimina un usuario, ya sea desde el Portal/SCIM o por la política de retención.
onLoginFailedNotificaciónNotificación de tipo dispara y olvida cuando un intento de inicio de sesión falla por credenciales incorrectas, bloqueo o rechazo de política.

Configuraciones adicionales de webhooks:

ConfiguraciónRangoPredeterminadoDescripción
webhookTimeoutSeconds1 – 305Tiempo máximo de espera para una respuesta de webhook de aplicación antes de que expire
webhookFailOpenActivado / DesactivadoActivadoCuando está habilitado, si un webhook de aplicación no es alcanzable o expira, la operación se permite continuar
Webhook configuration section showing URL inputs for each event type, timeout slider, and fail-open toggle

Configuración de eventos de webhook

Disponibilidad de webhooks de aplicación

Los webhooks de aplicación pueden bloquear flujos de autenticación. Si tu endpoint de webhook deja de funcionar y webhookFailOpen está deshabilitado, ningún usuario podrá iniciar sesión. Usa el modo de apertura por fallo a menos que tengas requisitos estrictos de cumplimiento que exijan bloqueo en caso de fallo del webhook.

Verificar webhooks

Una vez configurada cualquier URL de webhook, Authagonal genera un secreto de firma por inquilino (un valor whsec_… que se muestra en modo de solo lectura en Ajustes → Webhooks). Cada entrega saliente lleva una cabecera X-Authagonal-Signature: t=<unix>,v1=<hex>, donde v1 es HMAC-SHA256(secret, "{t}.{body}") calculado sobre el cuerpo crudo de la solicitud. Vuelve a calcularlo en tu endpoint y compáralo en tiempo constante para confirmar que la solicitud realmente provino de Authagonal y no fue manipulada — y rechaza las entregas cuyo t sea demasiado antiguo para bloquear repeticiones.

Verificar un webhook (Node.js)
import crypto from 'node:crypto';

// rawBody MUST be the exact bytes Authagonal sent: verify before any JSON re-serialization.
function verifyAuthagonalWebhook(signatureHeader, rawBody, signingSecret) {
  const parts = Object.fromEntries(signatureHeader.split(',').map((p) => p.split('=')));
  const { t, v1 } = parts;

  // Replay protection: reject deliveries older than 5 minutes.
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;

  const expected = crypto
    .createHmac('sha256', signingSecret)
    .update(`${t}.${rawBody}`)
    .digest('hex');

  return v1.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

Rotar el secreto de firma

Usa Regenerar junto al secreto de firma para rotarlo — por ejemplo, tras una sospecha de filtración. El secreto anterior se invalida de inmediato, así que actualiza tu verificador con el nuevo valor o las entregas en curso comenzarán a fallar su comprobación de firma.

Ventana de mantenimiento

Establece una ventana de mantenimiento preferida para operaciones disruptivas como mover los datos de tu inquilino entre shards de almacenamiento. Elige una hora UTC (0–23); el portal también muestra la hora equivalente en tu zona horaria local para mayor comodidad.

Registro y acceso

Quién puede convertirse en usuario de tu inquilino, y en qué condiciones puede iniciar sesión.

ConfiguraciónPredeterminadoDescripción
Registro públicoActivadoSi cualquiera puede registrarse por su cuenta. Desactivarlo oculta la página de registro y rechaza la API de registro, lo cual importa: ocultar solo el enlace dejaría el endpoint abierto. Úsalo cuando aprovisionas tú mismo a los usuarios mediante SCIM, la API o invitaciones.
Exigir verificación del correo para iniciar sesiónActivadoUna dirección sin confirmar no puede iniciar sesión. Desactívalo si es tu propia aplicación la que controla la verificación; la reclamación email_verified sigue viajando en el token en cualquier caso, así que conservas la señal.
Registro dinámico de clientesDesactivadoPermite que un cliente se registre a sí mismo en tiempo de ejecución conforme al RFC 7591, que es lo que necesita un agente de IA o un conector MCP antes de poder iniciar un flujo. Desactivado de forma predeterminada, y habilitarlo abre la puerta solo para tu inquilino. Los registros siguen con límite de tasa y siguen exigiendo PKCE y consentimiento en cualquier caso.
Política de MFA del portalDeshabilitadoEl multifactor para tu propio equipo cuando inicia sesión en el portal, configurado de forma independiente de la política de tus usuarios finales. Deshabilitado, ofrecido en el inicio de sesión u obligatorio.
Máximo de usuariosNingunoNo hay límite de usuarios totales por defecto, y ningún plan establece uno. Mientras la dirección de correo del propietario del inquilino no esté verificada, se aplica un límite temporal de 5 usuarios; se elimina definitivamente en cuanto se verifica la dirección.

Retención de usuarios inactivos

De forma opcional, desactiva y después elimina las cuentas que han dejado de usarse, para que un directorio no acumule identidades inactivas para siempre. Ambas están desactivadas mientras no las configures, y la eliminación es permanente.

ConfiguraciónPredeterminadoDescripción
Desactivar después de (días de inactividad)NuncaDesactiva una cuenta que lleva este tiempo sin iniciar sesión. El registro se conserva y se puede reactivar.
Eliminar después de (días de inactividad)NuncaElimina la cuenta de forma permanente. No hay marcha atrás, así que configura la ventana de aviso y el webhook de abajo antes de activarlo.
Días de aviso7Con cuántos días de antelación a una desactivación o una eliminación se dispara el webhook de aviso, dándote tiempo para intervenir.
Webhook de retención-Dónde se publican esos avisos y las acciones ejecutadas, para que puedas avisar a la persona o mantener la cuenta abierta.

Exportación de auditoría y copias de seguridad remotas

Dos formas de sacar tus datos de forma programada en lugar de bajo petición. La exportación de auditoría envía cada día completo de eventos de auditoría a una URL que tú indiques, firmada para que puedas verificar que viene de nosotros, para alimentar un SIEM o un archivo de cumplimiento. Las copias de seguridad remotas mandan copias de tus copias diarias y semanales a un destino que controlas tú, sin autenticación, con autenticación básica o con un token Bearer. La exportación de auditoría se configura en la pestaña Exportar de la página Registro de auditoría y las copias de seguridad remotas en la página Respaldos; ambas son tuyas, independientes de las copias que guardamos nosotros.

Entornos sandbox

La página Entornos gestiona los entornos sandbox: entornos con nombre y aislados, con sus propios usuarios, clientes, claves de firma, inscripciones de MFA y concesiones, cada uno accesible en una URL separada. La marca, el plan y la facturación se comparten con live. Úsalos para probar cambios de configuración, integraciones SSO y endpoints de webhook sin afectar a los usuarios activos. Puedes crear hasta 5 por defecto, y los usuarios activos de sandbox cuentan para tu MAU.

AcciónDescripción
Agregar entornoCrea un nuevo entorno. El nombre tiene de 1 a 20 letras minúsculas y dígitos, y "live" está reservado. El entorno empieza vacío: no se copia nada desde live.
ActualizarBorra los datos del entorno y lo deja vacío.
BorrarElimina permanentemente el entorno sandbox y todos sus datos.

Cada entorno es accesible en {name}-{slug}.authagonal.io.

Environments page listing sandbox environments with their URLs and Refresh and Delete actions

Controles del entorno sandbox

Facturación

Gestiona tu suscripción y facturación a través de la página de Facturación del portal. Esta página te ofrece un resumen de tu plan actual y proporciona acceso al portal de facturación de Stripe para gestionar métodos de pago, facturas y cambios de plan.

Información de suscripción

La página de facturación muestra los detalles de tu suscripción actual de un vistazo. Verás una insignia de estado indicando el estado de tu suscripción — active, trialing, past_due, canceled o unpaid — junto con el nombre de tu plan, el período de facturación actual (fechas de inicio y fin), y si tu suscripción está configurada para cancelarse al final del período actual.

Gestionar suscripción

Haz clic en el botón Gestionar suscripción para abrir el portal de facturación de Stripe en una nueva ventana. Desde ahí puedes actualizar tus métodos de pago, ver y descargar facturas, cambiar tu plan o cancelar tu suscripción.

Si aún no existe una suscripción, se muestra un botón de Configurar facturación en su lugar, que te guía a través de la selección de un plan y la introducción de datos de pago.

Billing page showing subscription status, plan name, billing period, and Manage Subscription button

La página de facturación muestra los detalles de tu suscripción actual y proporciona acceso a Stripe

Seguridad de pagos

Toda la facturación se gestiona a través de Stripe. Tu información de pago nunca se almacena en los servidores de Authagonal.

Dominios personalizados

Sirve tus páginas de autenticación desde tu propio dominio (por ejemplo, auth.tudominio.com) en lugar del predeterminado {slug}.authagonal.io. Los dominios personalizados brindan a tus usuarios una experiencia de autenticación fluida y con tu marca.

Añadir un dominio

Ingresa el nombre de host que deseas usar en el formulario de añadir dominio (por ejemplo, auth.tudominio.com). Una vez añadido, el dominio aparecerá en tu lista de dominios con un estado pending_verification.

Verificación DNS

Crea los dos registros CNAME que el portal muestra para el dominio, ambos apuntando a {slug}.authagonal.io: uno en el propio nombre de host, que sirve el tráfico y puede pasar por proxy, y otro en _authagonal-challenge. seguido del nombre de host, que demuestra la propiedad y debe ser solo DNS (sin proxy). Una vez que los registros estén configurados, haz clic en Verificar DNS para comprobarlos. Los dominios pendientes también se vuelven a comprobar automáticamente.

CNAME records
auth.yourdomain.com.                        CNAME  acme.authagonal.io.
_authagonal-challenge.auth.yourdomain.com.  CNAME  acme.authagonal.io.

Propagación DNS

La propagación DNS puede tomar hasta 48 horas. Si la verificación falla, espera e intenta de nuevo.

Certificados TLS

Una vez que tu dominio esté verificado, necesitas un certificado TLS para que los usuarios puedan conectarse de forma segura a través de HTTPS. Authagonal soporta dos opciones:

Automático (cert-manager) — Authagonal aprovisiona y renueva certificados TLS automáticamente usando cert-manager. Esta es la opción recomendada para la mayoría de los usuarios. No se requiere configuración adicional.

Traer el propio (BYO) — Sube tu propio certificado y clave privada en formato PEM. Esta opción es útil si tu organización requiere certificados de una autoridad de certificación específica. Se hace seguimiento de la expiración del certificado para que puedas renovarlo antes de que caduque.

Estado del dominio

Cada dominio muestra una insignia de estado indicando su estado actual: pending_verification (DNS aún no confirmado), verified (DNS confirmado, TLS pendiente) o active (totalmente operativo).

Domain list showing domains with status badges and verification controls

La lista de dominios muestra cada dominio personalizado y su estado actual

BYO certificate upload form with certificate and private key PEM fields

Sube tu propio certificado TLS y clave privada en formato PEM

Renovación de certificado BYO

Mantén tu certificado BYO renovado. Los certificados expirados causarán advertencias de seguridad del navegador para tus usuarios.

Organizaciones

Una organización es un cliente dentro de un inquilino. El inquilino sigue siendo el límite de aislamiento: un prefijo de tabla y una clave de firma, y cada host del inquilino es su propio emisor. Una organización particiona la identidad dentro del inquilino, de modo que un único inquilino puede atender a muchas organizaciones cliente sin necesitar un inquilino por cliente.

Las organizaciones conviven con los dominios personalizados (un dominio puede fijarse a una) y con las aplicaciones de aprovisionamiento (una aplicación de aprovisionamiento puede etiquetar a un usuario nuevo con una organización). Consulta la guía de aplicaciones multicliente para el patrón completo de “un inquilino, muchos clientes con marca propia” para el que existe esta función.

Modelo e ids

Cada organización tiene un id estable e inmutable (con la forma org_<32 hex>) que se emite como el claim de token org_id, y un slug inmutable y único en el inquilino que se emite como org_slug y que acepta el parámetro de autorización organization. Los ids y los slugs comparten un único espacio de búsqueda: un slug igual al id de otra organización se rechaza como colisión, exactamente igual que un slug duplicado normal.

CampoModificableDescripción
idNoEl claim org_id. Se genera como org_ + un GUID: el guion bajo no es válido en un slug, así que un id nuevo nunca puede colisionar con un slug.
slugNoEl claim org_slug, y lo que acepta el parámetro organization. Es inmutable porque una relying party lo codifica de forma fija.
nameSíEl claim <code>org_name</code>. Se puede editar libremente.
metadataSíPares clave/valor de formato libre, controlados por el inquilino. Nunca se emiten en un token a menos que el conjunto de claims de un scope libere uno de forma explícita.
brandingJsonSíObjeto JSON que se combina campo por campo sobre la marca del inquilino. Consulta Sobrescritura de marca más abajo.
domainsSolo mediante los endpoints de dominioLos dominios de correo que la organización ha reclamado, cada uno con el registro DNS que lo demuestra. Solo se modifican mediante los endpoints de dominio de abajo, nunca con una actualización.

Membresías

Una membresía es la unión de muchos a muchos entre un usuario y una organización: una fila por cada par (organización, usuario). Un usuario puede tener varias; la fila de membresía, no la etiqueta de organización heredada por usuario, es lo que autoriza iniciar sesión como una organización.

Estado¿Concede tokens?
invitedInvitado pero aún sin aceptar. No autoriza la emisión de tokens.
activeUn miembro en regla. Es el único estado que autoriza la emisión de tokens.
suspendedMembresía retirada sin eliminar el registro. No autoriza la emisión de tokens.

Los roles de una membresía se toman del catálogo de roles existente del inquilino y se unen en el claim roles, pero solo cuando la organización fue seleccionada explícitamente por la solicitud (consulta Selección de organización en el token) y únicamente a partir de una fila de membresía activa. Un rol que se tiene en una organización nunca llega a un token emitido para otra.

Invitar a una organización

POST /api/v1/users/invite acepta organizationId y organizationRoles opcionales. Una sola llamada crea la cuenta con una membresía invited y envía un correo de invitación con la marca de la organización. El enlace se abre en el dominio personalizado fijado a la organización, si lo tiene. Cuando la persona acepta, la membresía pasa a active. Indicar una organización requiere ser propietario o administrador.

Aprovisionamiento SCIM en una organización

Un token SCIM puede vincularse a una organización (organizationId en POST /api/v1/scim/tokens, o el selector de organización al crear un token). El id debe corresponder a una organización del inquilino. Cada usuario que cree ese token pasa a ser miembro active y lleva la organización como org_id. La vinculación se aplica solo en la creación y decide la membresía, no el acceso: dos tokens de un mismo cliente siguen viéndose mutuamente los usuarios. Eliminar un usuario, por cualquier vía, elimina sus membresías.

Indicadores de política

enabled (activado por defecto): una organización deshabilitada no emite tokens para sí misma, y esto se comprueba tanto en la autorización como en cada refresco, de modo que deshabilitarla detiene las sesiones activas en su siguiente rotación y no solo bloquea los inicios de sesión nuevos.

requireMembershipForTokens (activado por defecto): indica si un usuario debe tener una membresía activa para que se le emita un token para esta organización. Solo se aplica con una selección explícita (una solicitud que nombra la organización, un refresco que la lleva, una conexión con alcance de organización o un cliente restringido a exactamente una). Una organización simplemente heredada de la etiqueta heredada de la propia cuenta nunca queda sujeta a este indicador.

allowAutoMembership (desactivado por defecto) permite que un usuario se una sin invitación cuando su dirección de correo confirmada pertenece a uno de los dominios verificados de la organización. Se aplica en la autorización y en cada refresco. Consulta Dominios de correo y membresía automática más abajo.

Dominios de correo y membresía automática

Una organización reclama un dominio de correo y demuestra que lo controla con un registro DNS TXT. Con allowAutoMembership activado, un usuario cuya dirección de correo confirmada pertenece a ese dominio pasa a ser miembro la primera vez que inicia sesión como la organización.

  1. Reclámalo. POST /api/v1/organizations/{id}/domains con el dominio. La respuesta es 201 con recordName (_authagonal-org.acme.com) y recordValue (authagonal-org-verify=<token>). El token es aleatorio y distinto por cada reclamación.
  2. Publica el registro. Añade en el DNS del dominio un registro TXT con ese nombre y ese valor exacto.
  3. Verifícalo. POST /api/v1/organizations/{id}/domains/{domain}/verify busca el registro. Si coincide, devuelve 200 con verified: true. Si no, devuelve 409 verification_failed, nunca 200 con verified: false, para que un cliente que sondea el éxito no confunda un fallo con un acierto.
  4. Elimínalo. DELETE /api/v1/organizations/{id}/domains/{domain} devuelve 204. Las membresías existentes se conservan; solo dejan de producirse nuevas incorporaciones automáticas.
POST /api/v1/organizations/{id}/domains
POST /api/v1/organizations/org_7fa2c9e1.../domains
Content-Type: application/json

{ "domain": "acme.com" }

201 Created
{
  "domain": "acme.com",
  "verified": false,
  "verifiedAt": null,
  "createdAt": "2026-10-03T01:02:03Z",
  "recordName": "_authagonal-org.acme.com",
  "recordValue": "authagonal-org-verify=Qm9...base64url"
}

Rechazos: 400 domain_invalid (no es un nombre DNS simple), 409 domain_exists (ya está en esta organización), 409 domain_taken (otra organización del inquilino lo tiene), 404 organization_not_found y 404 domain_not_found. Un dominio pertenece como máximo a una organización por inquilino, y esto se vuelve a comprobar en el momento de verificar.

La regla de membresía automática

El selector admite a un usuario que no tiene ninguna membresía activa cuando se cumplen todas estas condiciones:

  • La organización fue seleccionada explícitamente: un grant de refresco transportado, una conexión con alcance de organización, el parámetro organization (un dominio fijado lo aporta) o un cliente restringido a exactamente una organización. La etiqueta heredada de la propia cuenta nunca incorpora automáticamente.
  • La organización está habilitada y allowAutoMembership está activado.
  • El correo del usuario está confirmado, porque cualquiera puede registrarse como [email protected].
  • La parte del correo posterior a su último @, en minúsculas, es exactamente igual a uno de los dominios de la organización que ha sido verificado. No hay coincidencia de subdominios: un acme.com verificado no admite a [email protected]. Reclama y verifica cada subdominio por separado.

Lo que escribe, antes de que se ejecute la comprobación de membresía: si no hay fila, se crea una nueva membresía active sin roles; una fila invited se promueve a active conservando sus roles; una fila active se deja intacta; una fila suspended nunca se promueve.

Eliminar a un miembro no lo mantiene fuera

Mientras allowAutoMembership esté activado, un miembro eliminado que siga cumpliendo los requisitos vuelve a unirse en su siguiente autorización o refresco. Para mantener fuera a un usuario que cumple los requisitos, establece su membresía en suspended, el único estado que la regla nunca modifica.

Selección de organización en el token

La organización a la que se resuelve una solicitud se decide en un único lugar, de modo que la respuesta es idéntica en /connect/authorize, en cada refresco y en el device grant. Precedencia, de mayor a menor:

#OrigenComportamiento
1Grant transportado (refresco)La organización para la que se emitió un token anterior. Si ya no existe, se rechaza el propio refresco en lugar de recurrir a cualquier otra cosa.
2Conexión con alcance de organizaciónLa sesión inició sesión a través de una conexión SAML u OIDC que pertenece a una organización, por lo que se selecciona esa organización. Es el único origen que está demostrado en lugar de afirmado. Se rechaza una solicitud que nombra una organización distinta, y también una conexión cuya organización ya no existe.
3organizationSe resuelve primero por slug y después por id. Un dominio fijado llega a esta misma rama: el middleware lo añade antes de evaluar la solicitud. Si se nombra y no se encuentra, es un rechazo firme, nunca un retroceso silencioso.
4Cliente restringido a exactamente una organizaciónSe selecciona automáticamente: una aplicación por cliente registra su única organización una vez y nunca envía un parámetro. Si está restringido a <em>más</em> de una y no hay indicación, se rechaza con <code>account_selection_required</code>.
5Etiqueta de organización heredada de la propia cuentaUna única cadena plana, resuelta por id en una sola búsqueda, no un recorrido por las membresías del usuario. Si no corresponde a ninguna fila de organización real, se emite tal cual y sin restricciones, exactamente como antes de que existieran las organizaciones. Nunca es una selección explícita, por lo que nunca incorpora automáticamente.
6Ninguna de las anterioresNinguna organización en el token: ni claim <code>org_id</code>, ni <code>org_slug</code>, ni <code>org_name</code>.

Las membresías nunca son la pista

Un usuario con varias membresías activas y una solicitud que no nombra ninguna se comporta exactamente igual que un usuario sin membresías: nunca se consulta la tabla de membresías para elegir un valor predeterminado. La selección pasa directamente a la etiqueta heredada de la propia cuenta (fila 5) y, si también está vacía, el token no lleva ninguna organización. Las membresías solo empiezan a importar después de que una organización ya se ha nombrado de forma explícita, que es cuando se comprueba requireMembershipForTokens y, si procede, se intenta una incorporación automática.

Fijación de dominio

Un dominio personalizado puede fijarse a una organización, convirtiéndolo en la puerta de entrada propia de esa organización. La fijación la aplica el middleware de resolución de inquilino tanto para GET /connect/authorize (se añade a la cadena de consulta) como para POST /connect/par (en este caso se reescribe el cuerpo enviado, ya que PAR lee sus parámetros del contenido almacenado). Consulta Dominios personalizados para ver el mecanismo completo.

PUT /api/v1/custom-domains/{domain}/organization
PUT /api/v1/custom-domains/auth.acme.com/organization
Content-Type: application/json

{ "organizationId": "org_7fa2c9e1..." }

Un dominio fijado rechaza una solicitud en conflicto

Una solicitud que nombra una organización distinta de la fijada se rechaza directamente con 400 access_denied, antes de mostrar cualquier página de inicio de sesión. Sin esto, una relying party podría enviar su propio parámetro organization y la fijación sería meramente decorativa.

Conexiones con alcance de organización

Una conexión SAML u OIDC puede pertenecer a una organización. Iniciar sesión a través de ella selecciona esa organización y crea una membresía active cuando el usuario no tiene ninguna. Una fila invited se acepta: pasa a active y conserva sus roles y quién la invitó, de modo que un invitado que inicia sesión mediante su IdP nunca necesita el correo. Un miembro suspended sigue suspendido y se le rechaza en la emisión del token. Esto no depende de allowAutoMembership ni de los dominios, porque la organización ya quedó elegida por la conexión.

El nombre de la organización en la página de inicio de sesión

La página de inicio de sesión muestra Iniciando sesión en {name} bajo el nombre de la aplicación. El nombre proviene de la misma organización de la que proviene la marca de la página: la organización del dominio fijado, luego la organización nombrada por la solicitud de autorización y, por último, la única organización restringida del cliente. Se oculta cuando no hay organización o cuando el nombre de la organización es igual al nombre de la aplicación, de modo que el encabezado nunca diga “Acme / Iniciando sesión en Acme”.

Sobrescritura de marca

El brandingJson de una organización se combina campo por campo sobre la marca del inquilino para la página de inicio de sesión: una clave presente y no nula sobrescribe, una clave ausente o nula hereda, y una clave desconocida se ignora. Un JSON mal formado vuelve a la marca propia del inquilino y registra una advertencia, sin que la página deje de cargarse.

La pestaña Marca edita los 21 campos combinables: apariencia (appName, logoUrl, primaryColor, customCssUrl), colores de los modos claro y oscuro, colores de correo, supportEmail, showForgotPassword, poweredBy y languages. Cada campo hereda el valor del inquilino, mostrado como pista, o lo sobrescribe, con un control Borrar que elimina la clave.

showRegistration no se puede sobrescribir

El ajuste de registro público del inquilino ya decidió si se ofrece el registro, y el endpoint de registro lo aplica independientemente de la marca. Una organización no es la autoridad para esa decisión, así que este campo queda excluido de la combinación y no tiene ningún control en la pestaña Marca.

Migración desde la etiqueta de organización heredada

Antes de que existieran las organizaciones, un usuario podía llevar una etiqueta de organización de texto libre sin ningún registro detrás. POST /api/v1/organizations/backfill la migra a organizaciones y membresías reales, agrupadas por cada valor heredado distinto. Es una simulación salvo que el cuerpo sea { "dryRun": false }.

  • Acotada: analiza como máximo 50 000 usuarios por llamada. Una respuesta truncated significa que debes ejecutarla de nuevo; los usuarios ya migrados se omiten en la nueva ejecución.
  • Idempotente: un valor heredado distinto ya migrado se reconoce mediante una marca interna, no por el nombre visible (editable) de la organización, así que cambiar después el nombre de la organización resultante no provoca un duplicado en la siguiente ejecución.
Respuesta de ejemplo (simulacro)
{
  "dryRun": true,
  "organizationsCreated": 3,
  "membershipsCreated": 41,
  "usersSkipped": 0,
  "organizations": [
    { "legacyValue": "acme-corp", "slug": "acme-corp", "users": 22 }
  ],
  "truncated": false
}

Recorrido por la interfaz del portal

La página Organizaciones muestra todas las organizaciones del inquilino, de 50 en 50 con un botón Cargar más, y ofrece Nueva organización (solo slug y nombre; los indicadores de política, los dominios y la marca se configuran después) y un flujo Rellenar desde el campo de organización heredado que ejecuta primero la migración anterior como vista previa y luego permite Aplicar.

Organizations list showing slug, name, and created-date columns, with New Organisation and Backfill from legacy organisation field controls

La lista de organizaciones muestra cada organización cliente del inquilino con su slug, nombre y fecha de creación

La página de detalle de cada organización tiene tres pestañas: General (nombre, slug de solo lectura, los tres interruptores de política, una tarjeta Dominios de correo para añadir, verificar y eliminar dominios de correo y copiar el registro TXT, y una eliminación que exige escribir el slug para confirmar), Branding (cada campo sobrescribible, que hereda el valor del inquilino o lo sobrescribe) y Miembros (añadir por correo, con una invitación ofrecida cuando no existe ninguna cuenta, cambio de estado y eliminación por fila, con Cargar más).

Organization detail page's Members tab showing invited, active, and suspended member rows with per-row status control

La pestaña Miembros lista cada membresía con su estado y un control por fila para cambiarla o eliminarla

Organization detail page's Branding tab with each overridable field showing either the tenant's inherited value or an override with a Clear control

La pestaña Marca sobrescribe, campo por campo, la marca de la página de inicio de sesión del inquilino para esta organización

La página Dominios incluye el selector de dominio → organización: cada tarjeta de dominio tiene un desplegable en línea que lista las organizaciones del inquilino más una opción “Inquilino (ninguno)” que quita la fijación, y se aplica al instante al cambiar. El mismo selector aparece al añadir un dominio.

Domain card showing the inline organisation selector that pins a custom domain to one organisation

El selector de organización en línea de una tarjeta de dominio fija ese dominio personalizado a una organización

Eventos de auditoría

organization.created · organization.updated · organization.deleted · organization.member.added · organization.member.invited · organization.member.joined · organization.member.updated · organization.member.removed · organization.domain_added · organization.domain_verified · organization.domain_removed · organization.backfill · domain.organization_set

Paginación

La lista de organizaciones y la lista de miembros se paginan por cursor y responden { items, nextCursor }. Pasa limit (50 por defecto, limitado de 1 a 200) y, tras la primera página, el nextCursor de la respuesta anterior sin modificar como cursor. Un nextCursor nulo indica la última página. El cursor es una posición de conjunto de claves opaca sobre el id de la organización (o el id de usuario para los miembros), de modo que añadir o quitar filas entre llamadas no puede desplazar ni repetir una página. Un cursor que el listado no emitió produce 400 invalid_cursor.

Gestionar organizaciones desde un asistente de IA

El MCP del portal alojado expone trece herramientas de organizaciones, todas con el rol de administrador del inquilino: listar, obtener, crear, actualizar y eliminar organizaciones; listar, añadir, actualizar y eliminar miembros; añadir, verificar y eliminar dominios de correo; y listar las organizaciones de un usuario. Llaman a las mismas operaciones que la API de arriba, así que una herramienta no puede desviarse de su ruta. Consulta Gestiona tu portal desde un asistente de IA.

Un emisor por host

Cada host de un inquilino es su propio emisor OIDC. Cuando el host de la solicitud se resolvió mediante la tabla de dominios del inquilino, el emisor y cada URL de endpoint que anuncia el discovery es https://{host}, por lo que cada dominio personalizado activo declara su propio iss y el host canónico del inquilino no cambia. Las claves de firma son por inquilino, así que todos los hosts sirven el mismo conjunto de claves. Esto es lo que permite que un inquilino atienda a varios clientes, cada uno en su propio dominio con marca propia fijado a su propia organización. Consulta Dominios personalizados.

Configuración de correo

Configura cómo tu inquilino envía correos transaccionales, como los de verificación, restablecimiento de contraseña e invitación. Elige entre el remitente compartido predeterminado, un dominio personalizado verificado mediante Resend o tu propio servidor SMTP.

Email settings showing provider options (default, Resend domain, custom SMTP) and a test-send

Correos localizados

Los correos transaccionales se envían en el idioma preferido del destinatario. Los correos de verificación, restablecimiento de contraseña, cuenta existente, bienvenida, invitación, eliminación de cuenta, soporte y facturación están plantillados en once idiomas: inglés, alemán, francés, español, portugués, vietnamita, chino simplificado, japonés, árabe, hindi y afrikáans. Cuando no existe una plantilla para el idioma del destinatario, el correo recurre al inglés.

El idioma se resuelve a partir de la preferencia almacenada del destinatario en el momento del envío. Esa preferencia puede provenir de varios lugares:

  • Registro y alta — capturado del idioma que el usuario eligió en las pantallas de inicio de sesión alojadas.
  • La página de Usuarios del portal — definida por un administrador al crear o editar un usuario.
  • El aprovisionamiento SCIM: mapeado desde el preferredLanguage (o locale) del IdP cuando los usuarios se sincronizan mediante SCIM.
  • La página de cuenta de autoservicio — elegida por el propio usuario en /login/account.

No requiere configuración

La localización es automática y se aplica a todos los modos de proveedor (predeterminado, dominio personalizado de Resend y SMTP). No hay nada que activar.

Proveedores de correo

ProveedorDescripciónConfiguración
Authagonal (Default)Correos enviados desde [email protected] usando nuestra infraestructura compartida de Resend.No requiere configuración — funciona desde el primer momento.
Custom Domain (Resend)Correos enviados desde tu propio dominio verificado mediante Resend.Registra tu dominio, añade registros DNS, verifica la propiedad.
Custom SMTPCorreos enviados a través de tu propio servidor SMTP.Proporciona host, puerto, credenciales y ajustes TLS del SMTP.

Identidad del remitente

El correo y el nombre del remitente se comparten en todos los modos de proveedor. El correo del remitente es obligatorio para los proveedores Dominio personalizado (Resend) y SMTP personalizado; si el nombre del remitente está vacío, se usa el nombre de la aplicación configurado en la marca.

CampoDescripción
emailSenderEmailLa dirección From en los correos salientes. Debe estar en un dominio verificado para el modo Dominio personalizado (Resend).
emailSenderNameNombre para mostrar que aparece en la bandeja de entrada del destinatario.

Dominio personalizado de Resend

Verifica tu dominio de envío con Resend una sola vez y úsalo como dirección de remitente para este inquilino. Los registros DNS (SPF, DKIM) se muestran en el panel Dominio de envío personalizado de Configuración → Correo; Resend los comprueba cuando haces clic en <strong>Verificar</strong>.

SMTP personalizado

Usa tu propio servidor SMTP — útil para relays internos, proveedores no cubiertos por Resend o fijación regulatoria.

CampoDescripción
smtpHostNombre de host del servidor SMTP (p. ej. smtp.example.com).
smtpPortPuerto de conexión, 587 por defecto. TLS se negocia con STARTTLS; no se admite TLS implícito en el puerto 465. Usa 25 para relays internos sin autenticación.
smtpUsernameUsuario de autenticación (opcional — déjalo en blanco para relays sin autenticación).
smtpPasswordContraseña de autenticación. Se almacena cifrada en el secreto de configuración del inquilino.
smtpUseTlsRequerir TLS. Déjalo activado salvo que dirijas a un relay interno confiable.

Dominio de envío personalizado

Con el proveedor Dominio personalizado (Resend) puedes registrar tu propio dominio para que los correos provengan de tu marca (por ejemplo, [email protected]) en lugar de @authagonal.io.

  1. Ve a Configuración → Correo y selecciona el proveedor Dominio personalizado (Resend).
  2. Introduce tu nombre de dominio y haz clic en Registrar dominio.
  3. Añade los registros DNS mostrados (DKIM, SPF y return path) al DNS de tu dominio.
  4. Haz clic en Comprobar verificación — cuando el DNS se propague (normalmente 1–10 minutos), el estado del dominio cambiará a verificado.

Propagación de DNS

Los cambios de DNS pueden tardar hasta 48 horas en propagarse globalmente, aunque la mayoría de los proveedores se actualizan en minutos. Puedes comprobar la verificación tantas veces como necesites.

Pruebas

Usa el botón Enviar correo de prueba en Ajustes → Correo para verificar tu configuración. Se enviará un correo de prueba a tu dirección de administrador usando los ajustes guardados.

Registro de auditoría

El Registro de auditoría proporciona un registro de solo lectura de todas las acciones administrativas realizadas en tu inquilino. Cada cambio realizado a través del portal o la API se captura con contexto completo, dándote un rastro completo para cumplimiento y resolución de problemas.

Columnas del registro

ColumnaDescripción
Marca de tiempoLa fecha y hora en que ocurrió la acción
ActorLa dirección de correo electrónico del administrador que realizó la acción, o "system" para acciones automatizadas
AcciónEl tipo de acción realizada (por ejemplo, Cliente creado, Configuración actualizada)
EntidadEl objetivo de la acción en formato tipo:id (por ejemplo, client:my-app)
DetalleContexto adicional sobre el cambio

Acciones registradas

Las siguientes acciones administrativas se registran en el registro de auditoría:

CategoríaAcciones
ClientesCliente creado, Cliente actualizado, Cliente eliminado
Conexiones SSOConexión SAML creada, Conexión SAML eliminada, Conexión OIDC creada, Conexión OIDC eliminada
UsuariosUsuario creado, Usuario actualizado
ConfiguraciónConfiguración actualizada, Marca actualizada
DominiosDominio añadido, Dominio verificado, Dominio eliminado
SCIMToken SCIM creado, Token SCIM revocado
RolesRol creado, Rol actualizado, Rol eliminado
GruposGrupo creado, Grupo eliminado
EquipoMiembro del equipo invitado, Miembro del equipo eliminado
Audit log table showing timestamped administrative actions with actor, action, entity, and detail columns

El registro de auditoría proporciona un registro completo de todas las acciones administrativas

Retención

Los registros de auditoría se conservan durante 365 días y no pueden ser modificados ni eliminados. Para conservarlos más tiempo, activa la exportación automática desde la pestaña Exportar de la página Registro de auditoría.

Copias de seguridad

Authagonal realiza copias de seguridad automáticas de los datos de tu inquilino cada hora. Las copias incluyen todos los usuarios, grupos, roles, clientes, conexiones SSO, tokens SCIM, marca y ajustes. Puedes ver el historial y descargar la última copia completa desde la página de Copias de seguridad.

Backups page showing backup history with timestamps, types, and entity counts

Cómo funcionan las copias

  • Una vez al día, las copias incrementales horarias se consolidan en una nueva copia completa, y los domingos las copias completas diarias se consolidan en una copia semanal. Se conservan siete copias diarias y cuatro semanales.
  • Las copias incrementales se ejecutan cada hora, capturando solo las filas que cambiaron desde la última copia.
  • Las copias se almacenan en Azure Blob Storage con la misma identidad administrada que usa tu inquilino.
  • Los registros eliminados se rastrean mediante tombstones y se incluyen en las copias para completitud de auditoría.

Descargar copias

Haz clic en "Descargar última" para obtener un archivo ZIP con la copia completa más reciente fusionada con todas las copias incrementales posteriores. Cada tabla se exporta como un archivo JSONL (un objeto JSON por línea).

Formato de copia

Las copias se exportan como JSONL (JSON Lines) — una entidad por línea y por tabla. Este formato es fácil de analizar, comparar e importar en otros sistemas.

Aplicaciones de aprovisionamiento

Las aplicaciones de aprovisionamiento son tus propios servicios. Authagonal las llama cada vez que se crea un usuario, para que puedan crear una cuenta, asignar una licencia, decidir a qué organización pertenece el usuario o rechazar el registro por completo.

Cómo funciona

Cuando se crea un usuario, Authagonal llama a la URL de callback de tu aplicación de aprovisionamiento siguiendo el patrón TCC (Try/Confirm/Cancel). Todas las aplicaciones deben aceptar en la fase Try antes de confirmar ninguna, de modo que varios sistemas posteriores puedan ponerse de acuerdo, o uno pueda vetar, sin dejar cuentas a medio crear.

FaseEndpointPropósito
/tryPOST {callbackUrl}/tryVerifica si la aplicación puede manejar al usuario. Devuelve 200 para aceptar o 4xx para rechazar.
/confirmPOST {callbackUrl}/confirmConfirma la operación después de que todas las aplicaciones hayan aceptado la fase /try.
/cancelPOST {callbackUrl}/cancelRevierte la operación si otra aplicación falla durante la fase /try.

Cuándo se ejecuta el aprovisionamiento

El aprovisionamiento se ejecuta en todas las rutas que crean un usuario, no solo en el registro autoservicio. Las combinaciones de aplicación y usuario ya aprovisionadas se omiten, por lo que una aplicación ve cada usuario una sola vez.

Ruta de creaciónCuándo se activa
POST /api/auth/registerRegistro autoservicio
Callback SAML ACSPrimer inicio de sesión SSO de un usuario nuevo (JIT)
Callback OIDCPrimer inicio de sesión SSO de un usuario nuevo (JIT)
POST /scim/v2/UsersUn conector aprovisiona un usuario desde el directorio del cliente
Creación de usuarios en el portal y en el adminUn operador crea o invita a un usuario manualmente

La solicitud Try

Authagonal envía este JSON por POST a <code>{callbackUrl}/try</code>. Los campos sin valor se omiten en lugar de enviarse como null.

CampoTipoDescripción
transactionIdstringIdentifica esta transacción de aprovisionamiento. El mismo valor se envía a /confirm y /cancel, así que prepara tu trabajo asociado a él y confírmalo o descártalo cuando llegue esa llamada.
userIdstringEl id de Authagonal del usuario. Es el subject que verás en sus tokens.
emailstringLa dirección de correo electrónico del usuario.
firstNamestringNombre de pila, cuando la ruta de creación ha proporcionado uno.
lastNamestringApellido, cuando la ruta de creación ha proporcionado uno.
organizationIdstringLa organización a la que ya pertenece el usuario, si la hay. Solo está presente cuando algo le ha asignado una antes. En un primer registro no aparece, y esa es la señal para asignarla.
customAttributesobjectLos atributos personalizados almacenados del usuario. En un usuario creado mediante SSO incluyen federated_connection, el nombre de la conexión que ha respondido por él.

El caso habitual que conviene prever es el de un usuario que llega por SSO: todavía no tiene organización, y federated_connection te dice de cuál de tus clientes procede.

Solicitud Try para un usuario que llega por una conexión SSO
{
  "transactionId": "8f14e45fceea167a5a36dedd4bea2543",
  "userId": "0f6b1c8e-3d2a-4f51-9e77-2c1a4b5d6e7f",
  "email": "[email protected]",
  "firstName": "Ada",
  "lastName": "Lovelace",
  "customAttributes": {
    "federated_connection": "acme-okta"
  }
}

La respuesta Try

Tu aplicación responde con un 200 y un cuerpo JSON. El cuerpo no es solo un acuse de recibo: es la forma en que una aplicación posterior asigna la organización y los atributos que acaban en los tokens del usuario.

CampoTipoDescripción
approvedbooleanIndica si esta aplicación acepta al usuario. Si se omite, el valor por defecto es true. False rechaza el registro y la cuenta nueva se elimina.
reasonstringPor qué se rechazó al usuario. Se muestra a quien invoca la ruta de creación.
organizationIdstringLa organización a la que pertenece este usuario. Se guarda en el usuario y se emite como el claim org_id en sus tokens. Solo se aplica si el usuario no tiene ya una, de modo que gana la primera aplicación que responde y las posteriores ven esa asignación.
customAttributesobjectAtributos que se fusionan en el usuario, clave por clave. Se emiten en los tokens a través de la configuración UserClaims de un scope.
emailVerifiedbooleanTu aplicación garantiza que ha verificado esta dirección, por ejemplo mediante el canje de una invitación enviada a ella. Authagonal marca la cuenta como confirmada y omite su propio correo de verificación.
Respuesta Try que asigna una organización
{
  "approved": true,
  "organizationId": "org_acme",
  "customAttributes": { "org_role": "member" }
}

De aquí viene org_id

La etiqueta de organización de la cuenta, y por tanto el claim org_id cuando una solicitud no indica ninguna organización, es exactamente lo que tu aplicación de aprovisionamiento haya devuelto como organizationId. Cuando es el id de una organización del inquilino, los tokens llevan el org_id, el org_slug y el org_name de esa organización, y una organización deshabilitada rechaza el inicio de sesión. Cualquier otro valor se emite literalmente como org_id, sin regla de unicidad ni requisito de formato. Devolver un id de organización no crea una membresía. También puedes establecerlo directamente con PUT /api/v1/users/{userId} y filtrar por él con GET /api/v1/users?organizationId=.

Etiquetar a los usuarios con la organización correcta

Decide la organización aquí, en un solo lugar, en vez de en cada ruta de creación. Un usuario de SSO lleva federated_connection, que identifica la conexión que lo autenticó y, por tanto, al cliente, y sigue siendo correcto cuando un mismo cliente federa varios dominios de correo. Un usuario invitado no tiene conexión, así que identifícalo por la invitación que emitiste. Ambas rutas llegan a /try antes de que el usuario exista, de modo que una sola lógica las cubre y no hay dos reglas que puedan divergir.

Resolver la organización en el callback Try
// POST {callbackUrl}/try
app.post('/provisioning/try', async (req, res) => {
  const { email, customAttributes } = req.body;

  // An SSO user carries the connection that vouched for them. That is the
  // customer, and it stays right when one customer has several domains.
  const connection = customAttributes?.federated_connection;

  const org = connection
    ? await orgByConnection(connection)
    : await orgByPendingInvite(email);

  if (!org) return res.json({ approved: false, reason: 'No organization for this user' });

  // Stamped on the user and emitted as org_id on every token from now on.
  res.json({ approved: true, organizationId: org.id });
});

El rechazo elimina la cuenta

Si alguna aplicación responde approved: false, el usuario recién creado se elimina para que no quede ninguna cuenta a medio aprovisionar. Las rutas de creación de la API devuelven 422 con tu reason; los callbacks SAML y OIDC devuelven 400. Devuelve approved: true para un usuario con el que no tengas nada que hacer.

Añadir una aplicación de aprovisionamiento

Para añadir una aplicación de aprovisionamiento, proporciona un Nombre de la aplicación, una URL de callback, una Clave API opcional y un Tiempo de espera de Try opcional (en segundos, 60 por defecto, rango de 5 a 300; Confirm y Cancel usan un tiempo de espera corto fijo). La clave API se envía como token Bearer en el encabezado Authorization de cada solicitud de webhook, permitiendo que tu aplicación autentique las solicitudes de Authagonal.

Pruebas

Haz clic en Probar junto a cualquier aplicación de aprovisionamiento para enviar una solicitud de prueba a tu URL de callback. Los resultados de la prueba muestran el código de estado HTTP y el cuerpo de la respuesta, ayudándote a verificar que tu aplicación está recibiendo y procesando webhooks correctamente.

Provisioning apps page showing configured apps with test results displaying HTTP status and response body

Prueba las aplicaciones de aprovisionamiento para verificar la entrega y manejo de respuestas del webhook

Límites del plan

El número máximo de aplicaciones de aprovisionamiento es configurable por inquilino, con un límite predeterminado de 6. Este límite puede ser ajustado por un administrador si tu flujo de trabajo requiere objetivos de aprovisionamiento adicionales.

Autenticación con clave API

Si se configura una clave API, se envía como token Bearer en el encabezado Authorization. Úsala para autenticar las solicitudes de webhook de Authagonal.

Equipo

La página de Equipo gestiona los administradores del portal: las personas que pueden acceder y configurar tu inquilino a través del portal de gestión. Cada miembro del equipo tiene un rol (Owner, Admin, Developer o Support) que decide qué puede cambiar.

Lista de administradores

La lista de administradores muestra el nombre, la dirección de correo electrónico, el rol y la fecha en que fue añadido cada miembro del equipo. Un indicador "Usted" se muestra junto a la fila del usuario actual para que puedas identificar fácilmente tu propia cuenta.

Invitar administradores

Para invitar a un nuevo miembro del equipo, proporciona su dirección de correo electrónico, nombre y rol. Recibirá un correo electrónico con un enlace para establecer su contraseña y activar su cuenta; el enlace es válido durante 7 días.

Campos de invitación

Las invitaciones de administrador crean una cuenta pendiente y envían al invitado un enlace de activación por correo electrónico.

CampoDescripción
emailDirección de correo del nuevo admin. Debe ser única en el inquilino.
nameNombre mostrado en la lista de administradores.
roleRol que se concede: tenant:admin, tenant:developer o tenant:support. Por defecto, tenant:admin. El rol de propietario no se puede conceder por invitación.

Eliminar administradores

El propietario del inquilino puede hacer clic en Eliminar junto a cualquier miembro del equipo para revocar su acceso. Se muestra un diálogo de confirmación antes de que la eliminación se finalice. No puedes eliminarte a ti mismo, y el inquilino siempre conserva a su propietario.

Team page showing the admin list with name, email, date added columns, a You indicator, and invite/remove controls

Gestiona los administradores del portal desde la página de Equipo

Propiedad

Cada inquilino tiene un propietario. Solo el propietario puede eliminar miembros del equipo o transferir la propiedad, usando Hacer Owner en otro miembro; el propietario anterior pasa a ser Admin.

Soporte

Abre un ticket de soporte con el equipo de Authagonal sin salir del portal. Cada ticket es una conversación con hilo, así que tú y nuestro equipo estáis siempre alineados, desde el primer reporte hasta la resolución.

Tus tickets

La página de soporte lista todos los tickets que has abierto, con la actividad más reciente primero. Usa la insignia de estado para ver de un vistazo qué está esperando por ti y qué está esperando por nosotros.

Support ticket list showing each ticket's subject, status badge, priority, and last-activity time, with a New ticket button

Tus tickets de soporte con asunto, estado, prioridad y última actividad

  • Cada fila muestra el asunto, el estado actual (abierto, pendiente, resuelto o cerrado), la prioridad y la hora de la última actividad.
  • Haz clic en Nuevo ticket para abrir uno y dale un asunto, una prioridad y tu primer mensaje.
  • Las insignias de estado con código de color facilitan revisar la lista en busca de tickets que necesitan tu atención.

El hilo de un ticket

Al abrir un ticket se muestra la conversación completa. Las respuestas se publican en orden y los nuevos mensajes de nuestro equipo aparecen sin recargar la página.

Support ticket thread showing the conversation between the customer and the Authagonal team with a reply box and file attachment control

El hilo de un ticket entre tú y el equipo de Authagonal

  • Los mensajes con hilo entre tú y el equipo de Authagonal se muestran en orden cronológico.
  • Responde en línea y adjunta archivos para compartir registros, capturas de pantalla o configuración.
  • El hilo se actualiza en vivo, así que una respuesta de nuestro equipo aparece en cuanto se envía.
  • Si en su lugar respondes al correo de notificación, tu mensaje se añade al hilo automáticamente.

Cómo te llegan las respuestas

El equipo de Authagonal gestiona los tickets desde el lado de administración. Recibes una notificación por correo electrónico cada vez que el equipo responde, así que no necesitas tener el portal abierto para estar al tanto de una conversación.

Mesa de soporte para tus usuarios

Aparte del soporte que recibes de nosotros, Authagonal puede gestionar una mesa de soporte para tus usuarios finales. Ellos abren tickets desde las páginas de su cuenta en el host con la marca de tu propio inquilino, y tu equipo los responde desde el portal.

Existe porque las personas que no pueden iniciar sesión son justo las que no pueden llegar a una herramienta de soporte que exige iniciar sesión. La mesa está junto a las pantallas de inicio de sesión, así que un usuario bloqueado sigue teniendo una vía, y cada ticket llega ya vinculado a una cuenta real de tu directorio y no a la dirección que alguien haya escrito.

Cómo activarla

Abre Atención al cliente en el portal, cambia a su pestaña Configuración y activa Habilitar atención al cliente. La pestaña está disponible para propietarios y administradores. Tus usuarios no ven nada hasta que lo hagas.

ConfiguraciónQué hace
Habilitar atención al clienteEl interruptor principal. Desactivado, tanto las páginas del usuario final como tu bandeja de entrada de operador quedan ocultas y sus API responden 404.
Permitir solicitudes de visitantes sin sesión iniciadaPermite que un visitante sin sesión iniciada abra un ticket, que es el caso del usuario bloqueado. Está protegido por una comprobación anti-bots, y el intercambio continúa por correo electrónico más un enlace privado, ya que no hay ninguna cuenta con la que iniciar sesión.
Notificaciones por correo electrónicoA quién se envía un correo cuando llega un ticket o responde un usuario: a nadie, a direcciones concretas o a todo tu equipo de soporte (propietarios, administradores y soporte), para que nadie tenga que quedarse vigilando la bandeja de entrada.
Idioma predeterminado del clienteEl idioma que se asume para un usuario cuando aún no conocemos el suyo, para sus tickets y correos. El idioma guardado del propio usuario siempre tiene prioridad y, si no hay nada configurado, es el inglés. Este ajuste está en la pestaña <strong>General</strong> de Configuración.
URL del webhook de soporteUna URL a la que enviar por POST los eventos de tickets, para llevarlos a tus propias herramientas.

No disponible en el plan Gratis

La mesa de soporte es la única capacidad que el plan Gratis no incluye, porque el correo entrante y la traducción tienen un coste real por uso. Todos los planes de pago la incluyen. Las funciones de autenticación nunca se limitan de esta forma: el inicio de sesión único, SCIM, el multifactor, los dominios personalizados, la marca y la auditoría están en todos los planes, incluido el Gratis.

Qué ven tus usuarios

Los usuarios con sesión iniciada tienen un área de soporte en las páginas de su cuenta en el host de tu inquilino, con tu marca. Pueden abrir un ticket, ver todo lo que han abierto y responder en un hilo. Las respuestas de tu equipo también llegan por correo electrónico, así que el usuario no tiene que estar comprobándolo.

Con los tickets anónimos habilitados, alguien que no puede iniciar sesión todavía puede abrir uno. Indica una dirección de correo y su mensaje, y recibe a cambio un enlace privado a la conversación. Ese enlace es la única vía de entrada, así que trátalo como una credencial: es imposible de adivinar, y cualquiera que lo tenga puede leer ese hilo concreto y responder en él.

La bandeja de entrada del operador

Tu equipo responde desde Atención al cliente en el menú lateral del portal. Es un lugar distinto de tus propios tickets con nosotros, y está disponible para el rol tenant:support y superiores, así que puedes dar a un agente acceso a la mesa sin darle el resto del portal.

AcciónQué hace
ResponderPublica en el hilo. Se envía un correo al usuario, que además lo ve en vivo si tiene la página abierta.
AsignarEntrega un ticket a un miembro concreto de tu equipo, para que dos personas no respondan al mismo.
Estado y prioridadMueve un ticket por los estados abierto, pendiente, resuelto y cerrado, y marca lo urgente que es. Los tickets cerrados se eliminan tras un periodo de retención en lugar de guardarse para siempre.
Notas internasNotas visibles solo para tu equipo, nunca para el usuario. Las ediciones y las eliminaciones quedan registradas en el registro de auditoría.
Abrir en nombre de un usuarioInicia un hilo con uno de tus usuarios eligiéndolo de tu directorio, para cuando la conversación empezó en otro sitio.
Escalar a AuthagonalSi resulta que un ticket trata sobre Authagonal y no sobre tu producto, escálalo. Eso abre un ticket enlazado con nuestro equipo, que opcionalmente lleva el hilo hasta ese momento, y enlaza los dos para que puedas seguir ambos. Un ticket solo se puede escalar una vez.

Los usuarios escriben en su propio idioma

Un ticket se almacena en el idioma en que lo escribió el usuario, y cada persona del hilo lo lee en el suyo. Tu agente ve el mensaje traducido al idioma de su portal, el usuario ve tu respuesta traducida al suyo, y el texto original se conserva siempre al lado. El idioma se detecta a partir del primer mensaje y queda fijado al ticket. Las traducciones se calculan una vez por idioma y se reutilizan, así que un hilo largo no se vuelve a traducir entero.

Zonas horarias

Un ticket registra la zona horaria desde la que lo abrió el usuario. Cada mensaje muestra entonces su hora local junto a la tuya, de modo que una respuesta a las 14:32 se lee como las 02:32 que en realidad eran para la persona que la esperaba. No se muestra nada cuando la zona es desconocida, por ejemplo en un ticket que llegó por correo, o cuando coincide con la tuya.

Webhooks

Configura una URL de webhook de soporte para recibir los eventos de tickets en el momento en que ocurren, para lanzar una alerta o replicar los tickets en tu propio sistema. Las cargas van firmadas para que puedas verificar que vienen de nosotros.

EventoQué hace
support.ticket.createdUn usuario abrió un ticket.
support.ticket.messageSe publicó un mensaje en un hilo, ya sea de un usuario o de uno de tus operadores. El campo fromStaff de la carga útil indica cuál de los dos.
support.ticket.status_changedEl estado de un ticket cambió, por ejemplo a resuelto.
support.ticket.assignedSe asignó un ticket a un miembro del equipo.

Importar y migrar

Migra un sistema de identidad existente a tu inquilino de Authagonal. Se admiten dos fuentes — Duende IdentityServer (una base de datos SQL Server) y Auth0 (la Management API). Cada una ejecuta una vista previa de solo lectura para que revises exactamente qué se copiará antes de confirmar.

Importación desde Duende IdentityServer

Migra clientes, ámbitos, usuarios y roles desde una base de datos SQL Server de Duende IdentityServer existente a tu inquilino de Authagonal. La importación se ejecuta en dos fases — vista previa y commit — para que puedas revisar lo que se copiará antes de realizar cualquier cambio.

Qué se importa

El importador lee de la ConfigurationDb de Duende y de las tablas de ASP.NET Identity y escribe las filas mapeadas en tu inquilino. Se omiten artefactos de corta duración como persisted grants, device codes y claves de firma.

EntidadTablas de origenNotas
ClientesClients, ClientSecrets, ClientGrantTypes, ClientScopes, ClientRedirectUrisLos clientes deshabilitados se importan deshabilitados. Los secrets expirados se omiten.
ÁmbitosApiScopes, ApiResources, IdentityResourcesSe conservan las asignaciones de claims de usuario reconocidas.
UsuariosAspNetUsers, AspNetUserClaimsLos hashes de contraseña (ASP.NET Identity V3) se copian tal cual y se rehashan en el primer inicio de sesión.
RolesAspNetRoles, AspNetUserRolesSe preservan las asignaciones de roles.
Inicios de sesión externosAspNetUserLoginsSe guardan como referencia; reconecta los IdP de origen mediante SSO tras la importación.

Vista previa antes del commit

Pega tu cadena de conexión a ConfigurationDb / IdentityDb de Duende y haz clic en Ejecutar vista previa. La vista previa abre una conexión de solo lectura y cuenta cada fila que se importaría. No se escribe nada.

  • Recuentos por entidad de clientes, ámbitos, usuarios, roles y asignaciones de roles.
  • Avisos de colisión cuando el inquilino de destino ya tiene clientes (los ClientIds coincidentes se sobrescriben), roles o ámbitos (los nombres coincidentes se omiten).
  • Avisos de tablas desconocidas y columnas no mapeadas para que sepas qué se descartará.
Import preview panel showing entity counts and warnings before committing the import

Panel de vista previa con recuentos y avisos

Hashes de contraseña

Duende almacena contraseñas con ASP.NET Identity V3 (PBKDF2). El PasswordHasher de Authagonal verifica ese formato directamente y rehashea al formato nativo en el primer inicio de sesión exitoso — los usuarios conservan su contraseña sin flujo de restablecimiento.

Reconciliación de ID de usuario

Si un usuario que ya está en este inquilino tiene el mismo correo que un registro entrante, la importación rota el userId de esa cuenta al sub de origen antes de importar, de modo que los roles, inicios de sesión y reclamaciones importados se vinculan a la cuenta existente y las apps que ya referencian al usuario por su sub de origen siguen resolviéndose tras la migración. La contraseña y el perfil existentes de la cuenta se conservan; los roles de origen se fusionan encima. La vista previa enumera cada cuenta que se reconciliará antes de confirmar.

Ejecutar la importación

Haz clic en Iniciar importación tras revisar la vista previa. La fase de commit escribe clientes, ámbitos, usuarios, roles y referencias de inicio de sesión externo en los stores del inquilino. Los clientes con un clientId coincidente se sobrescriben; las filas con un scope name, email o role name coincidente se omiten, así que el importador es seguro de re-ejecutar.

Qué no se importa

  • Persisted grants, device codes, server-side sessions — de corta duración, se regeneran automáticamente.
  • Claves de firma — Authagonal emite sus propias claves por tenant.
  • Columnas y tablas personalizadas — cualquier cosa fuera del esquema estándar de Duende se emite como aviso para que sepas que los datos se descartaron.
  • Clientes deshabilitados — se importan deshabilitados; reactívalos desde la página Clientes cuando estés listo.

No disponible en sandbox

La importación solo se ejecuta contra el inquilino en vivo. Sal del modo sandbox antes de importar.

Importar desde Auth0

Conecta Authagonal con la Management API de tu inquilino de Auth0 y trae tus aplicaciones, APIs, roles, usuarios y conexiones empresariales. Los IDs de usuario y aplicación importados se conservan, de modo que las referencias existentes a sub y client_id siguen resolviéndose tras el cambio.

Qué necesitarás

Crea una aplicación Machine-to-Machine en Auth0 autorizada para la Management API, con estos ámbitos de lectura: read:users, read:clients, read:resource_servers, read:roles, read:connections, read:client_grants. Pega su dominio, client ID y client secret en el formulario de importación — solo se usan para la importación.

Qué se importa

EntidadTablas de origenNotas
Aplicacionesclients, client-grantsPublic vs. confidential se detecta automáticamente. Los client secrets se rehashan para que sigan funcionando.
APIs y ámbitosresource-serversLas audiences y los ámbitos se asignan a cada cliente a partir de sus concesiones.
Rolesroles + asignacionesSe conservan las asignaciones de roles por usuario.
Usuariosusers + identitiesLos perfiles y metadatos se transfieren; las identidades sociales/empresariales pasan a ser inicios de sesión vinculados.
Conexionesconnections (OIDC)Las conexiones OIDC empresariales se convierten en proveedores federados. Las conexiones SAML, sociales y de base de datos se omiten con una advertencia.

Contraseñas

La Management API de Auth0 nunca devuelve los hashes de contraseña. Si dispones de la exportación masiva de contraseñas asistida por soporte de Auth0 (NDJSON), proporciónala — los hashes bcrypt se importan tal cual y tus usuarios conservan sus contraseñas sin restablecimiento. Ese archivo también incluye el conjunto completo de usuarios, eliminando el límite de 1.000 usuarios del listado de la API de Auth0. Sin él, los usuarios se importan como perfiles y establecen una nueva contraseña en el primer inicio de sesión.

Misma vista previa, rotación y límites

La vista previa, la rotación del owner-userId, el commit re-ejecutable y la restricción de sandbox descritos arriba también se aplican a las importaciones de Auth0.

Referencia de API

Cada inquilino expone un servidor OIDC compatible con estándares en https://{slug}.authagonal.io. Todos los endpoints siguen las especificaciones OAuth 2.0 y OpenID Connect. Esta referencia cubre todos los endpoints con los que tu aplicación puede necesitar interactuar.

OIDC Authorization Code Flow with PKCE: sequence diagram showing the 9-step flow between your app, the browser, and Authagonal

Flujo de código de autorización con PKCE

Descubrimiento OIDC y JWKS

El documento de descubrimiento permite que las bibliotecas de cliente OIDC se configuren automáticamente. No se requiere autenticación para ninguno de los endpoints.

GET /.well-known/openid-configuration

Devuelve el documento de configuración del proveedor OpenID. La respuesta incluye todos los metadatos que tu cliente necesita para interactuar con este inquilino.

CampoDescripción
issuerLa URL del emisor del inquilino
authorization_endpointURL para solicitudes de autorización
token_endpointURL para intercambio de tokens
userinfo_endpointURL para obtener reclamaciones del usuario
jwks_uriURL del JSON Web Key Set
revocation_endpointURL para revocación de tokens
introspection_endpointURL para introspección de tokens
end_session_endpointURL para cierre de sesión / end-session
device_authorization_endpointURL para solicitudes de autorización de dispositivo
pushed_authorization_request_endpointURL del endpoint de Pushed Authorization Request (RFC 9126).
require_pushed_authorization_requestsSi el inquilino exige PAR globalmente. Incluso cuando está en false, los clientes individuales pueden establecer RequirePushedAuthorizationRequests = true.
scopes_supportedLista de alcances soportados
response_types_supportedTipos de respuesta soportados
grant_types_supportedTipos de concesión soportados
code_challenge_methods_supportedMétodos PKCE soportados (S256)
backchannel_logout_supportedSi el cierre de sesión por canal trasero está soportado

GET /.well-known/openid-configuration/jwks

Devuelve el JSON Web Key Set utilizado para verificar las firmas de tokens. La respuesta contiene un array keys de claves públicas EC P-256 (los tokens se firman con ES256), cada una con los campos kty (EC), use, kid, alg, crv, x e y.

Fetch discovery document
curl https://acme.authagonal.io/.well-known/openid-configuration

Endpoint de autorización

GET /connect/authorize

Inicia un flujo de código de autorización. El usuario debe tener una sesión activa o será redirigido a la página de inicio de sesión. En caso de éxito, el usuario es redirigido de vuelta a tu aplicación con un código de autorización.

ParámetroRequeridoDescripción
response_typeSíDebe ser "code"
client_idSíTu identificador de cliente registrado
redirect_uriSíDebe coincidir exactamente con una URI de redirección registrada
scopeSíLista de alcances separados por espacio (por ejemplo, "openid profile email")
stateRecomendadoValor opaco para protección CSRF, devuelto sin cambios en la redirección
code_challengeRequerido si PKCEHash SHA-256 codificado en base64url del code_verifier
code_challenge_methodRequerido si PKCEDebe ser "S256"
nonceOpcionalValor vinculado al token de ID para protección contra reproducción
login_hintOpcionalRellenar previamente el campo de correo electrónico en la página de inicio de sesión

Respuesta exitosa: Redirección 302 a redirect_uri con los parámetros de consulta code y state.

Respuesta de error: Redirección 302 con los parámetros de consulta error, error_description y state.

PKCE requerido

PKCE es requerido por defecto para todos los clientes. Genera un code_verifier (una cadena aleatoria de 43 o más caracteres), hashéalo con SHA-256 y codifica el resultado en base64url para crear el code_challenge.

Pushed Authorization Requests (PAR)

RFC 9126. En lugar de poner cada parámetro de autorización en la URL, tu cliente los envía por POST a /connect/par con autenticación normal y recibe una request_uri opaca y de corta duración. El navegador visita luego /connect/authorize?client_id=...&request_uri=... — nada más queda en el historial del navegador, los logs del servidor ni los encabezados Referer, y el servidor ya ha verificado la integridad de los parámetros bajo autenticación de cliente.

POST /connect/par

La autenticación de cliente es la misma que en /connect/token: HTTP Basic con client_id/client_secret o credenciales codificadas en el formulario. Los clientes públicos publican sin secreto. El cuerpo lleva los mismos parámetros que enviarías normalmente a /connect/authorize; request_uri en sí es rechazado (encadenar un PAR está prohibido por §2.1 de la especificación). Devuelve 201 Created.

ParámetroRequeridoDescripción
client_idSíTu ID de cliente. Debe coincidir con el cliente autenticado.
client_secretClientes confidencialesTu secreto de cliente. Requerido para clientes confidenciales.
response_typeSíDebe ser "code"
redirect_uriSíDebe coincidir exactamente con una URI de redirección registrada
scopeSíLista de alcances separados por espacio (por ejemplo, "openid profile email")
code_challengeRequerido si PKCEHash SHA-256 codificado en base64url del code_verifier
code_challenge_methodRequerido si PKCEDebe ser "S256"
stateRecomendadoValor opaco para protección CSRF, devuelto sin cambios en la redirección
nonceOpcionalValor vinculado al token de ID para protección contra reproducción

Respuesta

CampoDescripción
request_uriReferencia opaca de un solo uso, p. ej. <code>urn:ietf:params:oauth:request_uri:abc123…</code>. Pásala a <code>/connect/authorize</code> como <code>request_uri</code>.
expires_inVida útil de la <code>request_uri</code> en segundos. Por defecto es 90 — valor típico de un IdP de referencia.

En la llamada posterior GET /connect/authorize?client_id=…&request_uri=…, todos los demás parámetros se toman de la carga útil enviada y cualquier parámetro de consulta extra se ignora. El client_id en la llamada de autorización debe coincidir con el cliente que envió la solicitud. Una vez consumida (o cuando transcurre expires_in), la request_uri se elimina del almacén.

Forzar PAR por cliente

Activa Exigir solicitudes de autorización empujadas en un cliente (Portal, Clientes, abre el cliente, pestaña Seguridad) para rechazar las llamadas planas a /connect/authorize. La postura recomendada para clientes de alto riesgo combina RequirePushedAuthorizationRequests = true con PKCE, lo que elimina por completo la barra de direcciones como superficie de ataque.
Push an authorization request and follow up
# 1. Push parameters (server returns request_uri + expires_in)
curl -X POST https://acme.authagonal.io/connect/par \
  -u "my-app:CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "response_type=code" \
  -d "redirect_uri=https://app.example.com/callback" \
  -d "scope=openid profile email" \
  -d "state=$(openssl rand -hex 16)" \
  -d "code_challenge=YOUR_CODE_CHALLENGE" \
  -d "code_challenge_method=S256"

# 2. Send the user to /authorize with only client_id + request_uri
# https://acme.authagonal.io/connect/authorize?client_id=my-app&request_uri=urn:ietf:params:oauth:request_uri:abc123...

Endpoint de token

POST /connect/token

Intercambia credenciales por tokens. Las solicitudes deben usar Content-Type: application/x-www-form-urlencoded. La autenticación del cliente puede proporcionarse a través de HTTP Basic auth (Authorization: Basic base64(client_id:client_secret)) o como parámetros del cuerpo del formulario (client_id + client_secret).

Concesión de código de autorización

ParámetroRequeridoDescripción
grant_typeSí"authorization_code"
codeSíEl código de autorización de la redirección
redirect_uriSíDebe coincidir con la URI utilizada en la solicitud de autorización
code_verifierRequerido si PKCELa cadena aleatoria original utilizada para generar el code_challenge
client_idSíTu identificador de cliente (si no usas autenticación Basic)
client_secretClientes confidencialesTu secreto de cliente (si no usas autenticación Basic)

Concesión de token de actualización

ParámetroRequeridoDescripción
grant_typeSí"refresh_token"
refresh_tokenSíEl token de actualización a intercambiar
client_idSíTu identificador de cliente
client_secretClientes confidencialesTu secreto de cliente

Concesión de credenciales de cliente

ParámetroRequeridoDescripción
grant_typeSí"client_credentials"
client_idSíTu identificador de cliente
client_secretSíTu secreto de cliente
scopeOpcionalAlcances separados por espacio a solicitar

Concesión de código de dispositivo

ParámetroRequeridoDescripción
grant_typeSí"urn:ietf:params:oauth:grant-type:device_code"
device_codeSíEl código de dispositivo de la respuesta de autorización de dispositivo
client_idSíTu identificador de cliente
client_secretClientes confidencialesTu secreto de cliente

Respuesta del token:

CampoDescripción
access_tokenEl token de acceso para llamadas a la API
token_type"Bearer"
expires_inDuración del token en segundos
id_tokenToken de ID de OpenID Connect (cuando se solicita el alcance openid)
refresh_tokenToken de actualización (cuando se otorga el alcance offline_access)
Exchange authorization code with PKCE
curl -X POST https://acme.authagonal.io/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://app.example.com/callback" \
  -d "client_id=my-app" \
  -d "code_verifier=YOUR_CODE_VERIFIER"

Endpoint UserInfo

GET /connect/userinfo

Devuelve reclamaciones sobre el usuario autenticado. Requiere un token de acceso válido con el alcance openid.

CampoTipoDescripción
substringIdentificador único del usuario
emailstringDirección de correo electrónico del usuario
email_verifiedbooleanSi el correo electrónico ha sido verificado
given_namestringNombre
family_namestringApellido
namestringNombre completo para mostrar
phone_numberstringNúmero de teléfono (si se proporcionó). Se entrega con el ámbito <code>phone</code>.
org_idstringLa organización a la que pertenece el usuario. La asigna tu propia aplicación de aprovisionamiento (ver Aplicaciones de aprovisionamiento) o se establece con PUT /api/v1/users/{userId}; Authagonal nunca la deriva. Se publica bajo el scope profile y no aparece cuando el usuario no tiene ninguna.
rolesstring[]Array de roles asignados. Solo se entrega cuando el token incluye el ámbito <code>roles</code>.
groupsobject[]Array de membresías de grupo, cada una con id y name. Solo se entrega cuando el token incluye el ámbito <code>groups</code>.
Fetch user info
curl https://acme.authagonal.io/connect/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"

Introspección de token (RFC 7662)

POST /connect/introspect

Valida un token y devuelve sus metadatos. Requiere credenciales de cliente (autenticación Basic o parámetros del cuerpo del formulario).

ParámetroRequeridoDescripción
tokenSíEl token a inspeccionar
token_type_hintOpcionalPista sobre el tipo de token (por ejemplo, "refresh_token")

Respuesta de token activo:

CampoDescripción
activetrue
subSujeto (ID de usuario)
client_idCliente al que se emitió el token
scopeAlcances otorgados separados por espacio
issEmisor
expTiempo de expiración (marca de tiempo Unix)
iatTiempo de emisión (marca de tiempo Unix)
audAudiencia
token_typeTipo de token (por ejemplo, "Bearer")

Respuesta de token inactivo: { "active": false }

Siempre 200 OK

Según RFC 7662, el endpoint de introspección responde 200 OK para cualquier token, por lo que no puede usarse para enumerar tokens. Un token inválido, expirado o revocado simplemente devuelve active: false. La única excepción es el propio llamante: un cliente que falla la autenticación recibe 401 invalid_client.
Introspect a token
curl -X POST https://acme.authagonal.io/connect/introspect \
  -u "my-app:CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=ACCESS_OR_REFRESH_TOKEN"

Revocación de token (RFC 7009)

POST /connect/revocation

Revoca un token emitido previamente. Requiere credenciales de cliente.

ParámetroRequeridoDescripción
tokenSíEl token a revocar
token_type_hintOpcionalPista sobre el tipo de token (por ejemplo, "refresh_token")

El endpoint siempre devuelve 200 OK, incluso para tokens inválidos o ya revocados, según la especificación RFC 7009.

Tokens de acceso y de actualización

Se pueden revocar tanto los tokens de actualización como los de acceso. Revocar un token de actualización también revoca los tokens de acceso emitidos a partir de él. La introspección y userinfo rechazan un token de acceso revocado, pero un servidor de recursos que valida el JWT localmente lo sigue aceptando hasta que expira, así que mantén cortas las duraciones de los tokens de acceso.

Autorización de dispositivo (RFC 8628)

POST /connect/deviceauthorization

Inicia el flujo de autorización de dispositivo para dispositivos con restricciones de entrada (CLIs, smart TVs, dispositivos IoT). El dispositivo muestra un código al usuario, quien luego aprueba la solicitud en un dispositivo separado con navegador.

ParámetroRequeridoDescripción
client_idSíTu identificador de cliente
client_secretClientes confidencialesTu secreto de cliente
scopeOpcionalAlcances separados por espacio (predeterminado: "openid")

Respuesta:

CampoDescripción
device_codeCódigo de verificación del dispositivo (utilizado para consultas periódicas)
user_codeCódigo visible para el usuario en formato XXXX-XXXX
verification_uriURL que el usuario visita para ingresar el código
verification_uri_completeURL con el user_code pre-completado
expires_in300 por defecto (segundos, así que el código es válido durante 5 minutos). Se configura por cliente.
interval5 (segundos — intervalo mínimo de consulta)

Flujo de aprobación: El usuario visita la verification_uri, ingresa el user_code y aprueba la solicitud. Mientras tanto, el dispositivo consulta periódicamente el endpoint de token con el device_code.

Códigos de error de consulta periódica:

ErrorSignificado
authorization_pendingEl usuario aún no ha aprobado — continuar consultando
expired_tokenEl código de dispositivo ha expirado — reiniciar el flujo
access_deniedEl usuario denegó la solicitud de autorización
Request device authorization
curl -X POST https://acme.authagonal.io/connect/deviceauthorization \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=my-cli" \
  -d "scope=openid profile email"

Cierre de sesión / Logout

GET POST /connect/endsession

Cierra la sesión del usuario actual, notifica a cada cliente que tenga registrada una URI de cierre de sesión por canal trasero o por canal frontal, y revoca las concesiones vinculadas a esa sesión. Sin un id_token_hint que coincida con la sesión actual, primero se pide al usuario que confirme el cierre de sesión.

ParámetroRequeridoDescripción
id_token_hintOpcionalEl token de ID — utilizado para validar el post_logout_redirect_uri
post_logout_redirect_uriOpcionalA dónde redirigir después del cierre de sesión (debe estar registrado)
stateOpcionalValor opaco devuelto en la redirección

Si se proporciona un post_logout_redirect_uri válido que coincida con una URI registrada, el usuario recibe una redirección 302. De lo contrario, una respuesta JSON confirma que la sesión ha sido finalizada.

Cierre de sesión por canal trasero

Cuando un usuario cierra sesión, Authagonal envía un JWT firmado al BackChannelLogoutUri de cada cliente. El JWT contiene sub, aud, iss y la reclamación de evento http://schemas.openid.net/event/backchannel-logout. Tu aplicación debe invalidar la sesión local del usuario cuando reciba esta notificación.

Referencia de API SCIM 2.0

Authagonal soporta el protocolo SCIM 2.0 para el aprovisionamiento automatizado de usuarios y grupos. Los proveedores de identidad como Okta, Azure AD y OneLogin pueden usar esta API para mantener tu inquilino de Authagonal sincronizado con tu directorio corporativo.

URL base: https://{slug}.authagonal.io/scim/v2

Autenticación: Todas las solicitudes requieren un token Bearer. Genera un token SCIM en el portal en la página SCIM: selecciona el cliente para el que aprovisiona tu IdP y luego Crear token.

Encabezados comunes:

EncabezadoValor
AuthorizationBearer SCIM_TOKEN
Content-Typeapplication/scim+json

Los endpoints de lista aceptan count (100 por defecto, máx. 200; 0 devuelve solo el total) y filtrado a través del parámetro filter (por ejemplo, userName eq "[email protected]"). Los usuarios se paginan con cursor: pasa el nextCursor de la respuesta anterior. Los grupos aceptan startIndex (basado en 1) o cursor.

Usuarios

GET /scim/v2/Users: Lista usuarios con paginación y filtrado opcionales.

Parámetro de consultaDescripción
startIndexPara Users solo se acepta 1; usa cursor para paginar. Un valor mayor devuelve 400 invalidValue.
cursorCursor de paginación opaco: pasa el nextCursor de la página anterior para obtener la siguiente página
countNúmero máximo de resultados por página (predeterminado: 100, máx.: 200; 0 devuelve solo el total)
filterExpresión de filtro SCIM (por ejemplo, userName eq "[email protected]")

GET /scim/v2/Users/{id}: Obtiene un usuario individual por su ID de usuario de Authagonal.

POST /scim/v2/Users: Crea un nuevo usuario. Devuelve 201 Created.

CampoRequeridoDescripción
userNameSíDirección de correo electrónico (debe ser única dentro del inquilino)
name.givenNameNoNombre
name.familyNameNoApellido
displayNameNoNombre completo para mostrar
activeNoSi el usuario está activo (predeterminado: true)
externalIdNoIdentificador del proveedor de identidad ascendente

PUT /scim/v2/Users/{id}: Reemplazo completo de un recurso de usuario. Todos los campos deben proporcionarse.

PATCH /scim/v2/Users/{id}: Actualización parcial usando SCIM PatchOp.

OperaciónRutas soportadasValor de ejemplo
replaceuserName, active, name.givenName, name.familyName, displayName, externalId, preferredLanguagetrue / false, o un valor de cadena
adduserName, active, name.givenName, name.familyName, displayName, externalId, preferredLanguagetrue / false, o un valor de cadena
removename.givenName, name.familyName, displayName, externalId, preferredLanguage(no se necesita valor)

DELETE /scim/v2/Users/{id}: Eliminación suave del usuario (desactiva la cuenta y revoca todos los tokens). Devuelve 204 No Content.

Create a user via SCIM
curl -X POST https://acme.authagonal.io/scim/v2/Users \
  -H "Authorization: Bearer SCIM_TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "[email protected]",
    "name": {
      "givenName": "Jane",
      "familyName": "Smith"
    },
    "displayName": "Jane Smith",
    "active": true,
    "externalId": "ext-12345"
  }'

Grupos

GET /scim/v2/Groups: Lista todos los grupos con paginación y filtrado opcionales.

GET /scim/v2/Groups/{id}: Obtiene un grupo individual por ID, incluyendo su lista de miembros.

POST /scim/v2/Groups: Crea un nuevo grupo. Devuelve 201 Created.

CampoRequeridoDescripción
displayNameSíNombre para mostrar del grupo
membersNoArray de objetos de miembros, cada uno con un campo value que contiene el ID de usuario
externalIdNoIdentificador del proveedor de identidad ascendente

PUT /scim/v2/Groups/{id}: Reemplazo completo de un recurso de grupo (incluyendo su lista de miembros).

PATCH /scim/v2/Groups/{id}: Actualización parcial: añadir, eliminar o reemplazar miembros, o cambiar displayName y externalId.

DELETE /scim/v2/Groups/{id}: Eliminación permanente del grupo. Devuelve 204 No Content.

Add members to a group via PATCH
curl -X PATCH https://acme.authagonal.io/scim/v2/Groups/GROUP_ID \
  -H "Authorization: Bearer SCIM_TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
      {
        "op": "add",
        "path": "members",
        "value": [
          { "value": "USER_ID_1" },
          { "value": "USER_ID_2" }
        ]
      }
    ]
  }'

Respuestas de error SCIM

Cuando una solicitud SCIM falla, el cuerpo de la respuesta sigue el esquema de error SCIM: { "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "400", "detail": "..." }. Los códigos de estado comunes incluyen 400 (solicitud incorrecta), 404 (recurso no encontrado), 409 (conflicto / duplicado) y 429 (límite de velocidad alcanzado).

API del portal (automatización)

La API del portal permite que tu propio backend automatice todo lo que puedes hacer en el portal — gestionar usuarios, clientes, grupos, roles, ámbitos, conexiones SSO y configuración — usando una credencial de máquina a máquina. Es la misma API que llama la interfaz del portal.

URL base: https://portal-api.<your-domain>/api/v1. Las solicitudes se autentican con un token de acceso Bearer; el inquilino se toma del token, no de la URL.

Crear una credencial de API

En el portal, abre Clients → Create API credential, elige un nivel de acceso y dale un nombre. Authagonal genera un cliente OAuth client_credentials configurado para la API del portal y devuelve un ID de cliente y un secreto.

Copia el secreto de inmediato

El secreto de cliente se muestra solo una vez, justo después de la creación. Guárdalo en tu gestor de secretos antes de cerrar el diálogo — si lo pierdes, elimina la credencial y crea una nueva.

Niveles de acceso

ÁmbitoConcede
tenant:ownerAcceso completo, incluidas las acciones destructivas exclusivas del propietario, como eliminar el inquilino completo.
tenant:adminGestionar todo excepto las acciones exclusivas del propietario — usuarios, clientes, SSO, grupos, roles, marca y configuración.
tenant:developerGestionar clientes, ámbitos, marca y aplicaciones de aprovisionamiento.
tenant:supportLeer y gestionar usuarios para tareas de soporte, y leer el registro de auditoría.

Solo puedes conceder lo que tú posees

Una credencial no puede tener más privilegios que la persona que la crea. Un administrador no puede generar una credencial con ámbito de propietario, y el ámbito administrativo de la plataforma nunca puede concederse a una credencial.

Obtener un token

Intercambia la credencial por un token de acceso en el endpoint de token de tu inquilino de administración — https://<your-tenant>.<your-domain>/connect/token — y luego envía el token como un encabezado Bearer a la API del portal. Los tokens son válidos durante una hora.

Obtén un token y luego llama a la API
# 1. Exchange the credential for an access token (your tenant's token endpoint)
curl -X POST https://acme.authagonal.io/connect/token \
  -d grant_type=client_credentials \
  -d client_id=api-3f2a... \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d scope=tenant:admin

# Response: { "access_token": "ey...", "token_type": "Bearer", "expires_in": 3600 }

# 2. Call the Portal API with the access token
curl https://portal-api.authagonal.io/api/v1/users \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Endpoints

Todas las rutas son relativas a la URL base y requieren un token de acceso Bearer. El ámbito junto a cada grupo es el nivel de acceso mínimo que necesitan las credenciales. La paginación depende del recurso: los usuarios y el registro de auditoría aceptan count (de 1 a 200, 50 por defecto) y after, con el valor de continuationToken de la respuesta anterior; los grupos aceptan startIndex y count; las organizaciones aceptan limit y cursor; los clientes, los roles y los ámbitos devuelven todas las filas.

Clientestenant:developer

GET/api/v1/clientsListar clientes OAuth.

GET/api/v1/clients/{id}Obtener un cliente por su ID.

POST/api/v1/clientsCrear un cliente. Devuelve 201 con el registro del cliente. Los secretos no se devuelven aquí: genera uno con POST /api/v1/clients/{clientId}/secrets, que lo muestra una sola vez.

PUT/api/v1/clients/{id}Actualizar un cliente (URIs de redirección, tipos de concesión, duración de tokens, requisitos PKCE/PAR).

DELETE/api/v1/clients/{id}Eliminar un cliente.

POST/api/v1/clients/api-credentialGenerar una credencial de API del Portal de máquina a máquina.

Usuariostenant:support

GET/api/v1/usersListar usuarios. Admite count, search (prefijo de correo o nombre), organizationId para filtrar por una organización y after para paginación por cursor.

GET/api/v1/users/countNúmero total de usuarios del inquilino.

GET/api/v1/users/stats/mfaEstadísticas de inscripción en MFA.

GET/api/v1/users/{id}Obtener un usuario.

POST/api/v1/users/inviteInvitar a un usuario por correo electrónico. Crea una cuenta pendiente y envía por correo un enlace donde el invitado establece su propia contraseña. Los campos opcionales organizationId y organizationRoles también añaden una membresía de organización.

PUT/api/v1/users/{id}Actualizar un usuario (perfil, correo, isActive, emailConfirmed, organizationId). Cambiar el correo o emailConfirmed requiere tenant:admin.

DELETE/api/v1/users/{id}Eliminar un usuario.

GET/api/v1/users/{id}/mfaGet a user's enrolled MFA methods.

DELETE/api/v1/users/{id}/mfaReset a user's MFA enrollment. Needs tenant:admin.

Rolestenant:admin

GET/api/v1/rolesListar roles.

POST/api/v1/rolesCrear un rol.

DELETE/api/v1/roles/{id}Eliminar un rol.

POST/api/v1/roles/assignAsignar un rol a un usuario.

POST/api/v1/roles/unassignQuitar un rol de un usuario.

Grupostenant:admin

GET/api/v1/groupsListar grupos.

GET/api/v1/groups/{id}Obtener un grupo con sus miembros.

POST/api/v1/groupsCrear un grupo.

POST/api/v1/groups/{id}/membersAgregar miembros a un grupo.

DELETE/api/v1/groups/{groupId}/members/{userId}Eliminar un miembro de un grupo.

DELETE/api/v1/groups/{id}Eliminar un grupo.

GET/api/v1/group-role-mappingsListar las asignaciones de grupo a rol (roles concedidos al emitir el token según la pertenencia al grupo).

Ámbitostenant:developer

GET/api/v1/scopesListar ámbitos de API.

POST/api/v1/scopesCrear un ámbito.

DELETE/api/v1/scopes/{name}Eliminar un ámbito.

Conexiones SSOtenant:admin

GET/api/v1/saml/connectionsListar conexiones SAML.

POST/api/v1/saml/connectionsCrear una conexión SAML.

DELETE/api/v1/saml/connections/{id}Eliminar una conexión SAML.

GET/api/v1/oidc/connectionsListar conexiones OIDC.

POST/api/v1/oidc/connectionsCrear una conexión OIDC.

DELETE/api/v1/oidc/connections/{id}Eliminar una conexión OIDC.

GET/api/v1/sso/domainsListar los dominios enrutados a conexiones SSO (descubrimiento de dominio de origen).

Personalizacióntenant:developer

GET/api/v1/brandingObtener la personalización del inquilino (colores, logotipo, idiomas admitidos).

PUT/api/v1/brandingActualizar la personalización del inquilino.

Configuracióntenant:admin

GET/api/v1/settingsObtener la configuración del inquilino (webhooks, registro público, política de tokens).

PUT/api/v1/settingsActualizar la configuración del inquilino.

POST/api/v1/settings/webhook-secret/regenerateRotar el secreto de firma del webhook.

POST/api/v1/settings/test-emailEnviar un correo de prueba con la configuración de correo actual.

Dominios personalizados y correotenant:admin

GET/api/v1/custom-domainsListar los dominios de inicio de sesión personalizados y su estado de verificación.

POST/api/v1/custom-domainsAgregar un dominio personalizado.

POST/api/v1/custom-domains/{domain}/verifyIniciar la verificación DNS de un dominio personalizado.

DELETE/api/v1/custom-domains/{domain}Eliminar un dominio personalizado.

GET/api/v1/email/domains/{domainId}Obtener los registros DNS y el estado de verificación de un dominio de correo del remitente.

Registro de auditoríatenant:support

GET/api/v1/auditConsultar el registro de auditoría del inquilino.

Aprovisionamiento de usuarios mediante SCIM

Para el aprovisionamiento masivo de usuarios y grupos desde un IdP (Entra, Okta), use la API SCIM 2.0 en lugar de estos endpoints.

Ejemplo: invitar a un usuario

POST /api/v1/users/invite
curl -X POST https://portal-api.authagonal.io/api/v1/users/invite \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "firstName": "Ada",
    "lastName": "Lovelace"
  }'

# 200 OK
# { "userId": "8f3a...", "email": "[email protected]" }

Todo lo que la interfaz puede hacer

La API del portal expone los mismos endpoints que usa la interfaz del portal, por lo que cualquier operación que puedas realizar en el portal se puede automatizar — según el nivel de acceso de la credencial.

API de organizaciones

Todas las rutas siguientes requieren la política TenantAdmin y están bajo /api/v1/organizations salvo que se indique lo contrario. Consulta la API del portal para saber cómo obtener una credencial. Las dos rutas de listado se paginan por cursor: pasa limit (50 por defecto, de 1 a 200) y el nextCursor anterior como cursor; responden { items, nextCursor }, y un cursor incorrecto produce 400 invalid_cursor. El objeto de organización incluye una lista domains de solo lectura.

MétodoRutaCuerpoNotas
GET/api/v1/organizations–Una página de organizaciones en orden de id. Consulta: cursor?, limit? (50 por defecto, de 1 a 200). Devuelve { items, nextCursor }; un nextCursor nulo indica la última página.
POST/api/v1/organizationsslug, name, brandingJson?, enabled?, requireMembershipForTokens?, allowAutoMembership?, metadata?201 + la organización. 409 slug_taken.
GET/api/v1/organizations/{idOrSlug}–Se busca primero por id y después por slug.
PUT/api/v1/organizations/{id}name?, brandingJson?, slug?, enabled?, requireMembershipForTokens?, allowAutoMembership?, metadata?Solo cambian los campos indicados. Un slug distinto se rechaza: es inmutable una vez creado. Aquí no se pueden cambiar los domains.
DELETE/api/v1/organizations/{id}–Primero elimina todas las membresías de la organización y después la propia organización.
GET/api/v1/organizations/{id}/members–Una página de membresías en orden de id de usuario, con el correo y el nombre actuales del miembro resueltos desde el almacén de usuarios. Consulta: cursor?, limit?.
POST/api/v1/organizations/{id}/membersuserId? | email?, status?, roles?201 + la membresía. 404 user_not_found. 409 membership_exists. Los roles reservados tenant:* y platform:* se rechazan con 400 invalid_role, no se eliminan en silencio.
PUT/api/v1/organizations/{id}/members/{userId}status?, roles?Establecer status en active asigna joinedAt si aún no estaba establecido.
DELETE/api/v1/organizations/{id}/members/{userId}–Elimina la fila por completo, no es un cambio de estado.
POST/api/v1/organizations/{id}/domainsdomainReclama un dominio de correo, sin verificar. 201 + { domain, verified, verifiedAt, createdAt, recordName, recordValue }. 400 domain_invalid. 409 domain_exists, domain_taken.
POST/api/v1/organizations/{id}/domains/{domain}/verify–Busca el registro TXT en recordName y compara recordValue de forma exacta. 200 + el dominio cuando está verificado (una repetición es un 200 sin efecto); 409 verification_failed si no coincide; 409 domain_taken; 404 domain_not_found.
DELETE/api/v1/organizations/{id}/domains/{domain}–204. Elimina la reclamación, verificada o no. Los miembros existentes se conservan. 404 domain_not_found.
POST/api/v1/organizations/backfilldryRun? = trueMigra la etiqueta heredada AuthUser.organizationId a filas reales de Organization/OrganizationMembership.
GET/api/v1/users/{userId}/organizations–Todas las organizaciones a las que pertenece este usuario, con su estado y roles en cada una.

Pantallas de inicio de sesión

Estas son las pantallas alojadas que tus usuarios finales ven en el servidor de autenticación de tu inquilino. Authagonal incluye todas las pantallas listas para usar, así que obtienes una experiencia de inicio de sesión completa y segura sin construir ninguna interfaz. Esta página recorre cada pantalla y muestra qué ajustes del portal la controlan.

Marca blanca completa

Todas las pantallas aquí se pintan con los ajustes de Marca de tu inquilino: tu logotipo, color, nombre de aplicación y CSS personalizado. Las pantallas también respetan prefers-color-scheme, por lo que cambian entre claro y oscuro para coincidir con el dispositivo del usuario.

Inicio de sesión

Hosted sign-in screen with an email field, Continue button, single sign-on provider buttons, and forgot-password and create-account links
  • Flujo de dos pasos, con el correo primero: el usuario introduce su correo y hace clic en Continuar, y entonces aparece el campo de contraseña.
  • Los botones de inicio de sesión único «Continuar con {provider}» aparecen automáticamente cuando existen conexiones SSO.
  • Enlaces de olvidé mi contraseña y crear cuenta, cada uno de los cuales se puede mostrar u ocultar.
  • Captcha opcional de Cloudflare Turnstile para disuadir intentos de inicio de sesión automatizados.

Controlado en la administración del portal

  • Marca define el logotipo, el color, el nombre de la aplicación, el correo de soporte y el CSS personalizado.
  • Muestra u oculta los enlaces de olvidé mi contraseña y registro (Marca).
  • Las conexiones SSO añaden los botones de inicio de sesión social (página SSO).
  • Duración de la sesión y umbrales de bloqueo (Configuración → Sesión).

Registro

Account registration screen with first and last name fields, email, password, and a live password-policy checklist
  • Recopila nombre y apellido (opcional), correo electrónico y una contraseña.
  • Una lista de verificación de la política de contraseñas en vivo se actualiza a medida que el usuario escribe, así los requisitos quedan claros antes de enviar.
  • Captcha opcional de Cloudflare Turnstile.
  • Un enlace de «Iniciar sesión» para usuarios que ya tienen una cuenta.

Controlado en la administración del portal

  • Muestra u oculta el enlace de registro (Marca). Para desactivar el registro por completo, desactiva Permitir registro público (Configuración → Sesión).
  • La política de contraseñas de tu inquilino controla la lista de verificación.
  • Marca da estilo a toda la pantalla.

Olvidé mi contraseña

Forgot-password screen with an email field and a neutral check-your-email confirmation state
  • El usuario introduce su correo y luego ve una confirmación neutral de «revisa tu correo».
  • La pantalla nunca revela si una cuenta existe, lo que frustra los sondeos de enumeración de cuentas.
  • Un enlace de «Volver al inicio de sesión» devuelve al usuario a la pantalla de inicio de sesión.

Controlado en la administración del portal

  • Muestra u oculta el enlace de olvidé mi contraseña (Marca).
  • La entrega de correo de tu inquilino envía el mensaje de restablecimiento.
  • Marca da estilo a toda la pantalla.

Restablecer contraseña

Reset-password screen with new and confirm password fields and a live per-rule requirement checklist
  • Campos de nueva contraseña y confirmar contraseña con una lista de verificación de requisitos por regla en vivo.
  • Un estado claro de enlace no válido o caducado cuando el token de restablecimiento ya no es válido.
  • Un estado de éxito que confirma que la contraseña se ha cambiado.

Controlado en la administración del portal

  • La política de contraseñas de tu inquilino controla la lista de verificación.
  • Marca da estilo a toda la pantalla.

Desafío MFA

MFA challenge screen with a method switcher, a six-digit authenticator code field, recovery-code entry, and a passkey button
  • Un selector de método entre aplicación autenticadora, passkey y código de recuperación.
  • Un campo TOTP de 6 dígitos que se envía automáticamente una vez introducidos todos los dígitos.
  • Entrada de código de recuperación para usuarios que han perdido el acceso a su autenticador.
  • Un botón de passkey para verificación respaldada por hardware.

Controlado en la administración del portal

  • La política de MFA se configura por aplicación (Clientes → Seguridad).
  • A cualquier usuario con un factor registrado siempre se le exige el desafío, independientemente de la política.

Configuración de MFA

MFA setup screen showing enrolled-method status, authenticator QR code and manual key, passkey enrolment, and recovery-code generation
  • Muestra el estado de los métodos registrados para que el usuario sepa qué ya está configurado.
  • Configuración del autenticador mediante código QR, una clave manual de respaldo y un paso de confirmación.
  • Registro de passkey para autenticación respaldada por hardware.
  • Generación de códigos de recuperación para recuperar la cuenta.
  • Una opción de omitir cuando el MFA es de autoservicio en lugar de obligatorio.

Controlado en la administración del portal

  • La política de MFA se configura por aplicación; Obligatorio fuerza la configuración al iniciar sesión (Clientes → Seguridad).
  • Marca da estilo a toda la pantalla.

Autorización de dispositivo

Device authorization screen with a centered user-code entry field, an Approve button, and an approved confirmation state
  • Un campo centrado de entrada del código de usuario para el código mostrado en el dispositivo.
  • Un paso de aprobación para autorizar el dispositivo.
  • Un interstitial de inicio de sesión cuando el usuario aún no está autenticado.
  • Una confirmación de aprobación una vez que el dispositivo está autorizado.

Controlado en la administración del portal

  • Habilita la concesión de código de dispositivo en la aplicación (Clientes → Scopes & Grants).
  • Establece la duración del código de dispositivo (Clientes → Tokens).
Consent screen showing the requesting application's logo and name, a per-scope permission list, and Allow and Deny buttons
  • Muestra el logotipo y nombre del cliente que hace la solicitud.
  • Una lista por scope con etiquetas claras y legibles para cada permiso.
  • Botones de Permitir y Denegar para conceder o rechazar el acceso.
  • Un pie con una nota de consentimiento que explica lo que significa la decisión.

Controlado en la administración del portal

  • Activa Requerir consentimiento por aplicación (Clientes → General).
  • El logotipo, el nombre y la URL provienen de los propios metadatos de la aplicación.
  • Marca pinta la tarjeta de consentimiento.

Aplicaciones conectadas (concesiones)

Connected apps screen listing the applications a user has authorized with their scopes and granted date, plus a revoke control
  • Lista todas las apps que el usuario ha autorizado, con su nombre, ámbitos y fecha de concesión.
  • Revoca el acceso a una app, con un paso de confirmación antes de que surta efecto.
  • Un estado vacío amigable cuando el usuario no ha autorizado ninguna app.

Controlado en la administración del portal

  • La lista se llena con las aplicaciones que requieren consentimiento.
  • Marca da estilo a toda la pantalla.

Cuenta

Una página de cuenta de autoservicio alojada en /login/account donde los usuarios que han iniciado sesión gestionan su propio perfil e idioma preferido, sin necesidad de acceso al portal.

Self-service account screen with editable profile fields and a preferred Language selector
  • Editar nombre y apellidos, empresa y teléfono; la dirección de correo se muestra en solo lectura.
  • Elegir un idioma preferido entre los idiomas soportados; la interfaz previsualiza la elección al instante y la conserva al guardar.
  • El idioma guardado controla la interfaz alojada del usuario y el idioma de los correos transaccionales que recibe.

Controlado en la administración del portal

  • Branding da estilo a toda la pantalla.
  • El mismo idioma preferido puede ser editado por un administrador en la página de Usuarios del portal.

Flujos de autenticación

Los flujos de autenticación cubren cómo los usuarios finales interactúan con tu inquilino de Authagonal — iniciar sesión, registrarse, restablecer contraseñas y configurar MFA. Estos endpoints son utilizados por la página de inicio de sesión alojada y pueden llamarse directamente si estás construyendo una interfaz de inicio de sesión personalizada.

Inicio de sesión

POST /api/auth/login

Autentica a un usuario con correo electrónico y contraseña. En caso de éxito, firma una cookie de sesión y devuelve el perfil del usuario. Si MFA está configurado, la respuesta indica que se requiere un segundo factor antes de que la sesión esté completamente establecida.

Cuerpo de la solicitud:

Login request
{
  "email": "[email protected]",
  "password": "correct-horse-battery-staple"
}

Respuesta exitosa:

CampoTipoDescripción
userIdstringIdentificador único del usuario
emailstringDirección de correo electrónico del usuario
namestringNombre completo para mostrar
mfaAvailablebooleanSi el usuario tiene métodos MFA inscritos

Respuesta de MFA requerido: Cuando el usuario tiene MFA inscrito, la respuesta incluye mfaRequired: true junto con un challengeId y un array methods que lista los métodos MFA disponibles.

Respuesta de configuración de MFA requerida: Cuando la política de MFA de la aplicación es "Obligatorio" pero el usuario aún no se ha inscrito, la respuesta incluye mfaSetupRequired: true con un setupToken para el flujo de inscripción.

Respuestas de error:

Código de errorEstado HTTPDescripción
invalid_credentials401El correo electrónico o la contraseña son incorrectos
account_disabled403La cuenta ha sido desactivada por un administrador
email_not_confirmed403El usuario no ha verificado su dirección de correo electrónico
locked_out423La cuenta está temporalmente bloqueada (incluye retryAfter en segundos). Solo se devuelve cuando la contraseña es correcta; una contraseña incorrecta mientras la cuenta está bloqueada devuelve invalid_credentials
sso_required409El dominio de correo electrónico tiene SSO configurado (incluye redirectUrl)
too_many_attempts429Demasiados intentos de inicio de sesión desde esta IP o para este correo electrónico; inténtalo de nuevo más tarde
captcha_failed400El desafío de Turnstile falló o falta (solo cuando Turnstile está habilitado)

Verificación SSO: Si el dominio de correo electrónico del usuario tiene una conexión SSO configurada, el endpoint de inicio de sesión devuelve sso_required con un redirectUrl. El cliente debe redirigir al usuario al proveedor SSO.

Bloqueo de cuenta: Después de maxFailedAttempts intentos consecutivos de inicio de sesión fallidos, la cuenta se bloquea durante lockoutDurationMinutes. Ambos valores son configurables en la configuración del inquilino.

Página de inicio de sesión alojada

El endpoint de inicio de sesión normalmente es llamado por la página de inicio de sesión alojada, no directamente por tu aplicación. Usa el flujo de código de autorización OIDC para iniciar la autenticación — tus usuarios serán redirigidos a la página de inicio de sesión alojada automáticamente.

Registro

POST /api/auth/register

Crea una nueva cuenta de usuario y envía un correo electrónico de verificación. Mientras <strong>Exigir verificación del correo para iniciar sesión</strong> (Configuración &rarr; Sesión) esté activado, que es lo predeterminado, el usuario debe verificar su correo electrónico antes de poder iniciar sesión.

Cuerpo de la solicitud:

Registration request
{
  "email": "[email protected]",
  "password": "a-strong-password-here",
  "firstName": "Jane",
  "lastName": "Smith"
}
CampoRequeridoDescripción
emailSíDirección de correo electrónico (debe ser única)
passwordSíDebe cumplir con la política de contraseñas del inquilino
firstNameNoNombre
lastNameNoApellido

Éxito: 201 Created con el userId de la nueva cuenta. Registrarse con un correo que ya existe también devuelve 201: nunca revelamos si un correo está registrado (para evitar la enumeración de cuentas) y, en su lugar, avisamos por correo al titular real de la cuenta.

Respuestas de error:

Código de errorEstado HTTPDescripción
weak_password400La contraseña no cumple con la política de contraseñas del inquilino
rate_limited429Demasiados intentos de registro
provisioning_rejected422Un webhook de aprovisionamiento rechazó el registro
invalid_email400La dirección de correo electrónico no es válida
captcha_failed400El desafío de Turnstile falló o falta (solo cuando Turnstile está habilitado)
public_signup_disabled403El registro público está desactivado para este inquilino (Configuración &rarr; Sesión)

Política de contraseñas

Verifica los requisitos de contraseña del inquilino antes de enviar a través de GET /api/auth/password-policy. Esto devuelve una lista rules: la longitud mínima y las clases de caracteres requeridas.

Restablecimiento de contraseña

POST /api/auth/forgot-password

Solicita un correo electrónico de restablecimiento de contraseña. El endpoint siempre devuelve una respuesta exitosa independientemente de si el correo electrónico existe, para prevenir la enumeración de correos electrónicos.

Forgot password request
{
  "email": "[email protected]"
}

POST /api/auth/reset-password

Restablece la contraseña del usuario usando el token del enlace del correo electrónico.

Reset password request
{
  "token": "RESET_TOKEN_FROM_EMAIL",
  "newPassword": "new-strong-password"
}

Efectos secundarios de un restablecimiento de contraseña exitoso:

  • El contador de intentos de inicio de sesión fallidos se reinicia a cero
  • Todos los tokens de actualización existentes son revocados
  • Se genera un nuevo sello de seguridad (invalidando todas las sesiones existentes)

Configuración y verificación de MFA

Authagonal soporta tres métodos MFA: TOTP (aplicaciones autenticadoras), WebAuthn (llaves de seguridad y biometría) y códigos de recuperación de un solo uso.

Configuración TOTP

POST /api/auth/mfa/totp/setup: Devuelve un <code>setupToken</code>, un URI de datos de código QR y una clave de entrada manual. El usuario escanea el código QR con su aplicación autenticadora (Google Authenticator, Authy, 1Password, etc.) y luego confirma la inscripción.

POST /api/auth/mfa/totp/confirm: Confirma la inscripción TOTP enviando el <code>setupToken</code> de la configuración junto con un código de 6 dígitos de la aplicación autenticadora.

Confirm TOTP enrollment
{
  "setupToken": "SETUP_TOKEN_FROM_SETUP_RESPONSE",
  "code": "123456"
}

Configuración WebAuthn

POST /api/auth/mfa/webauthn/setup — Devuelve opciones de creación de credenciales para la API WebAuthn. El navegador llama a navigator.credentials.create() con estas opciones.

POST /api/auth/mfa/webauthn/confirm: Confirma la inscripción WebAuthn enviando la respuesta de atestación del navegador.

Códigos de recuperación

POST /api/auth/mfa/recovery/generate: Genera 10 códigos de recuperación de un solo uso de 10 caracteres (formato <code>XXXXX-XXXXX</code>). Cada código puede usarse exactamente una vez para omitir MFA. Antes debe estar inscrita una aplicación autenticadora o una passkey.

Los códigos de recuperación se muestran solo una vez

Los códigos de recuperación se muestran solo en el momento de la generación y no se pueden recuperar después. Si un usuario pierde tanto su dispositivo autenticador como sus códigos de recuperación, un administrador debe eliminar manualmente su credencial MFA del portal antes de que pueda iniciar sesión nuevamente.

Verificación MFA

POST /api/auth/mfa/verify: Completa el desafío MFA después de un inicio de sesión exitoso con contraseña.

CampoRequeridoDescripción
challengeIdSíEl ID del desafío de la respuesta de inicio de sesión
methodSí"totp", "recovery" o "webauthn"
codeTOTP / RecuperaciónCódigo TOTP de 6 dígitos o código de recuperación (XXXXX-XXXXX)
assertionWebAuthnLa respuesta de aserción de navigator.credentials.get()

Estado de MFA

GET /api/auth/mfa/status: Devuelve los métodos MFA actualmente inscritos del usuario.

Flujo de inicio de sesión SSO

Authagonal soporta tanto conexiones SSO basadas en SAML 2.0 como en OIDC. El enrutamiento basado en dominio detecta automáticamente qué proveedor SSO usar según la dirección de correo electrónico del usuario.

Verificación SSO

GET /api/auth/[email protected]

CampoTipoDescripción
ssoRequiredbooleanSi el dominio de correo electrónico requiere SSO
providerTypestring"saml" o "oidc"
connectionIdstringEl identificador de la conexión SSO
redirectUrlstringLa URL a la que redirigir al usuario para el inicio de sesión SSO

Flujo SAML

El usuario es redirigido a GET /saml/{connectionId}/login que envía una AuthnRequest SAML al proveedor de identidad. El IdP autentica al usuario y publica una respuesta SAML de vuelta al endpoint del Assertion Consumer Service (ACS). Authagonal valida la aserción, crea o actualiza al usuario y firma una cookie de sesión.

Los metadatos SAML para configurar tu IdP están disponibles en GET /saml/{connectionId}/metadata.

Flujo OIDC

El usuario es redirigido a GET /oidc/{connectionId}/login que redirige al proveedor de identidad ascendente con PKCE. Después de que el usuario se autentica, el callback en /oidc/callback intercambia el código de autorización, valida el token de ID y crea o actualiza al usuario.

Aprovisionamiento JIT: Tanto los flujos SAML como OIDC soportan aprovisionamiento just-in-time, que está desactivado por defecto en cada conexión (Activar aprovisionamiento JIT). Cuando está activado y el usuario no existe ya en el inquilino, se crea automáticamente a partir de las reclamaciones del proveedor de identidad. Si ya existe, sus atributos de perfil se actualizan para coincidir con los valores más recientes del proveedor.

Enrutamiento basado en dominio

El enrutamiento basado en dominio significa que tus usuarios no necesitan saber qué proveedor SSO utilizan. Ingresar su dirección de correo electrónico es suficiente — Authagonal hace coincidir el dominio con la conexión SSO correcta y redirige automáticamente.

Backend-for-Frontend (BFF)

Un BFF mantiene los tokens de OAuth completamente fuera del navegador. Tu aplicación de página única no guarda más que una cookie de sesión httpOnly, y un cliente confidencial en tu propio backend ejecuta el flujo de OpenID Connect y guarda los tokens en el servidor.

Todo lo que una aplicación de página única puede leer, el cross-site scripting lo puede robar, y eso incluye un token de acceso en memoria y un token de actualización en localStorage. Guardar tokens en el navegador también limita su duración, porque un token de actualización de larga vida al alcance de los scripts es un riesgo permanente. La mejor práctica actual del IETF OAuth 2.0 for Browser-Based Apps recomienda este patrón exactamente por esa razón.

A cambio obtienes una sesión que sobrevive a una recarga de página sin un solo token a la vista, la renovación resuelta por ti en el servidor, revocación inmediata mediante el cierre de sesión back-channel, y un proxy autenticado para que tu API nunca tenga que analizar un token que el navegador podría haber manipulado.

Crear el cliente

En el portal, abre Clientes y elige Crear app BFF. Indica la URL base desde la que se sirve tu aplicación, por ejemplo https://app.acme.com, y Authagonal registra por ti un cliente confidencial correctamente configurado en lugar de dejarte armarlo a mano:

ConfiguraciónValor
URI de redirección{appBaseUrl}/bff/callback
URI de redirección tras el cierre de sesión{appBaseUrl}/
URI de cierre de sesión back-channel{appBaseUrl}/bff/backchannel-logout
Tipos de concesiónauthorization_code, refresh_token
Ámbitosopenid, profile, email, offline_access
PKCE y secreto de clienteAmbos obligatorios

El secreto se muestra una sola vez

La respuesta trae clientId, clientSecret y authority, y después el secreto ya no se puede recuperar porque solo se almacena su hash. Guárdalo directamente en la configuración o en el almacén de secretos de tu backend. Si lo pierdes, crea otro cliente en lugar de intentar recuperar este.

Conéctalo a tu backend

Hay dos entornos de ejecución compatibles que comparten el mismo protocolo central: Authagonal.Bff para .NET y @authagonal/bff para Node, este último con adaptadores para Express y Next.js. Apunta cualquiera de los dos a los valores que el portal acaba de darte. El paquete de Node también necesita un cookieSecret propio, que usa para cifrar sus cookies.

.NET
// dotnet add package Authagonal.Bff
builder.Services.AddAuthagonalBff(o =>
{
    o.Authority    = "https://acme.authagonal.io";       // your tenant auth host
    o.ClientId     = builder.Configuration["Bff:ClientId"]!;
    o.ClientSecret = builder.Configuration["Bff:ClientSecret"]!;
    o.Scope        = ["openid", "profile", "email", "offline_access"];
    o.PostLogoutRedirectUri = "https://app.acme.com/";
});

// Trust X-Forwarded-Proto from your ingress. With no options, UseForwardedHeaders() changes nothing.
builder.Services.Configure<ForwardedHeadersOptions>(o =>
{
    o.ForwardedHeaders = ForwardedHeaders.XForwardedProto;
    o.KnownNetworks.Clear();
    o.KnownProxies.Clear();
});

var app = builder.Build();

app.UseForwardedHeaders();   // required behind a proxy or ingress, see the note below
app.MapAuthagonalBff();
app.MapFallbackToFile("index.html");   // your SPA
app.Run();
Node (Express)
// npm install @authagonal/bff
import express from 'express';
import { authagonalBff } from '@authagonal/bff/express';

const app = express();

app.use(authagonalBff({
  authority: 'https://acme.authagonal.io',
  clientId: process.env.BFF_CLIENT_ID,
  clientSecret: process.env.BFF_CLIENT_SECRET,
  cookieSecret: process.env.BFF_COOKIE_SECRET,   // encrypts the session and login cookies
  scope: ['openid', 'profile', 'email', 'offline_access'],
  postLogoutRedirectUri: 'https://app.acme.com/',
}));

app.listen(8080);

Detrás de un proxy, confía en las cabeceras reenviadas

Casi todos los despliegues colocan el BFF detrás de un ingress o de un balanceador de carga que termina TLS y habla HTTP plano con tu proceso. Sin el tratamiento de las cabeceras reenviadas, el BFF cree que la solicitud es insegura y emite su cookie de sesión __Host- sin el atributo Secure, que los navegadores descartan entonces en silencio. El síntoma es un inicio de sesión que se completa sin errores y una sesión que nunca aparece. En .NET, habilita XForwardedProto en ForwardedHeadersOptions y llama a app.UseForwardedHeaders() antes de MapAuthagonalBff(), como arriba: la llamada sin opciones no confía en ninguna cabecera. Los adaptadores de Node leen X-Forwarded-Proto por sí mismos y siempre marcan una cookie __Host- como Secure; activa la opción trust-proxy de tu framework para que la dirección del cliente que se reenvía a tu API sea la real.

Endpoints

Se montan bajo /bff de forma predeterminada. Deben servirse desde el mismo origen que tu SPA, porque la cookie de sesión es httpOnly y de mismo origen: ponlos detrás del mismo nombre de host y no en un dominio de API aparte.

RutaPropósito
GET /bff/login?returnUrl=/Arranca el inicio de sesión y redirige a Authagonal. Después devuelve al usuario a returnUrl.
GET /bff/callbackLa URI de redirección de OIDC. Se gestiona por ti; nunca tienes que escribirla.
GET /bff/userDevuelve isAuthenticated, las reclamaciones de la sesión y sessionExpiresAt. Requiere la cabecera anti-falsificación.
GET|POST /bff/logoutCierra la sesión localmente y en Authagonal.
POST /bff/backchannel-logoutRecibe las notificaciones de cierre de sesión de Authagonal, de modo que un cierre de sesión en otro sitio también termina esta sesión.

Desde el navegador

Toda solicitud que no sea de navegación debe llevar una cabecera anti-falsificación estática. Protege frente a la falsificación de solicitudes entre sitios junto con el atributo SameSite de la cookie: el envío de un formulario entre sitios no puede establecer una cabecera personalizada, así que una solicitud que no la lleve se rechaza.

Comprobar quién ha iniciado sesión
const me = await fetch('/bff/user', {
  headers: { 'X-Authagonal-Bff': '1' },
}).then(r => r.json());

if (!me.isAuthenticated) {
  // Navigate, do not fetch: this is a redirect to your identity provider.
  window.location.href = '/bff/login?returnUrl=' + encodeURIComponent(location.pathname);
}

Inicia y cierra sesión navegando, no con fetch: location.href = '/bff/login'. Esas rutas responden con una redirección a tu proveedor de identidad, y una cadena de redirecciones no es algo que fetch pueda seguir de forma útil.

Llamar a tu API

El BFF puede reenviar tu API bajo su propia ruta base y adjuntar el token de acceso de la sesión al pasar. El navegador envía una cookie, tu API recibe un token Bearer que valida de la forma habitual, y nada de ese token es visible para la página ni falsificable por ella. Registra un upstream y las solicitudes a /bff/api/** llegan a él autenticadas. Deja la lista vacía y el proxy queda deshabilitado por completo.

Reenviar una API upstream
o.Upstreams.Add(new BffUpstream
{
    Prefix        = "/orders",                        // matches /bff/api/orders/**
    TargetBaseUrl = "https://api.internal.acme.com",
    StripPrefix   = false,                            // keep /orders in the forwarded path
});
OpciónPredeterminadoQué hace
Upstreams[]Las API a las que reenvía el proxy. Vacío deshabilita el endpoint del proxy.
Prefix/Prefijo de ruta después de /bff/api que gestiona este upstream, por ejemplo /orders.
TargetBaseUrl-URL base a la que se reenvían las solicitudes.
StripPrefixfalseElimina el prefijo coincidente antes de reenviar. Te permite usar un prefijo de enrutamiento sintético para repartir un mismo BFF entre varios backends que comparten un espacio de nombres de rutas.
AllowAnonymousProxyRequestsfalseReenvía sin cabecera Authorization una solicitud que no tenga una sesión utilizable, en lugar de rechazarla. Para una API que atiende tanto a llamantes con sesión iniciada como anónimos.
RequiredAuthority[]Un control de autoridad expresado como pares type:action, por ejemplo email:send. Cuando se establece, el proxy comprueba los authorization details del RFC 9396 del token saliente antes de reenviar.
AuthorityLocation-La raíz de locations del RFC 9396 por la que se conoce a este upstream, cuando la autoridad se concede sobre un identificador de recurso público distinto de la dirección interna a la que llama el proxy.
StrictAuthorityfalseRechaza una llamada que lleve una restricción de concesión que el proxy no puede evaluar, en lugar de reenviarla. El proxy reenvía a ciegas y no deriva ningún contexto de restricción, así que está desactivado de forma predeterminada.
ExchangeRoutes[]Rutas del proxy cuyas llamadas al upstream viajan con un token intercambiado y vinculado a un contexto, en lugar del token de acceso principal de la sesión. Gana el primer patrón que coincida.

WebSockets

Un handshake de WebSocket no puede llevar una cabecera personalizada ni un token Bearer, así que aquí no sirven ni la cabecera anti-falsificación ni el proxy. Habilita los tickets y la SPA podrá llamar a GET /bff/ws-ticket, poner en la URL de conexión el ticket de un solo uso y corta duración, y hacer que tu API lo canjee. Genera uno justo antes de cada conexión: se elimina en el primer uso y expira en segundos.

OpciónPredeterminadoQué hace
WsTicketsEnabledfalseHabilita el endpoint ws-ticket. Desactivado de forma predeterminada.
WsTicketLifetime30sCuánto tiempo es válido un ticket. Se mantiene corto a propósito, ya que viaja en una URL.
TicketExchangeParams[]Parámetros de consulta que una solicitud de ticket puede reenviar a un intercambio de tokens, de modo que el ticket queda vinculado a ese contexto en lugar de ser válido para todo.

Entregar un token al navegador, a propósito

Todo el sentido de un BFF es que el navegador no guarda ningún token, así que esto es opcional y de alcance limitado. Existe para el único caso al que el modelo de cookie no llega: un servidor de recursos en otro origen, como una aplicación que incrustas en un iframe, al que hay que llamar con un token Bearer. Habilitado, GET /bff/token?resource=… devuelve un token intercambiado: el token de la sesión reducido a un único recurso de la lista de permitidos y vinculado a cualquier parámetro de contexto también permitido. El navegador nunca ve el token propio de la sesión, y lo que sí recibe es de corta duración y para una sola audiencia. Se rechaza toda solicitud que nombre un recurso fuera de la lista de permitidos, que es lo que impide que esto sea una fábrica de tokens de uso general.

OpciónPredeterminadoQué hace
TokenEndpointEnabledfalseHabilita el endpoint de token. Desactivado de forma predeterminada.
TokenEndpointResources[]Los valores de resource a los que puede dirigirse un token. Cualquier otro se rechaza.
TokenEndpointExchangeParams[]Parámetros de consulta que se reenvían al intercambio como vínculos de contexto, por ejemplo project_id.

Servir a varios inquilinos desde un solo BFF

Establece un parámetro de consulta de inquilino y un solo despliegue atiende a muchos inquilinos: /bff/login?slug=acme selecciona el inquilino, un resolutor aporta la authority y las credenciales de cliente de ese inquilino, la clave viaja en la cookie de correlación hasta la sesión, y el cierre de sesión back-channel resuelve el inquilino a partir del emisor del token. El resolutor predeterminado mantiene el comportamiento de inquilino único idéntico byte a byte, así que esto no te cuesta nada mientras no lo uses.

Ejecutar más de una instancia

Las sesiones viven detrás de IBffSessionStore, que de forma predeterminada es una caché en el propio proceso. Eso sirve para una sola instancia y es incorrecto para varias: un usuario cuya siguiente solicitud aterrice en otra réplica queda desconectado. Registra un almacén compartido, por ejemplo Redis a través de IDistributedCache, antes de añadir el BFF.

Un almacén compartido no basta por sí solo

También necesitas un bloqueo de renovación entre réplicas. El single-flight de renovación es local al proceso, mientras que la sesión y su token de actualización rotatorio viven en el almacén que comparten todas las réplicas. Dos réplicas pueden leer la misma sesión, decidir ambas que hay que renovarla y canjear ambas el mismo token de actualización. Eso es indistinguible de la reutilización de un token robado, y la respuesta correcta ante una reutilización es revocar toda la familia de concesiones, así que un BFF con varias instancias y sin bloqueo puede desconectar a los usuarios de forma rutinaria. Puedes aportarlo de dos maneras: registra un ILeaseProvider mediante el clustering, o implementa IBffRefreshLockStore en tu almacén de sesiones, que es una escritura condicional con tiempo de vida y es el camino más corto si ya usas Redis. Un BFF cuyo almacén parece compartido y no tiene bloqueo lo advierte al arrancar, en lugar de dejar que lo descubras por un ticket de soporte.

Opciones que conviene conocer

El conjunto completo, con la grafía de .NET. El paquete de Node acepta las opciones centrales en camelCase, así que BasePath es basePath y SessionLifetime es sessionLifetimeSeconds. PersistentCookie, CorrelationLifetime (fijo en 15 minutos en Node) y LoginPassthroughParams son solo de .NET.

OpciónPredeterminadoQué hace
Authority-El host de autenticación de tu inquilino. De él se descubren los metadatos OIDC. Obligatorio salvo que trabajes en modo multiinquilino, donde lo aporta el resolutor.
ClientId-El id del cliente confidencial registrado para este BFF.
ClientSecret-El secreto de cliente. Un BFF es un cliente confidencial, así que es obligatorio.
Scopeopenid profile offline_accessÁmbitos solicitados. Incluye offline_access o no habrá token de actualización y las sesiones terminarán cuando lo haga el token de acceso.
BasePath/bffDónde se montan las rutas del BFF.
CallbackPath/bff/callbackLa ruta de la URI de redirección de OIDC. Debe coincidir con la que tiene registrada el cliente.
CookieName__Host-agbffNombre de la cookie de sesión. El prefijo __Host- exige HTTPS, así que el desarrollo local sobre HTTP plano necesita otro nombre.
SessionLifetime8hCuánto puede durar una sesión. Ajústalo para que coincida con la duración absoluta de tu token de actualización, o un usuario inactivo quedará desconectado mientras conserva una credencial que aún era válida.
PersistentCookiefalseSi la cookie sobrevive al cierre del navegador. El token de actualización permanece en el servidor en cualquier caso.
CorrelationLifetime30mCuánto puede tardar un inicio de sesión entre que comienza y llega el callback. Acota la cookie que lleva el state, el nonce y el verificador PKCE, así que el caso que tiene que soportar es el de un usuario que deja abierta la pantalla de inicio de sesión y vuelve más tarde.
RefreshThresholdSeconds60Cuántos segundos antes de su expiración se renueva el token de acceso.
AntiForgeryHeaderX-Authagonal-BffEl nombre de la cabecera que el navegador debe enviar en las solicitudes que no son de navegación.
PostLogoutRedirectUri-Dónde aterriza el navegador cuando se completa el cierre de sesión.
ReturnUrlAllowlist[]Orígenes absolutos a los que puede apuntar un returnUrl no relativo. Las rutas relativas se permiten siempre y todo lo demás se fuerza a /, de modo que no se puede llegar a una redirección abierta por la ruta de inicio de sesión.
LoginPassthroughParams[]Parámetros de consulta que se reenvían desde /bff/login a la solicitud de autorización, por ejemplo prompt, para que un enlace de bienvenida lleve al registro en lugar de al inicio de sesión.
TenantQueryParam-Establécelo para servir a varios inquilinos desde un solo BFF. Ver más arriba.

Ambos entornos de ejecución se comportan igual

Los paquetes de .NET y de Node implementan el mismo contrato de protocolo central, así que el inicio de sesión, el callback, user, el cierre de sesión y el cierre de sesión por canal trasero, la cookie, la cabecera anti-falsificación, el comportamiento de renovación y el proxy básico hacia el upstream son idénticos. Los tickets de WebSocket, el endpoint de token, las rutas de intercambio, StripPrefix, las restricciones de autoridad y el proxy anónimo son solo de .NET. Los nombres de arriba son la grafía de .NET; Node usa los equivalentes en camelCase.

Todo es reemplazable

Las piezas son interfaces, así que puedes llevar el BFF a tu propia infraestructura sin bifurcarlo: IBffSessionStore para dónde viven las sesiones, ICookieProtector para el cifrado de la cookie (ASP.NET Data Protection de forma predeterminada) y ITokenClient para hablar con los endpoints de token y de revocación. Un mismo BFF también puede servir a varios inquilinos mediante IBffTenantResolver, seleccionando el inquilino a partir de un parámetro de consulta en el inicio de sesión y resolviéndolo a partir del emisor del token en el cierre de sesión back-channel.

Gestiona tu portal desde un asistente de IA

Conecta un asistente de IA a tu inquilino y pídele que haga lo que de otro modo harías a base de clics: encontrar a un usuario que no puede iniciar sesión, comprobar si todavía tiene un segundo factor, invitar a alguien, ver quién tiene un rol de administrador.

Es una conexión OAuth corriente, no una clave API. Cada persona inicia sesión como ella misma y aprueba el acceso, así que un asistente puede hacer exactamente lo que esa persona puede hacer en el portal y nada más. No se crea nada nuevo que pueda filtrarse, y revocar un asistente deja intactos a todos los demás.

Cómo activarlo

Abre Configuración y activa el acceso de asistentes de IA. Hasta que lo hagas está desactivado, y mientras está desactivado el endpoint no existe, en lugar de limitarse a rechazar. Una vez activado, el panel muestra la URL que hay que pegar en tu cliente de IA:

Tu URL de MCP
https://portal-api.authagonal.io/api/v1/mcp/{your-tenant}

Cómo obtiene permiso un asistente

Un asistente se registra solo antes de poder iniciar un inicio de sesión, y lo que lo permite es activar el acceso de asistentes de IA. No hace falta que actives nada más y, en particular, no debes activar el registro dinámico de clientes en tu inquilino de usuarios finales para esto: ese ajuste rige el inquilino que atiende a tus propios usuarios, que no es donde inicia sesión un asistente. Registrarse no es tener acceso. Un asistente recién registrado no tiene absolutamente nada hasta que alguien de tu equipo inicia sesión y lo aprueba, y a partir de ahí cada herramienta vuelve a comprobar el rol de esa persona.

Qué puede hacer un asistente

Exactamente lo que puede hacer la persona que lo conectó, decidido en cada llamada contra su propio token. Un agente con tenant:support obtiene las herramientas de diagnóstico y del día a día; las herramientas de administrador no solo están ocultas para él, se rechazan si las nombra directamente. Todo lo que está restringido dentro del portal sigue restringido: cambiar la dirección de correo de un usuario exige allí el rol de administrador, y aquí lo exige también.

Como es una concesión normal, la gestionas de la forma normal: elimina el asistente en la página Aplicaciones autorizadas de tu cuenta y ya no podrá renovar su token, así que deja de funcionar cuando expire su token de acceso actual. Cada cambio que hace un asistente queda escrito en tu registro de auditoría a nombre de la persona por la que actuó, así que el rastro es el mismo que ya lees.

Las herramientas

Treinta y tres en esta versión. Tu cliente de IA decide cuáles habilitar, así que puedes darle a un asistente solo las herramientas de lectura si es todo lo que quieres que haga.

HerramientaRolQué hace
find_userSoporteBuscar usuarios por correo, prefijo de nombre o id. El punto de partida para todo lo demás.
get_userSoporteUn usuario completo, incluido si está activo, confirmado y bloqueado.
get_user_mfaSoporteQué segundos factores tiene inscritos alguien.
get_user_sessionsSoporteDónde tiene sesión iniciada un usuario en este momento.
search_auditSoporteBuscar en el registro de auditoría por actor, acción u objeto afectado.
list_usersSoporteListar el directorio, opcionalmente filtrado a una organización.
get_user_statsSoporteCuántos usuarios tienes y cuántos usan un segundo factor.
invite_userSoporteInvitar a alguien por correo.
resend_inviteSoporteEnviar de nuevo una invitación.
send_verification_emailSoporteEnviar de nuevo el mensaje de verificación de correo.
update_userSoporteActualizar un perfil. Cambiar la dirección de correo sigue requiriendo el rol de administrador.
revoke_user_sessionsSoporteCerrar la sesión de un usuario en todas partes.
list_rolesAdministradorLos roles definidos en tu inquilino.
list_role_membersAdministradorQuién tiene un rol determinado.
assign_roleAdministradorDar un rol a un usuario.
unassign_roleAdministradorQuitar un rol.
reset_user_mfaAdministradorEliminar todos los segundos factores, para alguien que ha perdido su autenticador.
get_settingsAdministradorLa configuración de tu inquilino.
list_sso_connectionsAdministradorTus conexiones SSO y los dominios que cubren.
list_organizationsAdministradorLas organizaciones de tu inquilino, una página cada vez.
get_organizationAdministradorUna organización por id o slug, con sus dominios de correo.
create_organizationAdministradorCrea una organización. El slug es permanente.
update_organizationAdministradorCambia el nombre, las opciones de política, los metadatos o la marca de una organización. El slug no puede cambiar.
delete_organizationAdministradorElimina una organización y todas sus membresías.
list_organization_membersAdministradorLos miembros de una organización, una página cada vez.
add_organization_memberAdministradorAñade un usuario a una organización.
update_organization_memberAdministradorCambia el estado o los roles de un miembro dentro de una organización.
remove_organization_memberAdministradorQuita a un usuario de una organización.
add_organization_domainAdministradorReclama un dominio de correo para una organización. Devuelve el registro TXT de DNS que hay que publicar.
verify_organization_domainAdministradorComprueba el registro TXT y marca el dominio como verificado. Se puede repetir sin riesgo.
remove_organization_domainAdministradorDescarta la reclamación de un dominio. Los miembros existentes se quedan.
list_user_organizationsAdministradorLas organizaciones a las que pertenece un usuario, con su estado y sus roles en cada una.
list_clientsDesarrolladorLos clientes OAuth registrados en tu inquilino.

Lectura y escritura vienen marcadas

Cada herramienta le dice a tu cliente si solo lee, si cambia algo y si ese cambio es destructivo. Un buen cliente lo usa para hacer una consulta sin interrumpirte y para detenerse antes de algo como eliminar un segundo factor. Tómalo como una comodidad y no como un control: lo que de verdad decide qué puede hacer un asistente es tu propio rol, comprobado en cada llamada.

Qué no está incluido todavía

Eliminar usuarios, crear o editar conexiones SSO, la facturación, las copias de seguridad y los secretos de cliente están todos ausentes de esta versión. Eliminar pertenece a tu cola de borrado y no a un sitio contiguo; una conexión SSO pesa lo suficiente como para que una edición equivocada deje fuera a toda una plantilla, así que por ahora son de solo lectura; y una herramienta que devolviera un secreto de cliente lo dejaría en la transcripción de un asistente. Dinos cuáles de estas quieres y en qué orden.

Autenticación de servidores MCP

Si expones un servidor Model Context Protocol, Authagonal puede ser el servidor de autorización que hay detrás. Un asistente de IA se conecta, la persona que está detrás inicia sesión y concede el acceso, y tu servidor recibe un token bearer normal que validas como el de cualquier otra API.

La alternativa es una clave API pegada en la configuración de un asistente: una credencial sin ningún usuario detrás, sin caducidad, sin paso de consentimiento y sin forma de revocar un conector sin rotarla para todo el mundo. Hacerlo con OAuth significa que la concesión pertenece a una persona con nombre, es visible en tu registro de auditoría y se puede revocar desde el portal sin tocar nada más.

Cómo se produce la conexión

Todo el intercambio se basa en el descubrimiento, así que un cliente conforme no necesita más configuración que la URL de tu servidor.

PasoQué ocurre
1El conector llama a tu servidor MCP sin token y recibe un 401 que indica dónde mirar.
2Obtiene los metadatos de tu recurso protegido, que nombran a tu inquilino de Authagonal como servidor de autorización.
3Obtiene los metadatos del servidor de autorización del inquilino y, al no haberse registrado nunca en ninguna parte, se registra a sí mismo.
4Envía al usuario a iniciar sesión y aprobar el acceso, nombrando a tu servidor MCP como el recurso para el que quiere un token.
5Vuelve a llamar a tu servidor con el token bearer resultante, que está acotado a tu servidor y a ese usuario.

Nada de esa secuencia es específico de Authagonal: es la especificación de autorización de MCP, construida sobre RFC 9728 para los metadatos del recurso, RFC 8414 para descubrir el servidor de autorización, RFC 7591 para el registro y RFC 8707 para nombrar el recurso. Un conector que sigue la especificación funciona sin tratarnos como un caso especial.

Deja que los conectores se registren solos

Un conector que nunca has visto no puede usar un cliente que hayas creado a mano, así que registra uno en tiempo de ejecución. Eso está desactivado por defecto. Activa el registro dinámico de clientes en Configuración y el endpoint de registro aparecerá en tu documento de descubrimiento; déjalo desactivado y el endpoint no se anuncia y rechaza las solicitudes. Activarlo abre el registro solo para tu inquilino, nunca para el de nadie más.

ProtecciónQué ocurre
Tipos de concesiónSolo se pueden registrar los flujos authorization code y refresh. El autorregistro no puede crear un cliente de máquina a máquina que evitaría por completo a un usuario.
PKCESe impone a todo cliente registrado, sea lo que sea lo que haya pedido el registro.
ConsentimientoTambién se impone. Un conector registrado no puede obtener un token hasta que una persona haya visto qué está pidiendo y lo haya aprobado.
ÁmbitosLos ámbitos integrados de OIDC están siempre disponibles. Más allá de esos, un cliente que se registra solo puede pedir únicamente un ámbito llamado mcp, y solo una vez que tu inquilino lo define sin restricciones de rol. Los ámbitos roles y groups no están disponibles mediante autorregistro.
Límite de tasaDiez registros por dirección IP y hora, para que un endpoint abierto no pueda usarse para llenar tu almacén de clientes.

Se sirven ambas rutas de descubrimiento

Los clientes MCP resuelven el servidor de autorización a través de /.well-known/oauth-authorization-server (RFC 8414), mientras que los clientes OIDC usan /.well-known/openid-configuration. Tu inquilino responde en ambas con los mismos metadatos, de modo que un conector que sigue la especificación MCP te encuentra sin que haya que decirle dónde buscar.

Qué implementa tu servidor MCP

Dos cosas pequeñas, y a partir de ahí es un servidor de recursos corriente. Primero, publica metadatos de recurso protegido que nombren a tu inquilino como servidor de autorización. Sírvelos en la ruta well-known y, si tu endpoint MCP está en una subruta, también en la forma con el sufijo de ruta, ya que los clientes prueban ambas.

Metadatos de recurso protegido
GET https://your-app.example/.well-known/oauth-protected-resource

{
  "resource": "https://your-app.example/mcp",
  "authorization_servers": ["https://acme.authagonal.io"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["mcp"]
}

Segundo, cuando llegue una llamada sin un token válido, responde 401 con un encabezado WWW-Authenticate que apunte a esos metadatos. Ese encabezado es lo que convierte un rechazo en una conexión: sin él el cliente no tiene forma de descubrir dónde autenticarse, y simplemente falla.

Validar el token
// Validate the connector's token like any other resource server.
builder.Services.AddAuthentication().AddJwtBearer("McpBearer", o =>
{
    o.Authority = "https://acme.authagonal.io";              // your tenant
    o.TokenValidationParameters.ValidAudience = "https://your-app.example/mcp";
});

// Unauthenticated? Point the connector at the metadata rather than just refusing.
http.Response.Headers.WWWAuthenticate =
    "Bearer resource_metadata=\"https://your-app.example/.well-known/oauth-protected-resource\"";
return Results.Unauthorized();

Comprueba la audiencia, no solo la firma

Valida que el token se emitió para tu servidor. El conector nombra a tu servidor MCP como el recurso, así que la audiencia del token es la URL de tu recurso. Un servidor de recursos que solo comprueba la firma y el emisor aceptará un token emitido para otro recurso del mismo inquilino, y así es como el acceso de un conector acaba siendo el de otro.

Ámbitos, planes y revocación

Define un ámbito llamado mcp en tu página Ámbitos, sin restricciones de rol, y un conector que se registra solo podrá solicitarlo; aparece en la pantalla de consentimiento para que el usuario vea qué está aprobando. El sujeto del token es la persona que inició sesión, de modo que tu servidor puede decidir qué puede hacer esta persona concreta en lugar de tratar a todos los conectores por igual. Un conector registrado por sí mismo no puede solicitar los ámbitos roles ni groups, así que consúltalos en tu lado en lugar de esperar que vengan en el token.

Como es una concesión de OAuth corriente, la revocación funciona de la forma corriente: el usuario elimina el conector en la página Aplicaciones autorizadas de su cuenta, lo que descarta su concesión y su token de actualización para que no pueda renovarse. /connect/introspect y /connect/userinfo rechazan de inmediato sus tokens de acceso existentes; un servidor que solo valida el JWT localmente acepta uno hasta que expira. El registro de auditoría deja constancia de cada inicio de sesión junto con el cliente al que iba destinado.

AjusteQué ocurre
Dynamic client registrationAjuste del portal que permite a los conectores registrarse solos. Desactivado por defecto.
mcpEl único ámbito, más allá de los integrados de OIDC, que puede solicitar un cliente que se registra solo. Defínelo en tu inquilino, sin restricciones de rol, para ofrecerlo.
resourceEl parámetro que envía un conector para nombrar a tu servidor MCP, lo que reduce la audiencia del token a él.

Crea una interfaz de inicio de sesión personalizada

Reemplaza las pantallas alojadas de inicio de sesión, registro, restablecimiento de contraseña y MFA de Authagonal por tu propia interfaz, mientras Authagonal sigue encargándose de la autenticación, MFA, SSO, sesiones y emisión de tokens. Dos vías: usar nuestra biblioteca de componentes de React, o llamar a la API de autenticación directamente desde cualquier framework. Es opcional: primero habilita Interfaz de inicio de sesión personalizada en Configuración → Sesión.

A fully customized hosted login page with a tenant logo, brand color, and support email in the footer

Requisito previo: un dominio personalizado en tu raíz

La sesión de inicio de sesión es una cookie de origen propio (first-party), por lo que tu interfaz y el servidor de autenticación de Authagonal deben compartir un dominio registrable. Apunta un dominio de autenticación personalizado a Authagonal en la misma raíz donde se ejecuta tu app — p. ej. autenticación en login.acme.com, app en app.acme.com. La configuración Custom login UI permanece deshabilitada hasta que exista un dominio personalizado activo.

Tu interfazHost de autenticación¿Funciona?
app.acme.comlogin.acme.com✅ misma raíz
acme.comauth.acme.com✅ misma raíz
app.acme.comacme.authagonal.io❌ entre sitios
myapp.iologin.acme.com❌ entre sitios

Por qué se requiere un dominio personalizado

Una cookie de sesión entre sitios sería una cookie de terceros — que los navegadores (Safari, Chrome) están eliminando progresivamente. Mantener la autenticación en tu propia raíz hace que la cookie sea de origen propio y a prueba de futuro, y es lo que impone la plataforma: las llamadas de autenticación de origen cruzado solo se aceptan desde un origen que comparta el dominio raíz del host de autenticación.

No se necesita ninguna configuración de CORS en el cliente para las llamadas a /api/auth: una vez activada la Interfaz de inicio de sesión personalizada, cualquier origen en el mismo dominio registrable que tu dominio de autenticación se admite automáticamente. Agrega el origen de tu interfaz (p. ej. https://app.acme.com) a los Orígenes CORS permitidos del cliente (Clientes → URIs) solo si el navegador también realiza el intercambio de tokens.

React: @authagonal/login

npm i @authagonal/login incluye la lógica de autenticación y la interfaz en un solo paquete — el mismo sobre el que está construido el inicio de sesión alojado de Authagonal. Elige tu nivel:

  • App completa — incorpora App y aplícale tu tema mediante la marca.
  • Componer páginas — usa LoginPage, MfaChallengePage, ResetPasswordPage… dentro de tu propio diseño.
  • Primitivas + lógica — crea tus propias pantallas con AuthLayout/Button/Input y el cliente de la API (login, mfaVerify, forgotPassword, …).
Una pantalla personalizada usando la API de @authagonal/login
import { AuthLayout, Input, Button, login, ApiRequestError } from '@authagonal/login';

// returnUrl: the /connect/authorize URL your login page was opened with
function MyLogin({ returnUrl }: { returnUrl: string }) {
  async function onSubmit(email: string, password: string) {
    try {
      const res = await login(email, password, returnUrl);  // POST /api/auth/login (sets the session cookie)
      if (res.mfaRequired) {/* render your MFA step, then mfaVerify(res.challengeId!, 'totp', code) */}
      else if (res.mfaSetupRequired) {/* enrol first: mfaTotpSetup(res.setupToken) */}
      else window.location.href = returnUrl;                 // resume /connect/authorize
    } catch (e) {
      if (e instanceof ApiRequestError) {/* show e.message; e.error is the error code */}
    }
  }
  return <AuthLayout>{/* your own markup + <Input/> <Button/> */}</AuthLayout>;
}

Cualquier framework: llama a la API de autenticación

¿No usas React? Llama directamente a los endpoints del flujo de autenticación (bajo /api/auth) y luego entrega al flujo OIDC estándar /connect/authorize. Envía credentials: 'include' para que se almacene la cookie de sesión.

EndpointPropósito
POST /api/auth/loginAutenticar; devuelve mfaRequired o una URL de retorno
POST /api/auth/registerRegistro de autoservicio (cuando está habilitado)
POST /api/auth/forgot-passwordIniciar un restablecimiento de contraseña
POST /api/auth/reset-passwordCompletar un restablecimiento de contraseña
GET /api/auth/password-policyPolítica de contraseñas (para mostrar las reglas)
POST /api/auth/mfa/*Configuración y verificación de MFA (TOTP, WebAuthn, recuperación)

Usa credentials: 'include'

La sesión es una cookie, así que tus solicitudes fetch deben enviar las credenciales. Las llamadas de origen cruzado solo tienen éxito cuando Custom login UI está habilitado y tu origen comparte el dominio raíz del host de autenticación — de lo contrario se rechazan con 403.
Autentica y luego entrega a OIDC
# 1. Authenticate (browser fetch; credentials:'include' so the session cookie is stored)
curl -i -X POST https://login.acme.com/api/auth/login \
  -H "Content-Type: application/json" \
  -H "Origin: https://app.acme.com" \
  --data '{"email":"[email protected]","password":"..."}'
# (handle {"mfaRequired":true} → POST /api/auth/mfa/verify, then continue)

# 2. Hand off to the OAuth flow: top-level navigation to the authorize endpoint with PKCE:
# https://login.acme.com/connect/authorize?client_id=my-app&redirect_uri=...&response_type=code
#   &scope=openid%20profile%20email&code_challenge=...&code_challenge_method=S256
# The session cookie (same-site) authenticates the user; you get back a code → exchange at /connect/token.

Un inquilino, muchos clientes

Un patrón para un integrador, un inquilino y N clientes con marca propia, cada uno con su propio dominio de inicio de sesión y sus propios usuarios, sin necesitar un inquilino por cliente. Para esto existen el aprovisionamiento declarativo y las organizaciones: convertirlo en un cambio de configuración en lugar de una tarea de ingeniería.

La estructura

  • Una organización por cliente, dentro de un único inquilino.
  • Un dominio de inicio de sesión con marca propia por cliente, cada uno fijado a la organización de ese cliente: iniciar sesión en él solo puede emitir un token para esa organización.
  • La aplicación también se sirve por host de cliente, todo desde el mismo despliegue: nada del código, la compilación o la imagen cambia entre clientes.
  • La relying party elige su autoridad a partir del host en el que se ejecuta, no a partir de una constante de compilación: el mismo paquete se conecta a un dominio de inicio de sesión distinto según el host de cliente que lo haya servido.

Paso a paso

Aprovisiona al cliente. Llama al endpoint de aprovisionamiento declarativo con una especificación que nombre la nueva organización y su dominio. La llamada es idempotente y está limitada por sección.

Especificación de aprovisionamiento
{
  "organizations": [
    { "slug": "acme", "name": "Acme Pty Ltd" }
  ],
  "customDomains": [
    { "domain": "login.acme.example", "organizationSlug": "acme" }
  ]
}

Apunta el DNS del cliente al inquilino. Un único CNAME desde la zona propia del cliente, que demuestra control e intención: sin token TXT.

CNAME record
_authagonal-challenge.login.acme.example.  CNAME  <slug>.<platformDomain>.

¿Misma cuenta de Cloudflare que la plataforma?

El registro debe ser solo DNS (sin proxy): un CNAME con proxy entre dos zonas de la misma cuenta nunca llega al custom hostname SaaS de la plataforma. Una zona de cliente en una cuenta distinta no tiene ningún interruptor de proxy con el que equivocarse.

Apunta la aplicación al host del cliente. La relying party resuelve su propia autoridad OIDC en cada solicitud, según el host que está sirviendo en ese momento; un host sin entrada en el mapa de clientes recurre a la derivación clásica de un solo inquilino, así que añadir un cliente es puramente aditivo.

oidc.ts
export function resolveCustomer(): { authority: string; clientId: string } {
  const cfg = getConfig();
  const customer = cfg.customers?.[window.location.host];
  if (customer) return customer;
  const baseDomain = cfg.baseDomain || window.location.hostname.replace(/^consumer\./, '');
  return { authority: `https://${cfg.tenantSlug}.${baseDomain}`, clientId: cfg.clientId };
}

El cliente no pide nada específico de la organización: ni parámetro organization, ni scope por cliente. La fijación del dominio hace toda la selección de organización en el servidor, que es lo que hace realmente cierto que “la aplicación es el mismo código para todos los clientes”.

Lo que ve el cliente

La página de inicio de sesión muestra la marca propia de cada organización combinada sobre la del inquilino; consulta Sobrescritura de marca. Cada cliente puede tener su propio nombre de aplicación, logotipo, color y correo de soporte sin afectar a los demás.

A un usuario del cliente A que intenta iniciar sesión en el host del cliente B se le rechaza, sin mostrarle los datos del cliente B, de una de estas dos formas según cómo surgió el conflicto:

  • La relying party no envía nada y simplemente llega al dominio fijado: la fijación aporta la organización en nombre del usuario, la selección pasa a ser explícita y a un usuario del cliente A sin membresía en B se le rechaza en el punto en que se emitiría el token.
  • La relying party nombra por sí misma una organización distinta: el middleware de fijación de dominio la rechaza directamente con un 400, antes de mostrar cualquier página de inicio de sesión.

El rechazo por membresía redirige de vuelta a la aplicación

La primera forma anterior no es una página de inicio de sesión rota: es una redirección OIDC ordinaria error=access_denied de vuelta al redirect_uri de la propia relying party, con una descripción que indica exactamente qué membresía de organización faltaba.

Incorporar al cliente N+1

Con Terraform ejecutando la llamada de aprovisionamiento, incorporar a otro cliente es editar un único archivo: otra entrada en el arreglo de organizaciones, otra entrada de dominio que la fije, otro registro DNS. Nada de la aplicación, su despliegue o su compilación cambia: el resolvedor basado en host recoge al nuevo cliente en cuanto existe su entrada de configuración.

Implementación de referencia

Un inquilino de desarrollo persistente ejercita todo este patrón de extremo a extremo con dos dominios de cliente reales, con un conjunto de pruebas de extremo a extremo que aprovisiona miembros, comprueba la marca y el claim org_id, y verifica las dos formas de rechazo anteriores: documentación ejecutable, no solo una descripción.

Ejecútalo en local
cd e2e-consumer && DOMAIN=authagonal.dev npx playwright test organizations-domains

El conjunto de pruebas se ejecuta por defecto como cualquier otra especificación; puede omitirse en un entorno donde los dominios de referencia no estén aprovisionados, ya que es la única especificación del conjunto que depende de infraestructura fuera del control del propio repositorio.

Planes y límites

Authagonal ofrece un plan Free y cuatro niveles de pago. Todos los planes incluyen todas las funcionalidades de autenticación. Los planes difieren en el límite de Usuarios Activos Mensuales (MAU) y en el precio de excedentes, y el plan Free solo tiene soporte de la comunidad, sin la mesa de soporte del inquilino.

Niveles de plan

PlanLímite MAUExcedenteCosto de excedente/usuario
Free250No—
Starter1,000No—
Pro5.000Sí$0,04/usuario
Scale25.000Sí$0,025/usuario
Enterprise100.000Sí$0,015/usuario

Usuarios Activos Mensuales (MAU)

Un Usuario Activo Mensual es cualquier usuario único que se autentica exitosamente al menos una vez durante un mes natural (UTC). Los usuarios aprovisionados a través de SCIM pero que no han iniciado sesión no cuentan para tu total de MAU.

Excedentes: si tu plan admite excedentes (Pro y superiores) y los excedentes están habilitados para tu inquilino (están desactivados por defecto), los usuarios más allá del límite de MAU se facturan a la tarifa por usuario mostrada en la tabla de planes anterior. Un tope de excedente fija el número máximo de usuarios adicionales permitidos por encima del límite.

Aplicación: si tu plan no admite excedentes (Free, Starter) o los excedentes no están habilitados, los usuarios que ya han iniciado sesión este mes siempre conservan el acceso. Cuando el inquilino supera su límite por primera vez, comienza un período de gracia de 10 días durante el cual los usuarios nuevos todavía pueden iniciar sesión. Después, a los usuarios que no han iniciado sesión este mes se les deniega el acceso hasta el mes siguiente o hasta que actualices tu plan.

Conjunto completo de funcionalidades en todos los planes

Todos los planes incluyen el conjunto completo de funcionalidades — SSO, SCIM, MFA, dominios personalizados, marca, webhooks, registro de auditoría y el portal.