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.

Abrir emChatGPT (abre em uma nova aba)Claude (abre em uma nova aba)Cursor (abre em uma nova aba)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

FeatureStatusNotes
Email / password sign-upEnabledVerification required before dashboard access
Email / password sign-inEnabledRedirects unverified users to /verify-email
Google OAuthOptionalEnabled when GOOGLE_* env vars are set
GitHub OAuthOptionalEnabled when GITHUB_* env vars are set
Email verificationRequiredSent on sign-up; resend on sign-in if still unverified
Password resetEnabledRequires Resend (RESEND_API_KEY, EMAIL_FROM)
Change passwordEnabledSettings → Security; revokes other sessions
Sign outEnabledUser menu in the dashboard header
Session managementEnabledList and revoke sessions in Settings → Security
Account linkingEnabledGoogle 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:

  1. src/proxy.ts — gate no edge para /dashboard e /dashboard/*. Redireciona usuários não autenticados para /sign-in e não verificados para /verify-email.
  2. 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.

StepWhat happens
Sign upBetter Auth sends a verification link via sendVerificationEmail
Click linkUser is verified; they can sign in
Unverified sign-inRedirect 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

RoutePurpose
/forgot-passwordRequest a reset link
/reset-password?token=…Set a new password from the email link

Fluxo:

  1. O usuário envia o e-mail em /forgot-password
  2. O cliente chama authClient.requestPasswordReset com redirectTo apontando para /reset-password
  3. O Better Auth envia o e-mail via sendResetPassword em auth.ts
  4. 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

FileChange this when you want to…
auth.tsEnable/disable providers, toggle verification, customize email hooks, add Better Auth plugins, change account linking
session.tsAdjust how server components read the session (getCachedSession)
client.tsConfigure the browser auth client (base URL is inferred automatically)
social.tsChange how Google/GitHub “configured” checks work
safe-client-error.tsEdit 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

PathChange 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.tsxShared 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

FileChange this when you want to…
actions.tsPassword change, session list/revoke server actions
config.tsPassword length limits, name length limits
components/security-settings-page.tsxSecurity UI (password form, session list)
components/profile-settings-page.tsxProfile 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

FileChange this when you want to…
src/proxy.tsEdge redirects for /dashboard (session + verification gate)
src/app/dashboard/layout.tsxDashboard shell gate and user bootstrap

E-mail transacional (relacionado a auth)

FileChange this when you want to…
src/lib/email/index.tsVerification, reset, welcome send functions
src/lib/email/templates/verification-email.tsxVerification email content
src/lib/email/templates/password-reset-email.tsxReset email content
src/lib/email/templates/welcome-email.tsxWelcome email content
src/lib/email/templates/shared.tsxEmail 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.