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:
- Tu app genera un
code_verifieraleatorio y sucode_challenge(SHA-256 base64url). - Rediriges al usuario a
/api/oauth/authorizecon tus parámetros. - OrzattyAccount intercede:
- Sin sesión en el navegador → pantalla de login.
- Con sesión(es) → selector de cuenta si hay varias (o primera vez).
- Primera vez por app → pantalla de consentimiento con tus permisos legibles.
- Tras elegir cuenta y aceptar, OrzattyAccount redirige a tu
redirect_uricon?code=...&state=.... - Tu backend intercambia el
codepor 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:
client_id: identificador de tu aplicación (regístrala en el dashboard de Desarrolladores de OrzattyAccount o pídela al equipo).redirect_uri: debe coincidir exactamente con una de las registradas (se compara sin trailing slash).scope: espacios separados (ver lista).state: valor anti-CSRF que te devolvemos intacto.code_challenge/code_challenge_method=S256: PKCE obligatorio para clientes públicos.prompt=none(opcional): SSO silencioso — devuelveerror=login_requiredsi no hay sesión, sin mostrar UI.
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:
- El estado del flujo vive 10 minutos; si expira, el usuario debe reiniciar desde tu app.
- Con una sola sesión y consentimiento ya otorgado para los mismos scopes, el
codese emite sin UI (experiencia "instantánea"). - Si el usuario elige "Usar otra cuenta" e inicia sesión con una nueva, el flujo continúa automáticamente.
Pantalla de consentimiento
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étodo | Ruta | Uso |
|---|---|---|
GET | /api/oauth/authorize | Inicia el flujo (redirect) |
POST | /api/oauth/token | code → tokens (auth code / refresh) |
GET | /api/oauth/userinfo | Perfil del usuario (Bearer) |
GET | /api/auth/me | Sesión actual + JWT fresco (cookie o Bearer) |
POST | /api/auth/logout | Cierra la sesión del navegador |
GET | /api/auth/accounts | Cuentas logueadas en el navegador |
POST | /api/auth/accounts/switch | Cambia la cuenta activa |
Sesiones y cookies del ecosistema
OrzattyAccount mantiene al usuario logueado en todo *.orzatty.com con el modelo tipo Google:
orz_session_<userId>(HttpOnly): sesión opaca por cuenta, 30 días de inactividad con renovación deslizante — mientras el usuario use el ecosistema una vez al mes, nunca expira.orz_accounts(legible): índice de las cuentas logueadas en el navegador (id, email, nombre, avatar).orz_active(legible): la cuenta activa actualmente.orz_token: JWT Bearer de 24h; se refresca solo vía/api/auth/me.
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
openid— verificar identidad (siempre incluido)profile— nombre y avataremail— dirección de correo (@omail si aplica)
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).