Autenticación

En esta página

EmDash usa autenticación con passkeys como método de inicio de sesión principal. Los passkeys resisten el phishing, no requieren contraseñas y funcionan entre dispositivos mediante el navegador o el gestor de contraseñas.

En despliegues con Cloudflare, puedes usar opcionalmente Cloudflare Access como proveedor de autenticación alternativo.

Cómo funciona

Los passkeys usan WebAuthn, un estándar web que crea credenciales de clave pública almacenadas en tu dispositivo o sincronizadas con el gestor de contraseñas. Al iniciar sesión, el dispositivo demuestra la posesión de la credencial sin enviar nunca una contraseña por la red.

Ventajas de la autenticación con passkeys:

  • Sin contraseñas que recordar o filtrar
  • Resistente al phishing — las credenciales quedan ligadas al dominio de tu sitio
  • Sincronización entre dispositivos — funciona con Llavero de iCloud, Google Password Manager, 1Password, etc.
  • Inicio de sesión rápido — un toque con biometría o PIN

Configuración del primer usuario

La primera vez que accedes al panel de administración, el asistente de configuración te guía para crear tu cuenta de administrador.

  1. Ve a http://localhost:4321/_emdash/admin

  2. Serás redirigido al asistente de configuración. Introduce:

    • Site Title — el nombre de tu sitio
    • Tagline — una breve descripción
    • Admin Email — tu dirección de correo
  3. Haz clic en Create Site para registrar tu passkey

  4. El navegador te pedirá crear un passkey:

    • En macOS: Touch ID, contraseña del dispositivo o security key
    • En Windows: Windows Hello o security key
    • En móvil: Face ID, huella o PIN
  5. Una vez registrado el passkey, inicias sesión y se te redirige al panel de administración.

Iniciar sesión

Tras la configuración, volver al panel de administración activa la autenticación con passkey:

  1. Visita /_emdash/admin

  2. Si no has iniciado sesión, verás la página de login

  3. Haz clic en Sign in para autenticarte

  4. El navegador solicita tu passkey (biometría, PIN o security key)

  5. Tras la verificación, se te redirige al panel de administración

Si no puedes usar tu passkey (p. ej., dispositivo perdido), los magic links ofrecen una alternativa. Requiere tener el correo configurado.

  1. En la página de login, haz clic en Sign in with email

  2. Introduce tu correo

  3. Revisa tu bandeja de entrada en busca del enlace de acceso

  4. Haz clic en el enlace para autenticarte (válido 15 minutos)

Inicio de sesión OAuth

EmDash admite OAuth con GitHub y Google cuando está configurado. Los usuarios pueden vincular cuentas tras el primer registro con passkey.

Consulta la guía de configuración para instrucciones de configuración.

Roles de usuario

EmDash usa control de acceso basado en roles con cinco niveles:

RoleLevelDescription
Subscriber10Solo lectura
Contributor20Crear contenido (requiere aprobación)
Author30Crear/editar/publicar el propio contenido
Editor40Gestionar todo el contenido
Admin50Acceso completo, incluida la configuración

Cada rol hereda los permisos de los niveles inferiores. El primer usuario siempre se crea como Admin.

Invitar usuarios

Los administradores pueden invitar usuarios nuevos desde el panel de administración:

  1. Ve a Settings > Users

  2. Haz clic en Invite User

  3. Introduce el correo del usuario y selecciona un rol

  4. Haz clic en Send Invite

  5. El usuario recibe un correo con el enlace de invitación

  6. Hace clic en el enlace y registra su passkey

Las invitaciones son válidas 7 días. Los administradores pueden reenviar o revocar invitaciones desde la página Users.

Gestionar passkeys

Los usuarios pueden gestionar sus passkeys desde la configuración de la cuenta:

  • Add passkey — registrar passkeys adicionales como copia de seguridad u otros dispositivos
  • Remove passkey — eliminar passkeys que ya no uses
  • Rename passkey — poner nombres descriptivos a los passkeys

Cada usuario puede tener hasta 10 passkeys registrados.

Auto-registro

Para sitios de equipo, puedes habilitar el auto-registro para dominios de correo concretos:

import { defineConfig } from "astro/config";
import emdash from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			auth: {
				selfSignup: {
					domains: ["example.com"],
					defaultRole: "contributor",
				},
			},
		}),
	],
});

Los usuarios con dominios de correo coincidentes pueden registrarse sin invitación. Recibirán un correo de verificación y registrarán un passkey para completar el registro.

Configuración de sesión

Las sesiones usan cookies HttpOnly seguras con valores predeterminados razonables:

emdash({
	auth: {
		session: {
			maxAge: 30 * 24 * 60 * 60, // 30 days (default)
			sliding: true, // Reset expiry on activity
		},
	},
});

Notas de seguridad

  • Los passkeys se almacenan como claves públicas — la clave privada no sale del dispositivo
  • La verificación del challenge evita ataques de repetición
  • Limitación de velocidad protege frente a fuerza bruta (5 intentos/minuto/IP)
  • Las sesiones son HttpOnly, Secure, SameSite=Lax para la seguridad de cookies
  • Los tokens de magic link se hashean con SHA-256 — no se guardan tokens en bruto

Solución de problemas

”No passkeys registered”

Si ves este error al iniciar sesión, es posible que tu passkey se haya eliminado del gestor de contraseñas. Pide a un administrador un magic link o una nueva invitación.

”Passkey authentication failed”

Suele indicar que el passkey se creó para otro dominio. Los passkeys están ligados al dominio: un passkey para localhost:4321 no funciona en example.com. Registra un passkey nuevo para cada dominio.

”Session expired”

Las sesiones duran 30 días por defecto con caducidad deslizante. Si cierras sesión de forma inesperada, borra cookies e inicia sesión de nuevo.

Perdí todos los passkeys

Si pierdes el acceso a todos los passkeys registrados:

  1. Pide a otro administrador un magic link (requiere correo configurado)
  2. Usa el magic link para iniciar sesión
  3. Registra un passkey nuevo en la configuración de la cuenta

Si eres el único administrador y el correo no está configurado, tendrás que restablecer la autenticación del sitio mediante la base de datos.

Cloudflare Access

Al desplegar en Cloudflare, puedes usar Cloudflare Access como proveedor de autenticación en lugar de passkeys. Access gestiona la autenticación en el edge con tu proveedor de identidad existente.

¿Por qué usar Cloudflare Access?

  • Single Sign-On — los usuarios se autentican con el IdP de tu empresa
  • Control de acceso centralizado — gestiona quién puede acceder al admin en el panel de Cloudflare
  • Sin gestión de passkeys — no hace falta registrar ni administrar passkeys
  • Roles basados en grupos — mapea grupos del IdP a roles de EmDash automáticamente

Configuración

  1. Crea una aplicación de Cloudflare Access para tu sitio EmDash
  2. Anota el Application Audience (AUD) Tag en la configuración de la aplicación
  3. Configura EmDash para usar Access:
import { defineConfig } from "astro/config";
import cloudflare from "@astrojs/cloudflare";
import emdash from "emdash/astro";
import { d1, access } from "@emdash-cms/cloudflare";

export default defineConfig({
	output: "server",
	adapter: cloudflare(),
	integrations: [
		emdash({
			database: d1({ binding: "DB" }),
			auth: access({
				teamDomain: "myteam.cloudflareaccess.com",
				audience: "abc123def456...", // From Access app settings
			}),
		}),
	],
});

Opciones de configuración

OptionTypeDefaultDescription
teamDomainstringrequiredYour Access team domain (e.g., myteam.cloudflareaccess.com)
audiencestringrequiredApplication Audience (AUD) tag from Access settings
autoProvisionbooleantrueCreate EmDash users on first Access login
defaultRolenumber30Role for users not matching any group (30 = Author)
syncRolesbooleanfalseUpdate role on each login based on IdP groups
roleMappingobjectMap IdP group names to role levels
audienceEnvVarstring"CF_ACCESS_AUDIENCE"Environment variable name for the audience tag (alternative to hardcoding)

Mapeo de roles

Mapea los grupos de tu IdP a roles de EmDash:

emdash({
	auth: access({
		teamDomain: "myteam.cloudflareaccess.com",
		audience: "abc123...",
		roleMapping: {
			Admins: 50, // Admin
			"Content Editors": 40, // Editor
			Writers: 30, // Author
		},
		defaultRole: 20, // Contributor for users not in any group
	}),
});

El primer grupo coincidente gana si un usuario pertenece a varios grupos. El primer usuario que accede al sitio siempre se convierte en Admin, independientemente de los grupos.

Comportamiento de sincronización de roles

Por defecto (syncRoles: false), el rol del usuario se fija en el primer inicio de sesión y no cambia después. Así los administradores pueden ajustar roles manualmente en EmDash.

Establece syncRoles: true si quieres que los grupos del IdP sean autoritativos: el rol se actualizará en cada inicio de sesión según los grupos actuales.

Cómo funciona

  1. El usuario visita /_emdash/admin
  2. Cloudflare Access intercepta y redirige a tu IdP
  3. El usuario se autentica (SSO, MFA, etc.)
  4. Access coloca un JWT firmado en la petición
  5. EmDash valida el JWT y crea/autentica al usuario

Funciones deshabilitadas

Con Access habilitado, no están disponibles:

  • Página de login (/_emdash/admin/login)
  • Registro y gestión de passkeys
  • Login OAuth
  • Login con magic link
  • Auto-registro
  • Invitaciones de usuario

La gestión de usuarios se hace por completo mediante las políticas de Cloudflare Access.

Solución de problemas

”No Access JWT present”

La petición llegó a EmDash sin JWT de Access. Significa:

  • Access no está configurado para proteger tu aplicación
  • La política de Access no coincide con las rutas de administración

Comprueba que tu aplicación de Access cubre /_emdash/admin/*.

”JWT audience mismatch”

El audience de tu configuración no coincide con el JWT. Verifica el Application Audience Tag en la configuración de Access.

”User not authorized”

El usuario se autenticó vía Access pero autoProvision es false y no existe en EmDash. Opciones:

  • Establecer autoProvision: true, o
  • Crear el usuario manualmente antes de que inicie sesión