Autenticación
SecureCodingHub admite varios métodos de autenticación. Las sesiones del navegador utilizan tokens bearer JWT; la API pública utiliza API keys de larga duración con autorización por scopes y límites de tasa por clave.
Métodos de autenticación
Elija el método de autenticación que mejor se adapte a su organización:
Magic Code (Email OTP)
Inicio de sesión sin contraseña mediante un código de 6 dígitos enviado por correo. Método por defecto para todos los usuarios. Los códigos caducan a los 10 minutos. Sin contraseñas que gestionar ni recordar.
OIDC (OpenID Connect)
SSO empresarial vía Azure AD, Okta o proveedores compatibles. Flujo de código de autorización con PKCE. Recomendado para organizaciones.
SAML 2.0
SSO basado en federación para entornos empresariales. Flujo de inicio de sesión iniciado por el SP.
Flujo de Magic Code
El flujo de autenticación sin contraseña por defecto funciona así:
El usuario introduce su dirección de correo
El servidor envía un OTP de 6 dígitos al correo
El usuario introduce el código
El servidor verifica el código y emite un JWT
El JWT se almacena en el navegador para gestionar la sesión
Flujo SSO
Cuando SSO está configurado para su organización, el flujo de autenticación cambia:
El usuario abre el punto de entrada SSO de su organización (el enlace incluye el slug de la organización; hoy no hay detección automática correo → dominio)
El navegador redirige al proveedor de identidad configurado
El usuario se autentica con las credenciales corporativas
El IdP devuelve un código de autorización (OIDC) o una afirmación SAML al callback de SecureCodingHub
El servidor valida la respuesta, aprovisiona al usuario mediante JIT en el primer inicio de sesión y emite un JWT
El usuario inicia sesión
Tokens JWT
Todas las sesiones autenticadas orientadas al navegador se gestionan mediante JSON Web Tokens emitidos por el backend después de que el paso de magic code o SSO se complete correctamente.
| Propiedad | Valor |
|---|---|
| Algoritmo | HS256 |
| Vida útil | 30 días desde la emisión. No hay un flujo de refresco dentro de la aplicación; los usuarios se reautentican mediante magic code o SSO una vez que el token caduca. |
| Claims | ID de usuario, ID de organización, rol, nombre, correo, caducidad. |
| Transmisión | Cabecera Authorization: Bearer … en cada llamada interna a la API. |
| Almacenamiento | Se almacena en el cliente en localStorage bajo la clave sch-token. Hoy no existe una opción de cookie HttpOnly. |
API Key Bearer (API pública)
La superficie pública REST y de webhooks bajo /api/public/v1/* utiliza API keys de larga duración en lugar de JWT. Las claves se crean desde la consola de administración en Organización → API Keys y se envían en cada petición como una cabecera bearer estándar:
Authorization: Bearer scs_live_…| Propiedad | Valor |
|---|---|
| Formato | scs_live_ + 32 caracteres aleatorios base62. 41 caracteres en total. |
| Almacenamiento | Solo se guardan en el servidor el hash SHA-256, el prefijo y los últimos cuatro caracteres. El token completo se muestra una sola vez al crearlo y no puede recuperarse de nuevo. |
| Scopes | 16 scopes de grano fino (p. ej. users:read, assignments:write, sarif:ingest). Una petición sin el scope requerido devuelve 403 insufficient_scope. |
| Vida útil | Indefinida por defecto. Puede establecerse una fecha de caducidad opcional en el momento de la creación. Las claves pueden revocarse en cualquier momento; la revocación surte efecto de inmediato. |
| Seguimiento del último uso | Cada llamada exitosa actualiza el campo lastUsedAt de la clave para auditoría e higiene de rotación. |
Referencia completa en API → Autenticación y scopes.
Limitación de tasa
Cada API key pública está acotada por dos ventanas deslizantes que protegen la plataforma de scripts descontrolados y evitan que un tenant deje sin recursos a otro:
| Ventana | Límite | Cabeceras de respuesta |
|---|---|---|
| Por minuto | 60 peticiones | Retry-After, X-RateLimit-Window: per_minute, X-RateLimit-Limit: 60 |
| Por hora | 1.000 peticiones | Retry-After, X-RateLimit-Window: per_hour, X-RateLimit-Limit: 1000 |
Las peticiones que superan cualquiera de las ventanas reciben 429 rate_limited con una cabecera Retry-After en segundos. Un limitador independiente basado en IP (5 peticiones / 15 minutos) cubre el formulario de contacto web anónimo. El tráfico interno de sesión del navegador contra la API de administración protegida por JWT hoy no está limitado por tasa.
Orientación detallada de reintentos y un cliente de ejemplo con backoff exponencial en API → Límites de tasa.
Registro de auditoría
Toda acción que modifica datos — tanto si se origina desde un administrador en el navegador como desde una API key pública — se escribe en una tabla de registro de auditoría por organización. Las acciones de solo lectura (listar, obtener, consultas del panel) no se auditan; el foco está en los cambios con impacto posterior.
| Campo | Significado |
|---|---|
action | Identificador con notación de puntos de lo que ocurrió (p. ej. user.updated, assignment.created, apikey.revoked, sarif.ingested). |
actorEmail / actorRole | Correo y rol del actor. Las mutaciones desde la UI de administración llevan el correo de la persona y org_admin. Las mutaciones desde API keys llevan apikey:<api-key-uuid> y el rol api_key. |
targetType, targetId, targetLabel | El recurso que se cambió. La etiqueta es una descripción breve y legible utilizada en la UI del registro de auditoría. |
metadata | Contexto serializado en JSON que describe exactamente qué cambió (p. ej., los nuevos scopes de una API key, el plazo antes vs después en una asignación). |
ipAddress | La IP de origen de la petición que provocó el cambio. |
createdAt | Marca de tiempo UTC. |
El flujo completo de auditoría puede consultarse desde la UI de administración (Organización → Registro de auditoría) o de forma programática vía GET /api/public/v1/audit-log. Ambas superficies admiten el filtrado por acción, actor y rango de fechas, y la UI de administración expone una exportación CSV para paquetes de evidencia.
Seguridad de sesión
- Los tokens se validan en cada petición a la API
- Los tokens no válidos o caducados se rechazan
- Las sesiones SSO respetan las políticas de sesión del IdP
- Los magic codes son de un solo uso y tienen tiempo limitado
Decisiones de diseño de autenticación que tomó SecureCodingHub y por qué
La ruta de autenticación por defecto en SecureCodingHub no usa contraseña. Tomamos esa decisión deliberadamente. La gran mayoría de compromisos de credenciales que vemos en los datos de formación de clientes siguen rastreándose hasta la reutilización de contraseñas, elecciones débiles y phishing de secretos estáticos. Eliminar la contraseña del flujo principal de inicio de sesión elimina una clase de modos de fallo que ninguna política puede mitigar por completo. Para las organizaciones que requieren un recurso tradicional con contraseña, aplicamos mínimos coherentes con la guía actual de NIST: un umbral de longitud en lugar de un conjunto de reglas de complejidad, cribado contra corpus de contraseñas filtradas conocidas y sin rotación forzada en ausencia de indicios de compromiso.
La recuperación basada en correo se mantiene intencionadamente incluso para cuentas respaldadas por SSO. Cuando un proveedor de identidad se vuelve inaccesible, o cuando se elimina la entrada de directorio corporativo de un colaborador externo a mitad de un contrato, seguimos necesitando una ruta determinista y auditable de vuelta a la cuenta para el propietario verificado. El canal de recuperación está limitado por tasa, es de un solo uso y se registra por separado del flujo de eventos de inicio de sesión estándar para que los equipos de seguridad puedan detectar actividad anómala de recuperación sin que se pierda en el ruido normal de inicios de sesión.
Las cuentas compartidas se desincentivan a nivel de producto en lugar de bloquearse de plano. Mostramos una advertencia en la consola de administración cuando los patrones de uso sugieren que un solo asiento se comparte entre varias personas, porque los asientos compartidos rompen la responsabilidad individual, distorsionan los informes de progreso y complican cualquier investigación futura de incidentes. Las organizaciones que necesiten acceso entre equipos a los paneles deberían utilizar la asignación de roles y los roles de estudiante aprovisionados por SCIM descritos en Seguridad de los datos en lugar de reutilizar credenciales.
Mapear la autenticación al cumplimiento
SecureCodingHub se está preparando para SOC 2 Type II y aún no ha completado una auditoría, por lo que no afirmamos estar certificados. No obstante, diseñamos el subsistema de autenticación frente a las mismas familias de control que un equipo de seguridad esperaría al evaluar a un proveedor para esa auditoría. Las expectativas de SOC 2 CC6.1 sobre acceso lógico — identificación única de cada usuario, autenticación multifactor o step-up equivalente para acciones sensibles, y revocación al cesar — se atienden mediante cuentas por usuario, el magic code o la credencial emitida por el IdP como segundo factor, y el desaprovisionamiento impulsado por SCIM.
Los controles del Anexo A.9 de ISO 27001 sobre política de control de acceso, registro de usuarios y acceso privilegiado se atienden mediante definiciones de rol documentadas, registro restringido al alcance de la organización y limitado a dominios verificados cuando se solicita, y la separación explícita de roles org_admin / estudiante dentro de cada tenant. Para las organizaciones sujetas a la sección 8 de PCI DSS, el control relevante es que nunca almacenamos datos de tarjetahabiente ni autenticamos a tarjetahabientes contra la plataforma; SecureCodingHub es un entorno de formación, no un entorno de pagos, por lo que la superficie a la que aplica PCI es intencionadamente estrecha.
Nada de lo anterior debe leerse como sustituto de su propia evaluación. Los paquetes de evidencia, incluida la lista de subprocesadores, los diagramas de flujo de datos y la postura actual de auditoría, están disponibles bajo petición en security@securecodinghub.com.
Qué cambia cuando se activa SSO
Activar SSO no es solo cambiar una pantalla de inicio de sesión por otra — cambia varios comportamientos en tiempo de ejecución que los equipos de seguridad deben comprender antes del despliegue. Una vez que su organización está conectada a un proveedor de identidad, la ruta local de magic code deja de ofrecerse a los usuarios cuyo correo coincida con su dominio verificado. Se les redirige al IdP. Este es el valor por defecto correcto, pero significa que la recuperación durante una caída del IdP pasa íntegramente a su equipo de TI en lugar de al soporte de SecureCodingHub. Recomendamos documentar internamente esa ruta de escalada antes de activar SSO para una base de usuarios grande.
El comportamiento de bloqueo también cambia: los intentos fallidos limitados por tasa en la ruta local de magic code dejan de aplicarse al mismo usuario una vez que SSO está en vigor, porque toda la validación de credenciales ocurre en el IdP. La política de bloqueo se rige entonces por la configuración de su IdP, no por los valores por defecto de SecureCodingHub. Las entradas del registro de auditoría escritas por las mutaciones que el usuario realiza tras iniciar sesión siguen llevando el correo del usuario y el rol org_admin / learner; la plataforma actualmente no almacena el método de autenticación del lado del IdP (por ejemplo, si MFA se satisfizo en el IdP) en la fila de auditoría, por lo que para ese nivel de detalle correlacionaría contra el flujo de registros de su propio proveedor de identidad central.