El paquete @emdash-cms/auth-atproto añade una opción de inicio de sesión con cuenta Atmosphere a EmDash. Una cuenta Atmosphere es una identidad portable propiedad del usuario usada en Bluesky y otras apps en la red AT Protocol. Los usuarios inician sesión con su handle (ej. alice.bsky.social) y se autentican en su propio proveedor — EmDash nunca ve una contraseña.
Es una buena opción cuando:
- Tus colaboradores ya tienen una cuenta Atmosphere.
- Quieres controlar el acceso con un dominio de la organización (
*.tuempresa.com) sin gestionar apps OAuth ni invitaciones. - Estás construyendo algo que forma parte de la Atmosphere más amplia y quieres identidad consistente con el resto de tu stack.
Instalar
Instala el paquete del proveedor:
pnpm add @emdash-cms/auth-atproto
Añade el proveedor a la integración EmDash:
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { atproto } from "@emdash-cms/auth-atproto";
export default defineConfig({
server: {
host: "127.0.0.1", // requerido para desarrollo local; ver abajo
},
integrations: [
emdash({
authProviders: [atproto()],
}),
],
});
Eso es suficiente para poner Sign in with Atmosphere en la página de inicio de sesión y el asistente de configuración. Sin lista de permitidos configurada, el primer usuario se convierte en Admin y el registro automático se cierra para todos después — ver listas de permitidos para abrirlo.
El proveedor es un cliente OAuth público y sirve su propio documento de metadatos en /.well-known/atproto-client-metadata.json, así que funciona solo con la configuración anterior — sin variables de entorno, secret de cliente ni registro de app OAuth.
Configurar acceso
El proveedor atproto() acepta una lista de permitidos y un rol por defecto:
atproto({
allowedDIDs: ["did:plc:abc123..."],
allowedHandles: ["*.example.com", "alice.bsky.social"],
defaultRole: 30, // Autor
});
| Opción | Tipo | Defecto | Descripción |
|---|---|---|---|
allowedDIDs | string[] | ninguno | Lista de DIDs permitidos exactos. |
allowedHandles | string[] | ninguno | Lista de handles permitidos. Soporta wildcards iniciales (*.example.com). |
defaultRole | number | 10 (Suscriptor) | Rol asignado a usuarios permitidos después del primero. El primer usuario siempre es Admin. |
La escalera completa de roles está documentada en la guía de autenticación principal.
Listas de permitidos
Si ni allowedDIDs ni allowedHandles están configurados, solo el primer usuario puede registrarse. Las cuentas ya vinculadas a un usuario EmDash pueden seguir iniciando sesión, mientras que una cuenta nueva es rechazada con signup_not_allowed.
Cuando al menos una lista de permitidos está configurada, cada inicio de sesión debe coincidir con ella, incluyendo inicios de sesión para usuarios existentes. Eliminar la DID y el handle de un usuario existente de las listas configuradas impide que esa cuenta inicie sesión. Un usuario es admitido si cualquiera de las listas coincide:
- Coincidencia de DID. El identificador estable de la cuenta del usuario coincide exactamente con un valor en
allowedDIDs. - Coincidencia de handle. El handle del usuario coincide con una entrada en
allowedHandles, exactamente o mediante un patrón wildcard inicial (*.example.comcoincide conalice.example.comybob.team.example.com).
Las listas de handles permitidos son seguras aunque los handles sean mutables. Antes de admitir a un usuario mediante coincidencia de handle, EmDash resuelve independientemente el registro DNS/HTTP del handle y verifica que apunta a la misma DID que el proveedor reclama. Un proveedor que se comporta mal no puede simplemente afirmar que posee tu.tuempresa.com.
Rol por defecto
Los usuarios permitidos llegan con el rol que estableces en defaultRole. Solo el primer usuario — el que completa la configuración — es forzado a Admin. No hay mapeo de grupo/rol para cuentas Atmosphere; si necesitas roles más granulares, cambia el rol del usuario desde Configuración → Usuarios después de que haya iniciado sesión una vez.
Configurar el primer usuario
Cuando inicias un sitio nuevo con el proveedor Atmosphere configurado, el asistente de configuración lo ofrece como opción para crear la cuenta de admin inicial.
-
Visita
/_emdash/admin. En Set up your site, ingresa el título del sitio y tagline opcional, luego continúa. -
En Create your account, ingresa la dirección de email y nombre opcional para almacenar en el usuario EmDash.
-
En Secure your account, elige Atmosphere, ingresa tu handle (por ejemplo,
alice.bsky.social) y continúa. -
Tu proveedor de cuenta abre su página de autorización. Inicia sesión usando el método que ese proveedor soporta y aprueba la solicitud.
-
El proveedor te redirige a EmDash. EmDash crea el primer usuario como Admin, almacena el email del paso 2, establece una sesión EmDash y abre el panel de control.
Los inicios de sesión posteriores comienzan con el handle, continúan en el proveedor de cuenta y retornan con una sesión EmDash. El estado OAuth y tokens del proveedor se almacenan por separado de esa sesión EmDash para que el callback OAuth pueda completarse y el proveedor pueda actualizar su propia sesión.
Desarrollo local
El perfil OAuth del AT Protocol requiere que las URIs de redirección de loopback usen un literal de IP (127.0.0.1 o [::1]), no localhost. EmDash reescribe transparentemente ://localhost a ://127.0.0.1 al generar la URI de redirección, pero eso significa que tu sesión de desarrollo necesita empezar en 127.0.0.1 también — de lo contrario la cookie de sesión establecida en localhost no será visible después de que la redirección te lleve a 127.0.0.1.
El servidor de desarrollo de Astro usa Vite, que se vincula a localhost por defecto. Establece la opción server.host de Astro a la IP de loopback:
export default defineConfig({
server: {
host: "127.0.0.1",
},
// ...
});
Luego abre http://127.0.0.1:4321/_emdash/admin para todo el flujo.
Producción
La misma configuración funciona en producción. El proveedor sirve sus propios metadatos de cliente en:
https://tu-sitio.example.com/.well-known/atproto-client-metadata.json
Los servidores de autorización obtienen esta URL durante el inicio de sesión para verificar la URI de redirección del cliente. Asegúrate de que la URL del sitio de tu despliegue sea accesible en internet público por HTTPS — los despliegues solo internos detrás de un VPN no podrán completar un inicio de sesión porque el servidor de autorización del usuario no puede obtener el documento de metadatos.
Si ejecutas EmDash detrás de un proxy inverso que termina TLS, establece siteUrl para que EmDash construya la URI de redirección correcta. Sin esto, las solicitudes parecen http://host-interno:4321 y los metadatos no coincidirán con lo que ve el servidor de autenticación.
Solución de problemas
”Account is not in the allowlist”
El handle o DID con el que iniciaste sesión no está en allowedDIDs / allowedHandles. Verifica el patrón wildcard (debe empezar con *.) y recuerda que la coincidencia de handle se verifica contra DNS/HTTP — si el registro DID del handle no resuelve actualmente a la misma DID que el proveedor devolvió, la coincidencia se rechaza.
”Self-signup is not allowed”
Llegaste al callback exitosamente, pero no hay lista de permitidos configurada y no eres el primer usuario. Añade la DID de la cuenta a allowedDIDs o su handle verificado a allowedHandles. Una invitación por email no vincula una DID de Atmosphere a un usuario EmDash.
El inicio de sesión redirige a la página de inicio de sesión sin error
Esto es casi siempre el problema de cookie de loopback descrito en Desarrollo local. Abre el admin en http://127.0.0.1:4321 (después de establecer server.host: "127.0.0.1") e intenta de nuevo.
La resolución de handle falla para un handle auto-hospedado
El proveedor verifica handles mediante DNS-sobre-HTTPS (endpoint DoH de Cloudflare) y una búsqueda HTTP /.well-known/atproto-did en paralelo. Los handles auto-hospedados necesitan al menos uno de:
- Un registro DNS TXT
_atproto.<handle>que contengadid=<tu-did>, o - Un archivo
https://<handle>/.well-known/atproto-didque contenga la DID.
Si ambos métodos fallan, la coincidencia de handle se rechaza incluso cuando la cuenta subyacente es válida. Las DIDs en allowedDIDs no se ven afectadas — se comparan directamente.