Magic Link
Autenticacao sem senha via token por email.
Como funciona
O Magic Link permite login sem senha. O fluxo e:
- Usuario informa seu email em
POST /api/auth/magic-link/send - Um token unico (nanoid, 32 caracteres) e gerado com expiracao
- Um link e criado:
http://localhost:3000/auth/verify?token=abc123... - O link e enviado por email (requer SMTP configurado)
- Usuario clica no link, que chama
GET /api/auth/magic-link/verify?token=abc123 - O token e validado e consumido (uso unico)
- Um JWT e gerado para o usuario
Arquivos gerados
O arquivo principal e magic-link.service.ts, compartilhado por todos os backends:
import { nanoid } from 'nanoid';
const EXPIRY_MINUTES = Number(process.env.MAGIC_LINK_EXPIRY_MINUTES) || 15;
const APP_URL = process.env.APP_URL || 'http://localhost:3000';
export function generateMagicLink(email: string): { token: string; url: string } {
const token = nanoid(32);
const expiresAt = new Date(Date.now() + EXPIRY_MINUTES * 60 * 1000);
tokens.set(token, { token, email, expiresAt });
const url = `${APP_URL}/auth/verify?token=${token}`;
return { token, url };
}
export function verifyMagicLinkToken(token: string): { valid: boolean; email?: string } {
const entry = tokens.get(token);
if (!entry) return { valid: false };
if (entry.expiresAt < new Date()) {
tokens.delete(token);
return { valid: false };
}
tokens.delete(token); // uso unico
return { valid: true, email: entry.email };
}
Alem do service, e gerado um controller (NestJS) ou router (Express/Fastify) com as rotas /send e /verify.
Dependencia de SMTP
Para que o magic link funcione em producao, voce precisa do servico de email (SMTP) habilitado. No modo de desenvolvimento, o link e logado no console.
# Variaveis de ambiente necessarias
MAGIC_LINK_EXPIRY_MINUTES=15
APP_URL=http://localhost:3000
# Se SMTP estiver habilitado:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=seu-email@gmail.com
SMTP_PASS=sua-app-password
Nota: Em desenvolvimento, o token e URL sao printados no console do servidor para teste rapido.
Armazenamento de tokens
Por padrao, os tokens sao armazenados em um Map em memoria. Em producao, voce deve migrar para:
- Redis — com TTL automatico (recomendado)
- Banco de dados — tabela/collection de tokens com campo
expiresAt