Capa nueva sobre la identidad (capa 7). El login usuario+contraseña sigue
funcionando igual; GitHub OAuth es aditivo y cerrado por defecto (sin las
4 variables de entorno, /oauth/github/* responde 503 y nada cambia).
OAuth NO inventa una sesión nueva: su único trabajo es producir el mismo token de sesión HMAC de la capa 7. El navegador hace el viaje a GitHub por HTTP; vuelve con un token; el front lo usa exactamente como el auto-login de hoy. El protocolo WebSocket no cambia ni un byte.
orux/identity/oauth.py— lógica pura (URL de autorización, identidadgh:<login>,stateCSRF firmado con vencimiento). Testeada en sandbox (tests/test_oauth.py).UserStore.asegurar_externo/PgUserStore.asegurar_externo— crea la cuentagh:<login>sin contraseña (no se puede entrar a ella por password;existe()sí, para queSessionMessagela acepte).orux/api/app.py— rutas HTTP (contenedorapi, Starlette):GET /oauth/github/login→ 302 a GitHub constatefirmado.GET /oauth/github/callback→ validastate, canjeacode, derivagh:<login>, asegura la cuenta, emite el token y redirige al SPA.
- Caddy proxya
/oauth/*→api:8800.docker-compose.ymly.env.exampleya tienen las variables.
El registro con contraseña está abierto. Si la identidad OAuth fuese el
login pelado, un atacante podría pre-registrar con contraseña el nombre =
al handle de GitHub de una víctima y secuestrar su cuenta cuando entrara por
GitHub. El prefijo gh: hace imposible esa colisión. Que se vea en la
UI es deuda cosmética (se pule luego con un display-name), no se negocia.
-
Botón "Entrar con GitHub" en la pantalla de login: un enlace normal a
/oauth/github/login(es un redirect del navegador, NO fetch/WS). Mostralo siempre; si OAuth no está configurado el server responde 503 y no se inicia nada — opcional: ocultarlo si unGET /oauth/github/logindiera 503, pero no es necesario para un primer corte. -
Al volver al SPA (
/app/), leer la URL de retorno:- Éxito: el token viene en el FRAGMENT —
#session=<token>, NO en el query. El fragmento no viaja al server ni aparece en Referer/logs de proxy (ver_volverenapi/app.py, BACKEND-AUDIT-0019). Leerlo delocation.hash, tratarlo idéntico aorux_sessionde localStorage: guardarlo y mandarSessionMessage(token). Es el mismo token de la capa 7 — el flujo auth→lobby→equipo no cambia. Limpiar el fragmento después (history.replaceState). - Error:
?oauth_error=<código>— códigos:cancelado(el usuario canceló en GitHub),state(CSRF/link vencido),github(falló el intercambio). Mostrar un aviso y volver al login normal.
- Éxito: el token viene en el FRAGMENT —
-
No hace falta tocar
store.ts/protocolo:SessionMessageya existe y el server ya lo acepta para identidadesgh:.
Ver .env.example (sección GitHub OAuth): crear la OAuth App en GitHub con
callback https://TU_DOMINIO/oauth/github/callback, y setear
ORUX_SESSION_SECRET (mismo valor para los servicios orux y api),
ORUX_GITHUB_CLIENT_ID, ORUX_GITHUB_CLIENT_SECRET,
ORUX_OAUTH_REDIRECT.
- Email real de commit: la identidad sigue siendo
gh:<login>y_autor_gitproduce el email sintético…@orux.local. Traer el email verificado de GitHub requiere propagar un campo email por todo el stack (hoy la identidad es un solo string). Diferido. - Display-name (mostrar
octocaten vez degh:octocaten presencia/ commits/panel) — cosmético, diferido. expen el token de sesión (hallazgo de la auditoría de robustez, ver memoriaorux_blindaje_pendiente): ortogonal a OAuth, sigue pendiente.- Scope
repopara autocompletar clone/push: descartado por ahora (consentimiento mínimo, decisión del usuario).