Documentação
Better Auth
Como o Motoko Base gerencia autenticação com Better Auth — e-mail/senha, OAuth, sessões, rotas protegidas, verificação e gerenciamento de conta.
O Motoko Base usa Better Auth para autenticação. As sessões são armazenadas no PostgreSQL via o adapter Drizzle. Não há um serviço de auth separado — Postgres mais as variáveis de ambiente bastam para o desenvolvimento local.
As rotas da API de auth ficam montadas em /api/auth/*. O dashboard exige uma sessão verificada antes de renderizar.
O que vem pronto de fábrica
| Feature | Status | Notes |
|---|---|---|
| Email / password sign-up | Enabled | Verification required before dashboard access |
| Email / password sign-in | Enabled | Redirects unverified users to /verify-email |
| Google OAuth | Optional | Enabled when GOOGLE_* env vars are set |
| GitHub OAuth | Optional | Enabled when GITHUB_* env vars are set |
| Email verification | Required | Sent on sign-up; resend on sign-in if still unverified |
| Password reset | Enabled | Requires Resend (RESEND_API_KEY, EMAIL_FROM) |
| Change password | Enabled | Settings → Security; revokes other sessions |
| Sign out | Enabled | User menu in the dashboard header |
| Session management | Enabled | List and revoke sessions in Settings → Security |
| Account linking | Enabled | Google and GitHub link to the same user when trusted |
Os botões de login social permanecem desabilitados até que as credenciais OAuth sejam configuradas. Veja Configuração OAuth para o setup passo a passo de cada provedor.
E-mail e senha
Sign up (/sign-up) coleta nome, e-mail e senha. O Better Auth cria o usuário e envia um e-mail de verificação quando o Resend está configurado.
Como requireEmailVerification está ativo, o cadastro não faz login automático. Após o cadastro, eles veem uma tela “Check your email” e precisam verificar antes de acessar /dashboard.
Sign in (/sign-in) aceita e-mail e senha. Em caso de sucesso, o cliente redireciona para /dashboard. Se o e-mail não estiver verificado, o Better Auth retorna 403 EMAIL_NOT_VERIFIED e o formulário redireciona para /verify-email.
As regras de senha para cadastro e alteração de senha são validadas em src/features/dashboard/schemas/security.ts (MIN_PASSWORD_LENGTH = 8 por padrão).
OAuth do Google e GitHub
Ambos os provedores estão conectados em src/lib/auth/auth.ts e só são ativados quando as variáveis de ambiente estão presentes. O cliente usa authClient.signIn.social({ provider: "google" | "github" }) nos formulários de sign-in e sign-up.
Usuários OAuth costumam ser marcados como verificados pelo provedor. O account linking está habilitado para Google e GitHub para que um usuário social que retorna possa se vincular a uma conta de e-mail existente quando o Better Auth confia no provedor.
Setup completo do provedor: Configuração OAuth.
Sessões
As sessões ficam na tabela session (src/lib/db/schema/auth.ts). Cada sessão tem token, expiração, IP e user agent.
Leituras no servidor usam getCachedSession() de src/lib/auth/session.ts. Ela envolve auth.api.getSession() em React cache() para que layout, páginas e server actions da mesma requisição compartilhem uma única consulta.
Chamadas no cliente usam authClient de src/lib/auth/client.ts (cliente React do Better Auth).
Exemplo — verificar a sessão em um server component ou action:
import { getCachedSession } from "@/lib/auth/session";
const session = await getCachedSession();
if (!session?.user?.id) {
// not signed in
}Rotas protegidas
As rotas do dashboard em /dashboard são protegidas em duas camadas:
src/proxy.ts— gate no edge para/dashboarde/dashboard/*. Redireciona usuários não autenticados para/sign-ine não verificados para/verify-email.src/app/dashboard/layout.tsx— layout do servidor que repete as mesmas checagens antes de renderizar o shell.
Páginas individuais e server actions também chamam getCachedSession() e redirecionam ou retornam erros quando necessário. Esse padrão de defesa em profundidade mantém rotas de API e actions seguras mesmo se uma página esquecer de checar.
Para proteger uma nova rota, coloque-a sob src/app/dashboard/ (herda layout + proxy) ou chame getCachedSession() e redirecione manualmente.
Verificação de e-mail
A verificação é obrigatória para acesso ao dashboard.
| Step | What happens |
|---|---|
| Sign up | Better Auth sends a verification link via sendVerificationEmail |
| Click link | User is verified; they can sign in |
| Unverified sign-in | Redirect to /verify-email |
| Resend | /verify-email calls authClient.sendVerificationEmail |
A entrega de e-mail exige RESEND_API_KEY e EMAIL_FROM. Sem Resend, o app sobe, mas e-mails de verificação não são enviados — configure o e-mail antes de testar o cadastro localmente.
O conteúdo do e-mail de verificação fica em src/lib/email/templates/verification-email.tsx. O hook de envio está em src/lib/auth/auth.ts sob emailVerification.sendVerificationEmail.
Redefinição de senha
| Route | Purpose |
|---|---|
/forgot-password | Request a reset link |
/reset-password?token=… | Set a new password from the email link |
Fluxo:
- O usuário envia o e-mail em
/forgot-password - O cliente chama
authClient.requestPasswordResetcomredirectToapontando para/reset-password - O Better Auth envia o e-mail via
sendResetPasswordemauth.ts - O usuário abre o link e envia uma nova senha via
authClient.resetPassword
E-mails de reset exigem Resend. A página de forgot-password verifica a configuração de e-mail antes de enviar.
Alterar senha
Usuários autenticados alteram a senha em Settings → Security (/dashboard/settings/account/security).
A UI chama updatePasswordAction em src/features/dashboard/actions/security.ts, que usa auth.api.changePassword com revokeOtherSessions: true — todos os outros dispositivos são desconectados após uma alteração bem-sucedida.
Os limites de comprimento de senha vêm de src/features/dashboard/schemas/security.ts.
Sair
O logout é disparado pelo menu do usuário no dashboard. src/features/dashboard/components/dashboard-shell.tsx chama:
await authClient.signOut({
fetchOptions: {
onSuccess: () => {
router.push("/sign-in");
router.refresh();
},
},
});O contexto de usuário de Analytics e Sentry é limpo no logout no mesmo handler.
Gerenciamento de conta e sessões
Profile (nome, avatar) — Settings → Profile (src/features/dashboard/components/settings/profile-settings-page.tsx).
Security (senha, sessões) — Settings → Security:
- Alterar senha
- Listar sessões ativas (navegador, SO, última atividade)
- Revogar sessões individuais
- Sair de todas as outras sessões
A lógica de servidor está em src/features/dashboard/actions/security.ts (updatePasswordAction, revokeSessionAction (sessions load via src/features/dashboard/lib/security-settings.ts)).
No cadastro, um e-mail de boas-vindas é enviado a partir do hook databaseHooks.user.create.after em auth.ts. Quando a cobrança Polar está configurada, o plugin Polar do Better Auth cria um cliente de cobrança no cadastro (src/lib/billing/providers/polar/auth-plugin.ts).
Onde eu mudo isso?
O Motoko Base divide a auth entre infraestrutura de servidor (src/lib/auth/), páginas de auth (src/app/…) e configurações de conta (src/features/dashboard/components/settings/). Não há uma pasta src/features/auth/ separada — a UI de auth vive nas rotas de app; o gerenciamento de conta vive em settings.
src/lib/auth/ — núcleo de auth no servidor
| File | Change this when you want to… |
|---|---|
auth.ts | Enable/disable providers, toggle verification, customize email hooks, add Better Auth plugins, change account linking |
session.ts | Adjust how server components read the session (getCachedSession) |
client.ts | Configure the browser auth client (base URL is inferred automatically) |
social.ts | Change how Google/GitHub “configured” checks work |
safe-client-error.ts | Edit user-facing error messages for sign-in, sign-up, OAuth |
O handler catch-all da API é src/app/api/auth/[...all]/route.ts — você raramente precisa editá-lo.
Tabelas do banco: src/lib/db/schema/auth.ts (user, session, account, verification).
Páginas de auth — sign-in, sign-up, recuperação
| Path | Change this when you want to… |
|---|---|
src/app/sign-in/ | Sign-in form behavior, post-login redirect, OAuth handlers |
src/app/sign-up/ | Sign-up form, pending-verification UI |
src/app/verify-email/ | Resend verification UX |
src/app/forgot-password/ | Forgot-password form |
src/app/reset-password/ | Reset-password form |
src/components/ui/auth-section-3.tsx | Shared auth layout (fields, social buttons, styling) |
As páginas de sign-in e sign-up passam googleEnabled / githubEnabled de isGoogleAuthConfigured() e isGitHubAuthConfigured() para que os botões se desabilitem automaticamente quando o OAuth não está configurado.
src/features/dashboard/components/settings/ — conta e sessões
| File | Change this when you want to… |
|---|---|
actions.ts | Password change, session list/revoke server actions |
config.ts | Password length limits, name length limits |
components/security-settings-page.tsx | Security UI (password form, session list) |
components/profile-settings-page.tsx | Profile name and avatar |
Rota: src/app/dashboard/settings/account/security/page.tsx carrega as sessões no servidor e renderiza SecuritySettingsPage.
Proteção de rotas
| File | Change this when you want to… |
|---|---|
src/proxy.ts | Edge redirects for /dashboard (session + verification gate) |
src/app/dashboard/layout.tsx | Dashboard shell gate and user bootstrap |
E-mail transacional (relacionado a auth)
| File | Change this when you want to… |
|---|---|
src/lib/email/index.ts | Verification, reset, welcome send functions |
src/lib/email/templates/verification-email.tsx | Verification email content |
src/lib/email/templates/password-reset-email.tsx | Reset email content |
src/lib/email/templates/welcome-email.tsx | Welcome email content |
src/lib/email/templates/shared.tsx | Email brand name and layout |
Variáveis de ambiente para auth: veja Variáveis de ambiente.
Próximos passos
Configuração OAuth — Configuração passo a passo do Google e GitHub.
Variáveis de ambiente — Referência completa de env, incluindo BETTER_AUTH_* e chaves OAuth.