Autenticação

Nesta página

O EmDash usa autenticação por passkey como método principal de login. As passkeys são resistentes a phishing, não requerem palavras-passe e funcionam entre dispositivos através do browser ou gestor de palavras-passe.

Para implantações na Cloudflare, pode opcionalmente usar o Cloudflare Access como fornecedor de autenticação alternativo.

Como funciona

As passkeys usam WebAuthn, um padrão web que cria credenciais de chave pública armazenadas no seu dispositivo ou sincronizadas pelo gestor de palavras-passe. Ao iniciar sessão, o dispositivo comprova a posse da credencial sem nunca enviar uma palavra-passe pela rede.

Benefícios da autenticação por passkey:

  • Sem palavras-passe para memorizar ou expor
  • Resistente a phishing — as credenciais estão vinculadas ao domínio do site
  • Sincronização entre dispositivos — funciona com iCloud Keychain, Google Password Manager, 1Password, etc.
  • Login rápido — um toque com biometria ou PIN

Configuração do primeiro utilizador

Na primeira vez que acede ao painel de administração, o Assistente de Configuração guia-o na criação da conta de admin.

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

  2. Será redirecionado para o Assistente de Configuração. Introduza:

    • Site Title — O nome do site
    • Tagline — Uma breve descrição
    • Admin Email — O seu endereço de email
  3. Clique em Create Site para registar a passkey

  4. O browser pedirá que crie uma passkey:

    • No macOS: Touch ID, palavra-passe do dispositivo ou chave de segurança
    • No Windows: Windows Hello ou chave de segurança
    • No telemóvel: Face ID, impressão digital ou PIN
  5. Quando a passkey estiver registada, fica autenticado e é redirecionado para o painel de administração.

Iniciar sessão

Após a configuração, regressar ao painel de administração aciona a autenticação por passkey:

  1. Visite /_emdash/admin

  2. Se não tiver sessão iniciada, verá a página de login

  3. Clique em Sign in para se autenticar

  4. O browser pede a passkey (biometria, PIN ou chave de segurança)

  5. Após verificação, é redirecionado para o painel de administração

Se não conseguir usar a passkey (ex.: dispositivo perdido), os magic links oferecem uma alternativa. Requer configuração de email.

  1. Na página de login, clique em Sign in with email

  2. Introduza o endereço de email

  3. Verifique a caixa de entrada para encontrar o link de login

  4. Clique no link para se autenticar (válido por 15 minutos)

Login OAuth

O EmDash suporta login OAuth com GitHub e Google quando configurado. Os utilizadores podem associar as contas após a configuração inicial da passkey.

Consulte o guia de configuração para instruções.

Funções de utilizador

O EmDash usa controlo de acesso baseado em funções com cinco níveis:

FunçãoNívelDescrição
Subscriber10Acesso apenas de leitura
Contributor20Criar conteúdo (precisa de aprovação)
Author30Criar/editar/publicar conteúdo próprio
Editor40Gerir todo o conteúdo
Admin50Acesso total incluindo configurações

Cada função herda as permissões de todos os níveis inferiores. O primeiro utilizador é sempre criado como Admin.

Convidar utilizadores

Os admins podem convidar novos utilizadores pelo painel de administração:

  1. Vá a Settings > Users

  2. Clique em Invite User

  3. Introduza o email do utilizador e selecione uma função

  4. Clique em Send Invite

  5. O utilizador recebe um email com um link de convite

  6. Ao clicar no link, regista a passkey

Os convites são válidos por 7 dias. Os admins podem reenviar ou revogar convites na página de Utilizadores.

Gerir passkeys

Os utilizadores podem gerir as passkeys nas definições da conta:

  • Adicionar passkey — Registar passkeys adicionais para backup ou outros dispositivos
  • Remover passkey — Eliminar passkeys que já não usa
  • Renomear passkey — Dar nomes descritivos às passkeys

Cada utilizador pode ter até 10 passkeys registadas.

Registo automático

Para sites de equipa, pode ativar o registo automático para domínios de email específicos:

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

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

Utilizadores com domínios de email correspondentes podem registar-se sem convite. Recebem um email de verificação e registam uma passkey para concluir o registo.

Configuração de sessão

As sessões usam cookies HttpOnly seguros com valores predefinidos sensatos:

emdash({
	auth: {
		session: {
			maxAge: 30 * 24 * 60 * 60, // 30 dias (predefinição)
			sliding: true, // Renovar expiração com atividade
		},
	},
});

Notas de segurança

  • As passkeys são armazenadas como chaves públicas — a chave privada nunca sai do dispositivo
  • Verificação de desafio previne ataques de repetição
  • Limitação de taxa protege contra força bruta (5 tentativas/minuto/IP)
  • As sessões são HttpOnly, Secure, SameSite=Lax para segurança dos cookies
  • Os tokens de magic link têm hash SHA-256 — os tokens em bruto nunca são guardados

Resolução de problemas

”No passkeys registered”

Se vir este erro ao iniciar sessão, a passkey pode ter sido eliminada do gestor de palavras-passe. Peça a um admin para enviar um magic link ou novo convite.

”Passkey authentication failed”

Normalmente significa que a passkey foi criada para um domínio diferente. As passkeys estão vinculadas ao domínio — uma passkey para localhost:4321 não funciona em example.com. Registe uma nova passkey para cada domínio.

”Session expired”

As sessões duram 30 dias por predefinição com expiração deslizante. Se a sessão terminar inesperadamente, limpe os cookies e inicie sessão novamente.

Perda de todas as passkeys

Se perdeu o acesso a todas as passkeys registadas:

  1. Peça a outro admin para enviar um magic link (requer configuração de email)
  2. Use o magic link para iniciar sessão
  3. Registe uma nova passkey nas definições da conta

Se for o único admin e o email não estiver configurado, terá de repor a autenticação do site através da base de dados.

Cloudflare Access

Ao implementar na Cloudflare, pode usar o Cloudflare Access como fornecedor de autenticação em vez das passkeys. O Access trata a autenticação na periferia usando o seu fornecedor de identidade existente.

Porquê usar o Cloudflare Access?

  • Single Sign-On — Os utilizadores autenticam-se com o IdP da empresa
  • Controlo de acesso centralizado — Gerir quem pode aceder ao admin no painel da Cloudflare
  • Sem gestão de passkeys — Sem necessidade de registar ou gerir passkeys
  • Funções baseadas em grupos — Mapear grupos do IdP para funções EmDash automaticamente

Configuração

  1. Crie uma aplicação Cloudflare Access para o seu site EmDash
  2. Anote a Application Audience (AUD) Tag das definições da aplicação
  3. Configure o EmDash para usar o 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...", // Das definições da aplicação Access
			}),
		}),
	],
});

Opções de configuração

OpçãoTipoPredefiniçãoDescrição
teamDomainstringobrigatórioO domínio da equipa Access (ex.: myteam.cloudflareaccess.com)
audiencestringobrigatórioApplication Audience (AUD) Tag das definições do Access
autoProvisionbooleantrueCriar utilizadores EmDash no primeiro login via Access
defaultRolenumber30Função para utilizadores sem correspondência de grupo (30 = Author)
syncRolesbooleanfalseAtualizar função em cada login com base nos grupos do IdP
roleMappingobjectMapear nomes de grupos do IdP para níveis de função
audienceEnvVarstring"CF_ACCESS_AUDIENCE"Nome da variável de ambiente para a audience tag (alternativa a fixar no código)

Mapeamento de funções

Mapeie os grupos do IdP para funções EmDash:

emdash({
	auth: access({
		teamDomain: "myteam.cloudflareaccess.com",
		audience: "abc123...",
		roleMapping: {
			Admins: 50, // Admin
			"Content Editors": 40, // Editor
			Writers: 30, // Author
		},
		defaultRole: 20, // Contributor para utilizadores fora de qualquer grupo
	}),
});

O primeiro grupo correspondente ganha se o utilizador pertencer a vários grupos. O primeiro utilizador a aceder ao site torna-se sempre Admin, independentemente dos grupos.

Comportamento de sincronização de funções

Por predefinição (syncRoles: false), a função do utilizador é definida no primeiro login e não muda depois. Isto permite que os admins ajustem funções manualmente no EmDash.

Defina syncRoles: true se quiser que os grupos do IdP sejam autoritários — a função do utilizador será atualizada em cada login com base nos grupos atuais.

Como funciona

  1. O utilizador visita /_emdash/admin
  2. O Cloudflare Access interceta e redireciona para o IdP
  3. O utilizador autentica-se (SSO, MFA, etc.)
  4. O Access define um JWT assinado no pedido
  5. O EmDash valida o JWT e cria/autentica o utilizador

Funcionalidades desativadas

Quando o Access está ativado, estas funcionalidades ficam indisponíveis:

  • Página de login (/_emdash/admin/login)
  • Registo e gestão de passkeys
  • Login OAuth
  • Login por magic link
  • Registo automático
  • Convites de utilizadores

A gestão de utilizadores é feita inteiramente através das políticas do Cloudflare Access.

Resolução de problemas

”No Access JWT present”

O pedido chegou ao EmDash sem um JWT do Access. Isto significa:

  • O Access não está configurado para proteger a aplicação
  • A política do Access não corresponde às rotas do admin

Verifique que a aplicação Access cobre /_emdash/admin/*.

”JWT audience mismatch”

A audience na configuração não corresponde ao JWT. Verifique novamente a Application Audience Tag nas definições da aplicação Access.

”User not authorized”

O utilizador autenticou-se via Access mas autoProvision é false e não existe no EmDash. Opções:

  • Definir autoProvision: true, ou
  • Criar o utilizador manualmente antes do primeiro login