Configuração de identidade antes do código
Voltar para blog

Configuração de identidade antes do código

07/06/2026 · 8 min · Infraestrutura

A camada prévia ao código: provisionando a identidade do app no provedor#

Em qualquer implementação de autenticação OAuth 2.0, existe uma camada prévia ao código que precisa ser provisionada corretamente: a identidade do aplicativo junto ao provedor de identidade (neste caso, o Google). Sem essa etapa, qualquer biblioteca de autenticação (NextAuth.js, Auth.js v5, Passport.js, Lucia) falha com erros de redirect_uri_mismatch ou access_denied antes de qualquer linha de código do backend ser executada.

O OAuth 2.0 funciona sob o protocolo de delegação de autorização. O fluxo simplificado:

Usuário clica "Login com Google"
    │
    ▼
App redireciona para accounts.google.com/o/oauth2/v2/auth
  ?client_id=SEU_CLIENT_ID
  &redirect_uri=https://seuapp.com/api/auth/callback/google
  &scope=openid profile email
  &response_type=code
    │
    ▼
Google valida:
  1. SEU_CLIENT_ID existe?
  2. redirect_uri está na lista de URIs autorizadas?
  3. Os scopes solicitados estão aprovados?
    │
  ✅ Tudo válido → Google autentica o usuário e retorna o authorization code
  ❌ Qualquer validação falha → error: redirect_uri_mismatch / access_denied

O objetivo da configuração no Google Cloud Console: registrar o aplicativo, definir quais dados serão acessados e autorizar explicitamente quais origens e URIs de callback são legítimas.


1) Introdução e delegação de autoridade#

O protocolo OAuth 2.0 é o padrão de mercado para delegação segura de autoridade na Web. Ele permite que uma aplicação cliente solicite acesso restrito a dados do perfil de um usuário (hospedados em um Provedor de Identidade, como o Google) sem que o usuário precise compartilhar suas credenciais primárias (senhas) com a aplicação. Em termos práticos de arquitetura de software, o sucesso desse ecossistema depende de uma configuração precisa na console do provedor. A menor discrepância em nomes de domínios, caminhos de callback ou permissões de escopo causa falhas catastróficas que interrompem o fluxo de onboarding dos usuários.


2) Provisionamento do projeto no Google cloud console#

O Google Cloud organiza todos os recursos de desenvolvimento e APIs em projetos isolados. É uma melhor prática de infraestrutura isolar ambientes corporativos para que chaves de homologação ou teste não compartilhem os mesmos privilégios de produção.

Para instanciar o ambiente:

  1. Acesse a console administrativa do Google Cloud.
  2. Na barra de navegação superior, clique no seletor de projetos e escolha Novo Projeto (New Project).
  3. Preencha o nome descritivo (ex: meuapp-producao-auth) e associe a uma organização do Google Workspace se aplicável.
  4. Clique em Criar (Create) e aguarde o término do provisionamento interno do contêiner.

A tela de consentimento (OAuth Consent Screen) é a interface que o usuário final visualiza quando concorda em compartilhar seus dados com seu sistema.

3.1 tipo de usuário (user type)#

3.2 escopos mínimos (scopes)#

Adicione exatamente os três escopos essenciais recomendados pelo padrão OpenID Connect (OIDC) para identificação do usuário:

3.3 test users#

Enquanto o projeto estiver no modo Testing (não verificado), apenas e-mails explicitamente inseridos na lista de Test Users conseguirão efetuar o login. Contas externas não listadas receberão um erro HTTP 403 access_denied.


4) Criação e configuração das credenciais#

Acesse o menu Credentials -> Create Credentials -> OAuth client ID.

4.1 origens javascript autorizadas (authorized javascript origins)#

Domínio de origem que inicia a requisição HTTP.

4.2 URIs de redirecionamento autorizadas (authorized redirect URIs)#

Caminho completo do endpoint (callback) que processará o código de autorização.


5) Isolamento de segredos e configuração de ambiente#

Os dados gerados pelo Google Cloud consistem em um Client ID (identificador público) e um Client Secret (segredo criptográfico privado). O vazamento do Client Secret permite que atacantes falsifiquem requisições em nome do seu aplicativo.

  1. Armazene as credenciais exclusivamente no arquivo de variáveis locais .env.local:
GOOGLE_CLIENT_ID=123456789-abcdef.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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er_value_xxxxxx
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=gerado_com_openssl_rand_base64
  1. Certifique-se de que o arquivo .gitignore está bloqueando o envio de arquivos de variáveis para o repositório git:
# .gitignore
.env
.env.local
.env.*.local
*.env

6) Verificação pós-configuração de identidade#

Após registrar as chaves na console do Google Cloud, é essencial realizar testes para validar a consistência e a validade sintática do Client ID gerado:

  1. Teste o status e a integridade da chave do Client ID enviando uma chamada direta para o validador público de tokens do Google:
curl -s "https://oauth2.googleapis.com/tokeninfo?id_token=TESTE" | jq .
  1. Valide o fluxo simulando o acesso local ao endpoint de autenticação do seu servidor Next.js:

7) Configuração de refresh tokens#

Para manter a experiência do usuário fluida e evitar desconexões frequentes a cada expiração do access token, configure o NextAuth para solicitar um refresh token durante o ciclo inicial de consentimento.

No arquivo src/auth.ts, ajuste o provider do Google adicionando os parâmetros de autorização offline e consent:

import NextAuth from "next-auth"
import Google from "next-auth/providers/google"

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      authorization: {
        params: {
          access_type: "offline",  // Exige refresh token do Google
          prompt: "consent",       // Força exibição da tela para capturar refresh_token
        },
      },
    }),
  ],
  callbacks: {
    async jwt({ token, account }) {
      if (account) {
        token.accessToken = account.access_token
        token.refreshToken = account.refresh_token
        token.expiresAt = account.expires_at // Timestamp de expiracao em segundos
      }
      return token
    },
  },
})

8) Tratamento de expiração e renovação de tokens#

O access token emitido pelo Google expira por padrão em 3600 segundos (1 hora). Para garantir a persistência das sessões ativas sem forçar re-autenticação manual, verifique e renove o token de acesso no servidor utilizando o refresh token:

  1. Função de utilidade para checar a expiração do token e renovação dinâmica:
// Validar expiração do token baseado em data/hora
const isTokenExpired = (token: any) => {
  return Date.now() >= (token.expiresAt * 1000)
}

// Renovar access token com chamada de API ao Google OAuth2
const refreshAccessToken = async (token: any) => {
  try {
    const response = await fetch("https://oauth2.googleapis.com/token", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({
        client_id: process.env.GOOGLE_CLIENT_ID!,
        client_secret: process.env.GOOGLE_CLIENT_SECRET!,
        refresh_token: token.refreshToken,
        grant_type: "refresh_token",
      }),
    })
    
    const data = await response.json()
    
    if (!response.ok) throw data

    return {
      ...token,
      accessToken: data.access_token,
      expiresAt: Math.floor(Date.now() / 1000) + data.expires_in,
      // Se o Google não retornar um novo refresh_token, mantém o atual
      refreshToken: data.refresh_token ?? token.refreshToken, 
    }
  } catch (error) {
    console.error("Falha ao renovar o access token do Google:", error)
    return { ...token, error: "RefreshAccessTokenError" }
  }
}

9) Implementação de fluxo de logout seguro#

O encerramento de sessão deve limpar os vestígios locais da autenticação no NextAuth e opcionalmente guiar o usuário na remoção do token junto ao provedor de identidade.

Adicione o controle de encerramento seguro na interface do seu aplicativo de frontend:

import { signOut } from "next-auth/react"

// Estratégia 1: Logout local limpando cookies da aplicacao
const handleLocalLogout = () => {
  signOut({ redirect: true, callbackUrl: "/" })
}

// Estratégia 2: Logout combinado limpando sessao do Google
const handleGlobalLogout = () => {
  // Redireciona para o logout do Google e retorna ao site após a limpeza
  signOut({
    callbackUrl: "https://accounts.google.com/Logout",
  })
}

10) Políticas CORS e rate limiting no gateway#

As rotas da API de autenticação do Next.js devem ser protegidas contra ataques de força bruta, abuso de chamadas concorrentes e requisições maliciosas originadas em domínios não autorizados:

  1. Configure as diretivas de cabeçalhos de segurança CORS para a rota da API de autenticação no arquivo next.config.js:
module.exports = {
  async headers() {
    return [
      {
        source: "/api/auth/:path*",
        headers: [
          { key: "Access-Control-Allow-Origin", value: process.env.NEXTAUTH_URL || "*" },
          { key: "Access-Control-Allow-Methods", value: "GET, POST, OPTIONS" },
          { key: "Access-Control-Allow-Headers", value: "Content-Type, Authorization" },
        ],
      },
    ]
  },
}
  1. Implemente rate limiting básico baseado no endereço IP de origem no arquivo middleware.ts para blindar as tentativas de login:
import { NextResponse } from "next/server"
import type { NextRequest } from "next/request"

const rateLimitMap = new Map<string, number[]>()

export function middleware(request: NextRequest) {
  const ip = request.ip || "127.0.0.1"
  const now = Date.now()
  const windowMs = 15 * 60 * 1000 // Janela de 15 minutos
  const maxRequests = 20

  if (request.nextUrl.pathname.startsWith("/api/auth/signin")) {
    if (!rateLimitMap.has(ip)) {
      rateLimitMap.set(ip, [])
    }
    
    const requests = rateLimitMap.get(ip)!
    const recentRequests = requests.filter(time => time > now - windowMs)
    
    if (recentRequests.length >= maxRequests) {
      return NextResponse.json({ error: "Limite de tentativas excedido. Tente novamente mais tarde." }, { status: 429 })
    }
    
    recentRequests.push(now)
    rateLimitMap.set(ip, recentRequests)
  }
  
  return NextResponse.next()
}

11) Auditoria de SSL/TLS, domínio e política de privacidade#

Para o funcionamento correto do OAuth 2.0 em produção, todos os endpoints envolvidos devem rodar sob conexões HTTPS seguras com certificados digitais válidos e domínio validado.

  1. Teste o status SSL e verifique as datas de expiração do certificado digital do servidor principal da aplicação:
echo | openssl s_client -connect meudominio.com.br:443 2>/dev/null | openssl x509 -noout -dates
  1. Valide o status de verificação de propriedade do domínio consultando o registro TXT associado ao Google Cloud no DNS público:
dig TXT _google-domain-verification.meudominio.com.br +short
  1. Certifique-se de que a política de privacidade (exigência do console do Google para sair do modo Testing) está acessível publicamente via HTTPS:
curl -I https://meudominio.com.br/privacy

12) Logs de auditoria e rastreamento de autenticação#

Registrar eventos no ciclo de login auxilia na auditoria forense do comportamento do sistema e na detecção precoce de acessos suspeitos.

Implemente um callback de auditoria em src/auth.ts:

const logAuthAttempt = (email: string, success: boolean, provider: string) => {
  console.log(JSON.stringify({
    event: "oauth_auth_attempt",
    email,
    success,
    provider,
    timestamp: new Date().toISOString(),
  }))
}

// Dentro da configuracao do NextAuth:
callbacks: {
  async signIn({ user, account, profile }) {
    if (profile?.email) {
      logAuthAttempt(profile.email, true, account?.provider || "unknown")
    }
    return true
  }
}

13) Checklists de configuração e matriz de riscos#

13.1 checklist operacional de integração do Google oauth2#

Certifique-se de validar todos os itens listados antes do lançamento:

13.2 matriz de riscos de autenticação e severidade#

Risco / AmeaçaSeveridadeDescriçãoAção de Mitigação Técnica
Vazamento do SecretCríticaChave privada Client Secret exposta publicamente em repositórios Git públicos.Armazenamento de chaves em variáveis de ambiente seguras e restrições rígidas no .gitignore.
Bloqueio de ContasAltaUsuários não conseguem logar recebendo erro 403 access_denied em homologação.Adição manual de endereços de e-mail dos testadores na aba Test Users da console do Google Cloud.
Invalidação de CallbackAltaErro redirect_uri_mismatch impede o fluxo por discrepância de portas ou caminhos.Cadastro detalhado e correspondência binária exata das URIs de callback cadastradas.
Ataques de Força BrutaMédiaTentativas excessivas de requisições de login e inundações na API de callback.Configuração de middleware com Rate Limit ativo baseado em IP e janela de requisições de 15 minutos.
Falha de RenovaçãoMédiaO usuário é desconectado abruptamente após 1 hora devido ao access token do Google expirado.Configuração de parâmetros de acesso offline e renovação dinâmica automática usando refresh tokens.

Considerações práticas#

A integração do Google OAuth 2.0 com o NextAuth.js é mais do que a escrita de código de rotas; exige uma governança sólida de credenciais e segurança de rede. Ao isolar os segredos do repositório, monitorar o tempo de expiração dos tokens e auditar conexões seguras HTTPS de ponta a ponta, você constrói uma barreira de autenticação resiliente e em conformidade com as melhores práticas de cibersegurança do mercado.

Este artigo foi útil?

Deixe uma reação rápida para apoiar o conteúdo:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários