OrzattyAccount Identity API

Autenticación unificada del ecosistema Orzatty: OAuth 2.0 + PKCE, multi-cuenta estilo Google, consentimiento de permisos y sesiones persistentes.

OrzattyAccount es el proveedor de identidad (IdP) único de todo el ecosistema Orzatty. Cualquier servicio (web, móvil o CLI) debe autenticar a sus usuarios a través del flujo OAuth descrito aquí — no implementes login propio con contraseñas.

El botón "Continuar con Orzatty" ofrece acceso al perfil del usuario, correo verificado (incluyendo @omail.orzatty.com) y avatar, con experiencia tipo Google: el usuario elige cuenta, ve los permisos de tu app una sola vez y queda conectado.


Flujo OAuth 2.0 (Authorization Code + PKCE)

Requerimos PKCE (S256) para todos los clientes públicos. El flujo completo:

  1. Tu app genera un code_verifier aleatorio y su code_challenge (SHA-256 base64url).
  2. Rediriges al usuario a /api/oauth/authorize con tus parámetros.
  3. OrzattyAccount intercede:
  4. Tras elegir cuenta y aceptar, OrzattyAccount redirige a tu redirect_uri con ?code=...&state=....
  5. Tu backend intercambia el code por un JWT en el token endpoint.

1. Solicitar autorización

GET https://api.myaccount.orzatty.com/api/oauth/authorize
  ?client_id=TU_CLIENT_ID
  &redirect_uri=https://tu-app.com/callback
  &response_type=code
  &scope=openid profile email
  &state=xyz123
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URtcr10O4gygOM
  &code_challenge_method=S256

Parámetros:

2. Intercambio de código

POST https://api.myaccount.orzatty.com/api/oauth/token
Content-Type: application/json

{
  "client_id": "TU_CLIENT_ID",
  "grant_type": "authorization_code",
  "code": "CÓDIGO_RECIBIDO_EN_LA_URL",
  "redirect_uri": "https://tu-app.com/callback",
  "code_verifier": "EL_SECRETO_ORIGINAL_DEL_PKCE"
}

Respuesta exitosa:

{
  "access_token": "<JWT del ecosistema, 24h>",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "<token opaco para renovar>",
  "scope": "openid profile email"
}

El access_token es un JWT HS256 firmado por orzatty-account (issuer orzatty-account, audience orzatty-ecosystem). El refresh_token se usa con grant_type=refresh_token para renovar sin pasar por el navegador.

3. Datos del usuario

GET https://api.myaccount.orzatty.com/api/oauth/userinfo
Authorization: Bearer <access_token>

→ { "sub", "name", "given_name", "family_name",
     "email", "email_verified", "picture" }

Selector multi-cuenta (estilo Google)

Si el usuario tiene varias cuentas de Orzatty logueadas en su navegador, /api/oauth/authorize le muestra el selector de cuenta en accounts.orzatty.com/oauth/choose para decidir con cuál conectar tu app. No tienes que hacer nada extra: es parte del redirect del paso 1.

Detalles que sí te afectan:

La primera vez que un usuario conecta tu app, ve qué permisos solicitas (en lenguaje claro) y debe aceptar. El consentimiento queda memorizado por usuario + app: mientras no pidas scopes nuevos, no se vuelve a preguntar.

Si el usuario rechaza, tu redirect_uri recibe ?error=access_denied&state=... — maneja ese caso con un mensaje amable, no como error del sistema.

El usuario puede revocar el acceso desde myaccount.orzatty.com → Seguridad → Sesiones en cualquier momento.


Endpoints

MétodoRutaUso
GET/api/oauth/authorizeInicia el flujo (redirect)
POST/api/oauth/tokencode → tokens (auth code / refresh)
GET/api/oauth/userinfoPerfil del usuario (Bearer)
GET/api/auth/meSesión actual + JWT fresco (cookie o Bearer)
POST/api/auth/logoutCierra la sesión del navegador
GET/api/auth/accountsCuentas logueadas en el navegador
POST/api/auth/accounts/switchCambia la cuenta activa

Sesiones y cookies del ecosistema

OrzattyAccount mantiene al usuario logueado en todo *.orzatty.com con el modelo tipo Google:

Tu app recibe tokens OAuth propios; estas cookies las maneja OrzattyAccount internamente. Solo importan si construyes UI que conviva con el ecosistema (p. ej. para saber qué cuentas hay sin preguntar).

Scopes /u/n estilo Google

Los servicios del ecosistema pueden servir su UI bajo un prefijo de cuenta: /u/0/ (o /), /u/1/, /u/2/… según la posición de la cuenta en el índice del navegador. OrzattyAccount, Sylor y Omail ya lo soportan.

Para adoptarlo en tu servicio SvelteKit: hook reroute que mapea /u/<n>/ruta → /ruta, y al iniciar OAuth pasa account_scope=/u/1 para que el callback regrese al mismo scope.

API de cuentas (multi-cuenta)

GET /api/auth/accounts → { accounts: [...], active_id }
POST /api/auth/accounts/switch  { user_id }  → { token, user }
POST /api/auth/accounts/signout { user_id }  → { success }

Usa switch para rotar de cuenta desde tu UI: devuelve un JWT fresco de la cuenta elegida (la sesión de esa cuenta debe seguir viva en el navegador).


Scopes disponibles

Scopes extendidos (mail.read, drive.read…) llegan con las integraciones de producto; solicítalos al equipo.

Ejemplo completo (JS)

// 1. PKCE
const verifier = crypto.randomUUID() + crypto.randomUUID();
const challenge = btoa(String.fromCharCode(...new Uint8Array(
  await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))
))).replaceAll('+','-').replaceAll('/','_').replace(/=+$/,'');

// 2. Redirige al usuario
const url = `https://api.myaccount.orzatty.com/api/oauth/authorize` +
  `?client_id=${client_id}&redirect_uri=${encodeURIComponent(redirect_uri)}` +
  `&response_type=code&scope=openid+profile+email&state=${state}` +
  `&code_challenge=${challenge}&code_challenge_method=S256`;
location.href = url;

// 3. En tu /callback: intercambia code → tokens (POST /api/oauth/token)
// 4. Guarda access_token (24h) + refresh_token; refresca cuando expire.
//    Valida el usuario con GET /api/oauth/userinfo.

Soporte: equipo de plataforma Orzatty · Dominios: accounts.orzatty.com (auth UI), myaccount.orzatty.com (dashboard), api.myaccount.orzatty.com (API).