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.
-
Ve a
http://localhost:4321/_emdash/admin -
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
-
Haz clic en Create Site para registrar tu passkey
-
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
-
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:
-
Visita
/_emdash/admin -
Si no has iniciado sesión, verás la página de login
-
Haz clic en Sign in para autenticarte
-
El navegador solicita tu passkey (biometría, PIN o security key)
-
Tras la verificación, se te redirige al panel de administración
Respaldo con magic link
Si no puedes usar tu passkey (p. ej., dispositivo perdido), los magic links ofrecen una alternativa. Requiere tener el correo configurado.
-
En la página de login, haz clic en Sign in with email
-
Introduce tu correo
-
Revisa tu bandeja de entrada en busca del enlace de acceso
-
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:
| Role | Level | Description |
|---|---|---|
| Subscriber | 10 | Solo lectura |
| Contributor | 20 | Crear contenido (requiere aprobación) |
| Author | 30 | Crear/editar/publicar el propio contenido |
| Editor | 40 | Gestionar todo el contenido |
| Admin | 50 | Acceso 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:
-
Ve a Settings > Users
-
Haz clic en Invite User
-
Introduce el correo del usuario y selecciona un rol
-
Haz clic en Send Invite
-
El usuario recibe un correo con el enlace de invitación
-
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:
- Pide a otro administrador un magic link (requiere correo configurado)
- Usa el magic link para iniciar sesión
- 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
- Crea una aplicación de Cloudflare Access para tu sitio EmDash
- Anota el Application Audience (AUD) Tag en la configuración de la aplicación
- 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
| Option | Type | Default | Description |
|---|---|---|---|
teamDomain | string | required | Your Access team domain (e.g., myteam.cloudflareaccess.com) |
audience | string | required | Application Audience (AUD) tag from Access settings |
autoProvision | boolean | true | Create EmDash users on first Access login |
defaultRole | number | 30 | Role for users not matching any group (30 = Author) |
syncRoles | boolean | false | Update role on each login based on IdP groups |
roleMapping | object | — | Map IdP group names to role levels |
audienceEnvVar | string | "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
- El usuario visita
/_emdash/admin - Cloudflare Access intercepta y redirige a tu IdP
- El usuario se autentica (SSO, MFA, etc.)
- Access coloca un JWT firmado en la petición
- 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