Voltar para Artigos
Back-end★ Destaque10 min de leitura

Autenticação Híbrida: JWT Tradicional e OAuth2 com Google

Veja como estruturar um sistema de autenticação sólido que suporte tanto o clássico login com E-mail e Senha, via JWT, quanto o Single Sign-On (SSO) através do Google.

12 de agosto de 2026

Em aplicativos modernos, fornecer apenas o login por email e senha não é suficiente. Os usuários querem a conveniência de fazer login com suas contas do Google, Apple ou GitHub. Mas como unificar esses dois mundos na sua base de dados?

O Modelo de Usuário

O segredo para uma autenticação flexível está na modelagem do banco. Se você exige que o campo password seja obrigatório no banco de dados, terá problemas ao registrar usuários via OAuth (pois eles não fornecem senha).

A melhor abordagem é tornar o password nulo/opcional e, idealmente, ter um campo de identificador do provedor (ex: googleId).

src/modules/users/entities/User.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity('users')
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;

  @Column({ unique: true })
  email: string;

  @Column({ nullable: true })
  password?: string; // Opcional

  @Column({ nullable: true })
  googleId?: string; // Opcional
}

Autenticação Tradicional (JWT)

Na autenticação tradicional, o usuário envia e-mail e senha. Verificamos o hash usando bcrypt e geramos um JSON Web Token (jsonwebtoken).

src/modules/users/services/AuthenticateUserService.ts
import { compare } from 'bcrypt';
import { sign } from 'jsonwebtoken';

export class AuthenticateUserService {
  public async execute({ email, password }: Record<string, string>) {
    const user = await usersRepository.findByEmail(email);
    if (!user || !user.password) throw new AppError('Incorrect credentials');

    const passwordMatch = await compare(password, user.password);
    if (!passwordMatch) throw new AppError('Incorrect credentials');

    const token = sign({}, process.env.JWT_SECRET as string, {
      subject: user.id,
      expiresIn: '1d'
    });

    return { user, token };
  }
}

Autenticação via Google (OAuth2)

O fluxo OAuth2 é diferente. O frontend redireciona o usuário para a página de consentimento do Google. O Google então redireciona de volta para sua API trazendo os dados do perfil.

A biblioteca passport-google-oauth20 e google-auth-library facilitam esse trabalho. Ao receber o retorno do Google, nossa lógica deve:

  1. Verificar se já existe um usuário com aquele googleId.
  2. Se não existir pelo googleId, verificar pelo email (vincular a conta existente).
  3. Se não existir por nenhum dos dois, criar um novo usuário sem senha.
  4. Gerar e retornar um JWT idêntico ao da autenticação tradicional.

O grande pulo do gato: a saída de ambos os fluxos é a mesma (um token JWT). Dessa forma, seus middlewares de proteção de rota (ensureAuthenticated) só precisam saber validar um JWT. Eles não se importam se o usuário logou com senha ou pelo Google.

Conclusão

Manter os métodos de autenticação normalizados através de um JWT padronizado garante escalabilidade e segurança. Se amanhã você quiser adicionar login com GitHub, sua aplicação já está preparada e seus middlewares de proteção de rota continuarão intactos.