Parte 1: Criando um Sistema de Login com Google e JWT no Spring Boot
Introdução O login social é uma abordagem moderna para autenticação que utiliza serviços de terceiros, como Google, Facebook ou GitHub, para identificar usuários. Ele é baseado em protocolos como OAuth 2.0, que nasceu em 2006 como um framework de autorização, e OpenID Connect (OIDC), uma camada de autenticação sobre o OAuth 2.0 lançada em 2014. Esses padrões permitem que aplicações deleguem a autenticação a provedores confiáveis, reduzindo a complexidade de gerenciar senhas e aumentando a segurança com infraestrutura consolidada. Vamos construir um sistema de login com o Google usando Spring Boot e Spring Security, gerando um JSON Web Token (JWT) para encapsular as informações do usuário autenticado? O foco será no Google, mas outros serviços compatíveis com OIDC incluem Microsoft Azure AD, Okta, Auth0 e Keycloak — todos seguindo o mesmo padrão de troca de tokens e fornecimento de dados via userinfo. Usaremos ao máximo as classes prontas do Spring, como OidcUserService e JwtEncoder, que encapsulam lógicas testadas e otimizadas, evitando reinventar a roda. Por que login social? Além de simplificar a UX (sem formulários de senha), ele aproveita autenticação multifator (MFA) e outros recursos de segurança dos provedores, tornando-o ideal para aplicações modernas. Credenciais do Google Caso não possua, crie as credenciais no Google. Acesse o Google Cloud Console Vá para console.cloud.google.com. Faça login com sua conta Google. Crie ou Selecione um Projeto No topo, clique no menu de projetos (ao lado de "Google Cloud") e selecione "New Project". Dê um nome (ex.: "MySpringBootApp"), escolha a organização (se aplicável) e clique em "Create". Selecione o projeto recém-criado no menu de projetos. Habilite a API do Google No menu lateral, vá para "APIs & Services" > "Library". Pesquise por "Google OAuth" ou "Google API" e habilite a "Google+ API" ou "People API" (necessária para userinfo com profile e email). Configure a Tela de Consentimento OAuth No menu lateral, vá para "APIs & Services" > "OAuth consent screen". Escolha o tipo de usuário: Internal: Apenas usuários da sua organização. External: Qualquer usuário com conta Google (mais comum para testes). Preencha os campos obrigatórios: App name: Nome da sua aplicação (ex.: "MySpringBootApp"). User support email: Seu email. Developer contact information: Seu email. Em "Scopes", adicione openid, profile, e email. Salve e continue. Crie as Credenciais No menu lateral, vá para "APIs & Services" > "Credentials". Clique em "Create Credentials" e selecione "OAuth 2.0 Client IDs". Configure: Application type: "Web application". Name: Um nome para identificar (ex.: "Spring Boot Client"). Authorized JavaScript origins: Deixe em branco (não necessário para Spring Boot). Authorized redirect URIs: Adicione a URI de callback do seu app, como http://localhost:8080/login/oauth2/code/google (padrão do Spring Boot). Clique em "Create". Obtenha as Credenciais Após criar, você verá o Client ID e o Client Secret. Configurando o projeto Tenha no seu projeto as dependências necessárias: spring-boot-starter-web: Inclui Tomcat e Spring MVC para criar endpoints REST. spring-boot-starter-oauth2-client: Fornece suporte a OAuth 2.0 e OIDC, com filtros como OAuth2AuthorizationRequestRedirectFilter. nimbus-jose-jwt: Biblioteca para criar JWTs assinados com algoritmos como RS256. pom.xml org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-oauth2-client com.nimbusds nimbus-jose-jwt 9.37 Configure as credenciais do Google no projeto (criadas anteriormente): client-id e client-secret: Credenciais únicas do Google para identificar sua aplicação. scope: Define os dados solicitados (openid para autenticação, profile para nome/foto, email para email). provider.google: Endpoints padrão do Google para autorização, tokens e informações do usuário. application.yml spring: security: oauth2: client: registration: google: client-id: [seu-client-id-do-google] client-secret: [seu-client-secret-do-google] scope: - openid - profile - email redirect-uri: http://localhost:8080/login/oauth2/code/google server: port: 8080 servlet: session: tracking-modes: cookie # Usa apenas cookies, não URL Fluxo Geral da Aplicação Requisição Inicial: O usuário acessa /home, uma rota protegida. Redirecionamento OAuth2: O filtro OAuth2AuthorizationRequestRedirectFilter detecta a falta de autenticação e redireciona para /oauth2/authorization/google. Autorização no Google: O Google exibe a tela de login/consentimento e retorna um cód

Introdução
O login social é uma abordagem moderna para autenticação que utiliza serviços de terceiros, como Google, Facebook ou GitHub, para identificar usuários. Ele é baseado em protocolos como OAuth 2.0, que nasceu em 2006 como um framework de autorização, e OpenID Connect (OIDC), uma camada de autenticação sobre o OAuth 2.0 lançada em 2014.
Esses padrões permitem que aplicações deleguem a autenticação a provedores confiáveis, reduzindo a complexidade de gerenciar senhas e aumentando a segurança com infraestrutura consolidada.
Vamos construir um sistema de login com o Google usando Spring Boot e Spring Security, gerando um JSON Web Token (JWT) para encapsular as informações do usuário autenticado?
O foco será no Google, mas outros serviços compatíveis com OIDC incluem Microsoft Azure AD, Okta, Auth0 e Keycloak — todos seguindo o mesmo padrão de troca de tokens e fornecimento de dados via userinfo
.
Usaremos ao máximo as classes prontas do Spring, como OidcUserService
e JwtEncoder
, que encapsulam lógicas testadas e otimizadas, evitando reinventar a roda.
Por que login social? Além de simplificar a UX (sem formulários de senha), ele aproveita autenticação multifator (MFA) e outros recursos de segurança dos provedores, tornando-o ideal para aplicações modernas.
Credenciais do Google
Caso não possua, crie as credenciais no Google.
-
Acesse o Google Cloud Console
- Vá para console.cloud.google.com.
- Faça login com sua conta Google.
-
Crie ou Selecione um Projeto
- No topo, clique no menu de projetos (ao lado de "Google Cloud") e selecione "New Project".
- Dê um nome (ex.: "MySpringBootApp"), escolha a organização (se aplicável) e clique em "Create".
- Selecione o projeto recém-criado no menu de projetos.
-
Habilite a API do Google
- No menu lateral, vá para "APIs & Services" > "Library".
- Pesquise por "Google OAuth" ou "Google API" e habilite a "Google+ API" ou "People API" (necessária para
userinfo
comprofile
eemail
).
-
Configure a Tela de Consentimento OAuth
- No menu lateral, vá para "APIs & Services" > "OAuth consent screen".
- Escolha o tipo de usuário:
- Internal: Apenas usuários da sua organização.
- External: Qualquer usuário com conta Google (mais comum para testes).
- Preencha os campos obrigatórios:
- App name: Nome da sua aplicação (ex.: "MySpringBootApp").
- User support email: Seu email.
- Developer contact information: Seu email.
- Em "Scopes", adicione
openid
,profile
, eemail
. - Salve e continue.
-
Crie as Credenciais
- No menu lateral, vá para "APIs & Services" > "Credentials".
- Clique em "Create Credentials" e selecione "OAuth 2.0 Client IDs".
- Configure:
- Application type: "Web application".
- Name: Um nome para identificar (ex.: "Spring Boot Client").
- Authorized JavaScript origins: Deixe em branco (não necessário para Spring Boot).
-
Authorized redirect URIs: Adicione a URI de callback do seu app, como
http://localhost:8080/login/oauth2/code/google
(padrão do Spring Boot).
- Clique em "Create".
-
Obtenha as Credenciais
- Após criar, você verá o Client ID e o Client Secret.
Configurando o projeto
Tenha no seu projeto as dependências necessárias:
-
spring-boot-starter-web
: Inclui Tomcat e Spring MVC para criar endpoints REST. -
spring-boot-starter-oauth2-client
: Fornece suporte a OAuth 2.0 e OIDC, com filtros comoOAuth2AuthorizationRequestRedirectFilter
. -
nimbus-jose-jwt
: Biblioteca para criar JWTs assinados com algoritmos como RS256.
pom.xml
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-oauth2-client
com.nimbusds
nimbus-jose-jwt
9.37
Configure as credenciais do Google no projeto (criadas anteriormente):
-
client-id
eclient-secret
: Credenciais únicas do Google para identificar sua aplicação. -
scope
: Define os dados solicitados (openid
para autenticação,profile
para nome/foto,email
para email). -
provider.google
: Endpoints padrão do Google para autorização, tokens e informações do usuário.
application.yml
spring:
security:
oauth2:
client:
registration:
google:
client-id: [seu-client-id-do-google]
client-secret: [seu-client-secret-do-google]
scope:
- openid
- profile
- email
redirect-uri: http://localhost:8080/login/oauth2/code/google
server:
port: 8080
servlet:
session:
tracking-modes: cookie # Usa apenas cookies, não URL
Fluxo Geral da Aplicação
-
Requisição Inicial: O usuário acessa
/home
, uma rota protegida. -
Redirecionamento OAuth2: O filtro
OAuth2AuthorizationRequestRedirectFilter
detecta a falta de autenticação e redireciona para/oauth2/authorization/google
. -
Autorização no Google: O Google exibe a tela de login/consentimento e retorna um código para
/login/oauth2/code/google
. -
Troca de Tokens: O Spring usa o código para obter
access_token
eid_token
do Google viatoken-uri
. -
Carregamento do Usuário: O
OidcUserService
consulta ouser-info-uri
e retorna umOidcUser
. -
Geração do JWT: O
HomeController
cria um JWT com os dados do usuário e retorna ao cliente.
Show Me The Code!
1. Configurar o Spring Security (SecurityConfig
)
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.web.SecurityFilterChain;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, OidcUserService oidcUserService) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable) // Desativa proteção CSRF (adequado para APIs REST)
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/oauth2/**", "/login/oauth2/**", "/error", "/favicon.ico", "/").permitAll() // Rotas públicas
.anyRequest().authenticated() // Todas as outras exigem autenticação
)
.oauth2Login(oauth2 -> oauth2
.defaultSuccessUrl("/home", true) // Após login, vai para /home
.failureUrl("/error?error=true") // Em caso de erro
.userInfoEndpoint(userInfo -> userInfo.oidcUserService(oidcUserService())) // Define o serviço de usuário
)
.logout(logout -> logout.logoutSuccessUrl("/").permitAll()) // Logout redireciona para raiz
.build();
}
@Bean
public OidcUserService oidcUserService() {
return new OidcUserService(); // Serviço padrão para carregar dados do usuário via OIDC
}
@Bean
public JwtEncoder jwtEncoder() {
JWKSource<SecurityContext> jwkSource = getJwkSource();
return new NimbusJwtEncoder(jwkSource); // Encoder para gerar JWTs assinados
}
private JWKSource<SecurityContext> getJwkSource() {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAKey rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString()) // Identificador único da chave
.build();
JWKSet jwkSet = new JWKSet(rsaKey); // Conjunto de chaves JWK
return new ImmutableJWKSet<>(jwkSet); // Fonte imutável de chaves
}
private KeyPair generateRsaKey() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // Tamanho da chave para segurança
return keyPairGenerator.generateKeyPair(); // Gera par público/privado
} catch (Exception ex) {
throw new IllegalStateException("Erro ao gerar RSA KeyPair", ex);
}
}
}
-
securityFilterChain(HttpSecurity http, OidcUserService oidcUserService)
:- Configura a cadeia de filtros de segurança.
-
csrf.disable()
: Remove proteção CSRF, pois estamos usando tokens (não formulários). -
authorizeHttpRequests
: Define regras de acesso —/oauth2/**
e/login/oauth2/**
são rotas internas do OAuth2,/error
e/favicon.ico
são utilitárias, e/
é a página inicial pública. -
oauth2Login
: Ativa o fluxo OIDC, redirecionando para/home
após sucesso e usando ooidcUserService
. -
logout
: Limpa a sessão e redireciona para/
.
-
oidcUserService()
: Retorna um serviço padrão que consulta ouser-info-uri
do Google e retorna umOidcUser
com atributos comosub
,email
, ename
. -
jwtEncoder()
: Cria um encoder que usa oJWKSource
para assinar JWTs com RS256. -
getJwkSource()
: Monta umJWKSet
com uma chave RSA, encapsulada em umImmutableJWKSet
para ser usada pelo encoder. -
generateRsaKey()
: Usa o algoritmo RSA com 2048 bits para gerar um par de chaves seguro.
2. Criar o Controlador (HomeController
)
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
@RestController
public class HomeController {
private final JwtEncoder jwtEncoder;
public HomeController(JwtEncoder jwtEncoder) {
this.jwtEncoder = jwtEncoder; // Injetado pelo Spring
}
@GetMapping("/home")
public ResponseEntity<Map<String, String>> home(@AuthenticationPrincipal OidcUser oidcUser) {
Instant now = Instant.now();
JwtClaimsSet claims = JwtClaimsSet.builder()
.issuer("self") // Identifica o emissor do token
.issuedAt(now) // Data de emissão
.expiresAt(now.plusSeconds(3600)) // Expira em 1 hora
.subject(oidcUser.getSubject()) // ID único do usuário
.claim("email", oidcUser.getEmail()) // Email do usuário
.claim("name", oidcUser.getFullName()) // Nome completo
.build();
String jwt = jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue(); // Gera o JWT assinado
Map<String, String> response = new HashMap<>();
response.put("message", "Welcome " + oidcUser.getFullName());
response.put("jwt", jwt);
return ResponseEntity.ok(response);
}
@GetMapping("/")
public String root() {
return "Bem-vindo à página inicial!";
}
}
-
HomeController(JwtEncoder jwtEncoder)
: O construtor recebe oJwtEncoder
via injeção de dependência. -
home(@AuthenticationPrincipal OidcUser oidcUser)
:-
@AuthenticationPrincipal
: Extrai oOidcUser
doSecurityContext
, preenchido pelo Spring Security após o login. -
JwtClaimsSet.builder()
: Cria um conjunto de reivindicações (claims) para o JWT, incluindoiss
,iat
,exp
,sub
, e claims customizados (email
,name
). -
jwtEncoder.encode()
: Usa a chave privada RSA doJWKSource
para assinar o JWT com RS256, retornando uma string no formatoheader.payload.signature
. -
ResponseEntity.ok()
: Retorna um JSON com a mensagem e o JWT.
-
-
root()
: Endpoint público simples para a raiz.
3. Testar o Sistema
- Execute
mvn spring-boot:run
. - Acesse
http://localhost:8080/home
. - O fluxo redireciona ao Google, e após login, retorna:
{
"message": "Welcome Uira Teste",
"jwt": "eyJraWQiOiJhYjNkZGYy..."
}
Outras Formas de Fazer
-
Senhas Tradicionais com Spring Security:
-
Como: Usa
UserDetailsService
e autenticação por formulário com um banco de usuários. - Vantagens: Total controle local, sem dependência externa.
- Desvantagens: Complexidade de gerenciar senhas, sem integração social nativa.
-
Como: Usa
-
Auth0 como Provedor:
-
Como: Substitui o Google por Auth0, configurando-o no
application.yml
. - Vantagens: Suporte a múltiplos provedores, painel de gerenciamento.
- Desvantagens: Custo adicional, menos controle sobre o backend.
-
Como: Substitui o Google por Auth0, configurando-o no
Espero que este artigo tenha sido útil para entender o fluxo de autenticação e como aproveitar as ferramentas do framework.
O que achou dessa abordagem? Deixe seu feedback nos comentários abaixo