> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bbrands.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Inicio de sesión social y SSO interno

> El inicio de sesión social para usuarios finales y el handshake de sesión entre apps — dos sistemas distintos del IdP OAuth para clientes externos.

<Warning>
  Esta página cubre **dos sistemas que son diferentes del IdP OAuth** para
  clientes externos. No los confundas:

  | Sistema                     | Propósito                                                           | Token clave                           | Punto de entrada                      |
  | --------------------------- | ------------------------------------------------------------------- | ------------------------------------- | ------------------------------------- |
  | **IdP OAuth (OIDC)**        | Clientes OAuth externos                                             | code → ES256 → exchange interno       | `/api/v3/oauth/*`                     |
  | **Inicio de sesión social** | Usuarios finales de B Brands inician sesión con un proveedor social | JWT interno HS256                     | `/api/v3/auth/login/oauth/<provider>` |
  | **SSO interno**             | Transportar una sesión entre apps de B Brands en distintos dominios | token firmado de vida corta en la URL | `/api/v3/auth/sso/exchange`           |
</Warning>

## 1. Inicio de sesión social

Los usuarios finales inician sesión en las apps de B Brands con un proveedor social. Esto usa el
inicio de sesión social del motor administrado directamente, luego acuña el JWT interno de B Brands — **no**
usa el IdP OAuth, los tokens ES256, ni la pantalla de consentimiento.

### Rutas

| Paso                      | Método | Ruta                                                                 |
| ------------------------- | ------ | -------------------------------------------------------------------- |
| 1. Inicio                 | GET    | `/api/v3/auth/login/oauth/<provider>?redirect_url=<url>&format=json` |
| 2. Callback (puente HTML) | GET    | `/api/v3/auth/login/oauth/<provider>/callback`                       |
| 3. Procesamiento          | GET    | `/api/v3/auth/login/oauth/<provider>/callback-redirect`              |

```mermaid theme={null}
sequenceDiagram
    actor U as User
    participant A as App (frontend)
    participant G as api.bbrands.io
    participant S as OIDC engine
    participant GG as Social provider

    U->>A: Click "Continue with provider"
    A->>G: GET /api/v3/auth/login/oauth/<provider>?redirect_url=…
    G->>S: signInWithOAuth(provider, redirectTo=callback)
    alt Web
        G->>U: 302 to provider OAuth URL
    else Mobile / SPA (Accept: application/json or format=json)
        G->>U: 200 { data: { redirectUrl } }
    end
    GG->>S: User approves
    S->>G: /callback#access_token&refresh_token&expires_in
    G->>G: HTML page reads fragment → /callback-redirect?access_token=…
    G->>S: setSession(access_token, refresh_token)
    G->>G: ensure registration (deferred), login
    alt Deep link (redirect_url without http/https)
        G->>U: 302 with tokens in query
    else Web / API
        G->>U: 200 login payload + is_new_user + redirect_url
    end
```

* La ruta de inicio requiere `redirect_url`; `format=json` (o `Accept: application/json`) devuelve JSON en lugar de un 302.
* La página `/callback` es un puente HTML que lee el fragmento de la URL (`#access_token…`) o `?code=` y lo reenvía a `/callback-redirect`.
* `/callback-redirect` establece la sesión del motor, autorregistra un perfil si es necesario, y devuelve el **JWT interno de B Brands** (HS256) más los datos de la cuenta.

<Note>
  Existen rutas heredadas para proveedores adicionales bajo una versión anterior de la API. El
  flujo actual añade un `redirect_url` parametrizable y soporte JSON/deep-link.
</Note>

## 2. SSO interno — el handshake entre apps

Cuando un usuario inicia sesión vía la app de autenticación y debe aterrizar en una app
hermana de B Brands en un **dominio diferente**, la sesión se transporta con un token firmado de
vida corta en la URL. Un pequeño paquete interno compartido maneja esto.

```mermaid theme={null}
sequenceDiagram
    actor U as User
    participant AU as Authentication app (issuer)
    participant APP as Target app (consumer)
    participant G as api.bbrands.io

    U->>AU: Login (email/password or social)
    AU->>AU: Sign a short-lived handshake token (HS256, 60s)
    AU->>U: Redirect target?<handshake-token>
    U->>APP: GET target?<handshake-token>
    APP->>G: POST /api/v3/auth/sso/exchange { token }
    G->>G: Verify token (HMAC), re-verify inner jwt, mint new session JWT
    G->>APP: { jwt }
    APP->>U: Set HttpOnly session cookie, redirect to clean URL
```

### Paquete interno compartido de SSO

Un pequeño paquete para las apps **consumidoras**, con helpers para:

| Helper             | Propósito                                                                                                       |
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
| Firmar / verificar | Crear y validar el token de handshake HS256 de vida corta (claims `{ jwt, nonce, next? }`, TTL por defecto 60s) |
| Exchange           | Llamar a `POST /api/v3/auth/sso/exchange` y recibir la sesión `{ jwt }`                                         |
| Proxy              | Un middleware que convierte el token de handshake en una cookie de sesión                                       |

```typescript theme={null}
// Consumer app proxy (pseudocode)
const sso = createSsoProxy({
  backendUrl: config.routeApiUrl,
  cookieDomain: config.sessionCookieDomain,
  cookieName: config.sessionCookieName,
  hmacSecret: config.ssoHmacSecret,
  isProduction: config.isProduction,
});

export default function proxy(request) {
  if (hasHandshakeToken(request)) return sso.proxy(request);
  // ...session guard
}
```

### El emisor del SSO

La app de autenticación es la UI centralizada de login/registro/2FA + consentimiento. Es
el **emisor**: firma el token de handshake y escribe la cookie de sesión
directamente en server actions (no monta el proxy consumidor). Los targets del mismo dominio
redirigen sin token de handshake; los targets de dominio cruzado reciben uno.

<Note>
  El exchange de SSO interno (`/api/v3/auth/sso/exchange`) es para la transferencia de sesión
  entre apps. **No** es el exchange de clientes OAuth externos
  (`/api/v3/oauth/exchange`). Consulta [Intercambio de tokens](/es/oauth/token-exchange).
</Note>

### Modelo de seguridad

| Aspecto           | Detalle                                                             |
| ----------------- | ------------------------------------------------------------------- |
| Algoritmo         | HS256                                                               |
| Secreto           | Un secreto HMAC compartido entre el emisor y el backend             |
| TTL               | 60s — solo sobrevive a una redirección                              |
| Claims            | `jwt`, `nonce`, `next?` + `iss`/`aud`/`iat`/`exp`                   |
| Cookie del target | `HttpOnly`, `SameSite=Lax`, `Secure` en producción                  |
| Fallo             | El proxy redirige a una URL limpia con `?sso_error=exchange_failed` |
