auth.* del entorno. Ningún
endpoint de cara al cliente apunta al motor subyacente — incluso /.well-known/*
se sirve desde el issuer. Los ejemplos a continuación usan la URL base de producción
https://auth.bbrands.io; sustituye por la base de cada entorno:
Convenciones
- Content-Type:
application/json, excepto los endpoints OAuth que usanapplication/x-www-form-urlencoded. - Transporte: solo HTTPS (TLS 1.2+).
- Caché:
Cache-Control: no-storeen cada endpoint OAuth. - Errores: los endpoints OAuth devuelven
{"error": "...", "error_description": "..."}. - Correlación: cada respuesta transporta
X-Request-Id.
Discovery
GET /.well-known/openid-configuration
Devuelve el documento de discovery OIDC. Público, sin auth. Apunta la
autoconfiguración de tu cliente a esta URL.
El
iss en el discovery y en cada token de acceso emitido es la URL canónica
auth.* por entorno — nunca la URL del motor subyacente. El
registration_endpoint intencionalmente no se expone: el registro dinámico
de clientes está desactivado; los clientes se dan de alta a través de la consola de administración de identidad.id_token_signing_alg_values_supported lista ["ES256"] por defecto y
["ES256", "RS256"] en los entornos donde la vía RS256 del id_token está
habilitada. ES256 es siempre el algoritmo por defecto; RS256 solo aplica a
los clientes registrados con id_token_alg: "RS256" (p. ej. Odoo).GET /.well-known/jwks.json
Devuelve las claves públicas para validar los JWT OAuth. Público. Servido por el
IdP (proxy/caché del JWKS del motor); el cliente nunca ve la URL del motor.
Response headers
En los entornos con la vía RS256 habilitada, el documento contiene la clave
EC P-256 del motor más la clave pública RSA del IdP (ambas con
kid).
Los verificadores resuelven las claves por kid, así que la clave extra es
transparente para los clientes ES256.Endpoint de autorización
GET /api/v3/oauth/authorize
Inicia el flujo de authorization-code. Llamado por el navegador del usuario tras una
redirección desde el cliente. La solicitud se valida estrictamente, se reenvía al
motor, y el navegador se redirige a la UI de consentimiento en el mismo origen auth.*.
string
requerido
Debe ser
code.string
requerido
El identificador del cliente OAuth registrado (UUID provisto en el onboarding).
string
requerido
Debe coincidir exactamente con una de las redirect URIs registradas del cliente.
string
requerido
Lista separada por espacios. Debe incluir
openid. Soportados: openid email profile.string
requerido
Valor anti-CSRF del cliente, devuelto en la redirección.
string
requerido
Challenge PKCE. PKCE es obligatorio para cada cliente.
string
requerido
Debe ser
S256 (plain se rechaza).string
Recomendado. Valor anti-replay del ID-token.
302 a https://auth.bbrands.io/oauth/consent?... (la
UI de consentimiento). Con una sesión válida y un cliente first-party habilitado, el consentimiento
se autoaprueba y el navegador se redirige de vuelta al cliente con
?code&state.
Los errores de validación se devuelven como JSON 400 (sin redirección, ya que el
redirect_uri no puede considerarse confiable antes de la validación):
Consentimiento
UI de consentimiento — https://auth.bbrands.io/oauth/consent
Servida por la app de autenticación (no una API). Valida la sesión de B Brands
(redirigiendo al login con ?next= cuando falta), muestra el nombre del cliente y los
scopes OIDC solicitados, y ofrece Permitir / Denegar. Los usuarios first_party + habilitados se
autoaprueban.
POST /api/v3/oauth/decision
Registra la decisión de consentimiento del usuario para auditoría. No continúa el
flujo de código OAuth (el motor lo hace, vía el authorize_url).
string
requerido
Handle estable del cliente, p. ej.
erp-prod.string
requerido
approve o deny.string[]
Scopes solicitados.
string
Identificador del usuario.
client_handle faltante o un decision inválido devuelve 400.
Endpoint de token
POST /api/v3/oauth/token
Intercambia un código de autorización por tokens, o refresca un token de acceso. Llamado
servidor a servidor por el cliente. El gateway hace proxy de la solicitud al motor,
que ejecuta el hook de token de acceso (verificación de habilitación + reescritura de iss/aud).
Headers: Content-Type: application/x-www-form-urlencoded y
Authorization: Basic <base64(client_id:client_secret)> (o el secreto en el
cuerpo para client_secret_post).
aud es la audiencia fija del IdP bbrands-idp; el cliente solicitante se
identifica por https://bbrands.io/client_handle (y client_id). Valida
iss, la firma ES256 vía JWKS, y que client_handle coincida con tu
propio handle. El id_token conserva el issuer/audience del motor y está pensado
para la verificación de nonce y los claims de perfil; usa el token de acceso como la
aserción de identidad.Vía RS256 del id_token: los clientes registrados con
id_token_alg: "RS256" (p. ej. Odoo con el módulo OCA auth_oidc) reciben
el mismo id_token re-firmado con la clave RSA del IdP — header
alg: RS256 con un kid que resuelve vía /.well-known/jwks.json, con
todos los claims preservados (nonce, at_hash, exp, …). El token de
acceso siempre es ES256.Endpoint UserInfo
GET /api/v3/oauth/userinfo
Devuelve los claims de identidad del usuario, enriquecidos con la dimensión
de cuenta de negocio. Con proxy al userinfo del motor.
Headers: Authorization: Bearer <access_token> (obligatorio; un header faltante
devuelve 401 invalid_token con WWW-Authenticate: Bearer).
Sin claim de permisos/roles. UserInfo es identidad más contexto de tenancy:
el objeto
https://bbrands.io/profile lleva la cuenta vinculada al usuario
mediante el rol primary_user (account), el id del sistema externo de esa
cuenta (odoo, null hasta que la API de migración la mapee) y el sujeto
(user, igual a sub).Endpoint de revocación
POST /api/v3/oauth/revoke
Invalida un token (RFC 7009), típicamente al cerrar sesión. Agrega el jti del token al
store de blacklist local y hace proxy de la revocación al motor.
Body (application/x-www-form-urlencoded): token, token_type_hint
(access_token | refresh_token), client_id.
Según la RFC 7009 la respuesta es siempre
200 y opaca, independientemente de si el
token existía.Códigos de error personalizados
Más allá de los errores OAuth estándar, los endpoints específicos de B Brands pueden devolver estos enerror.code:
Rate limiting
Las respuestas incluyen
X-RateLimit-Limit, X-RateLimit-Remaining,
X-RateLimit-Reset; 429 transporta Retry-After.