Cuando piensas en seguridad en sistemas distribuidos o microservicios, quieres que sea unificado, escalable y fácil de gestionar. OAuth2 ofrece un enfoque centralizado para la autenticación, permitiéndote delegar la autorización a proveedores externos (por ejemplo, Google, GitHub). Con Spring Security puedes configurar todo esto con el mínimo esfuerzo gracias a la potente integración que vamos a ver ahora.
Características clave de OAuth2 con Spring Security
Antes de meternos en el código, veamos brevemente qué obtenemos al integrar OAuth2 con Spring Security:
- Unificación de la autenticación: ya no necesitas implementar tu propio mecanismo de inicio de sesión y verificación de usuarios. Puedes usar soluciones preparadas de Google, GitHub y otros servicios populares.
- Intercambio de tokens: OAuth2 permite obtener tokens de acceso y Refresh tokens, que luego se usan para proteger recursos.
- Flexibilidad de roles y permisos: tienes la posibilidad de gestionar fácilmente los roles de los usuarios y proteger recursos utilizando esos roles.
Configuración de Spring Security para trabajar con OAuth2
1. Añadir dependencias
Para empezar necesitaremos incluir las dependencias necesarias en tu pom.xml (si usas Maven) o en build.gradle (si usas Gradle). Para trabajar con OAuth2 en Spring Security añade estas dependencias:
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
2. Configuración del cliente OAuth2
Spring Boot ya funciona muy bien con proveedores OAuth2 como Google y GitHub, así que la configuración es muy sencilla. Lo único que necesitas es añadir la configuración en el archivo application.yml:
spring:
security:
oauth2:
client:
registration:
google:
client-id: YOUR_GOOGLE_CLIENT_ID
client-secret: YOUR_GOOGLE_CLIENT_SECRET
scope:
- email
- profile
redirect-uri: "{baseUrl}/login/oauth2/code/google"
client-name: Google
provider:
google:
authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://openidconnect.googleapis.com/v1/userinfo
No te olvides de reemplazar YOUR_GOOGLE_CLIENT_ID y YOUR_GOOGLE_CLIENT_SECRET por tus valores. Puedes obtenerlos registrando la aplicación en Google Cloud Console.
3. Configurar el controlador
Tras configurar todo, tenemos que asegurarnos de que el usuario sea redirigido a la página de login OAuth2. Spring Security lo hace automáticamente, pero necesitaremos un controlador para comprobar la autorización.
Creamos un controlador de prueba:
@RestController
public class HelloController {
@GetMapping("/")
public String home(@AuthenticationPrincipal OAuth2User principal) {
String email = principal.getAttribute("email");
return "Hello, " + email + "! You are successfully authenticated.";
}
}
Aquí usamos la anotación @AuthenticationPrincipal para obtener el objeto del usuario actual desde el contexto de seguridad.
¿Cómo funciona todo esto?
Así sería el flujo de interacción con el proveedor OAuth2 en la práctica:
- El usuario hace clic en el botón de login en tu web.
- Se le redirige a la página de autorización del proveedor (por ejemplo, Google).
- Tras un login exitoso, el proveedor devuelve un token.
- Tu aplicación usa el token para acceder a los datos del usuario (por ejemplo, nombre o email).
Protección de recursos con roles
Imagina que necesitas limitar el acceso a ciertos recursos solo a roles concretos. Esto es lo que puedes hacer:
1. Añade el filtro de seguridad en la configuración de Spring Security
Crea la clase de configuración de seguridad:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/", "/login").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login(); // Activamos OAuth2 para el login
}
}
2. Trabajar con roles de usuarios
Por defecto Spring Security permite usar roles personalizados. Asegúrate de que tu proveedor OAuth2 los proporcione. Si no — puedes ampliar la funcionalidad con un mapeador personalizado:
@Component
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = new DefaultOAuth2UserService().loadUser(userRequest);
// Añadimos el rol "USER" a todos los usuarios autenticados
List<GrantedAuthority> authorities = new ArrayList<>(oAuth2User.getAuthorities());
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new DefaultOAuth2User(authorities, oAuth2User.getAttributes(), "name");
}
}
Con esta configuración puedes añadir tus propios roles a los usuarios, por ejemplo basándote en los datos que recibes del proveedor OAuth2.
Ejercicio práctico
- Configura una aplicación Spring Boot para autenticación mediante Google.
- Implementa un controlador que devuelva un mensaje de bienvenida con el email del usuario autenticado.
- Restringe el acceso a ciertas URL solo a usuarios con rol "ADMIN".
Preguntas frecuentes y errores típicos
- Me sale el error "invalid_client" al iniciar sesión con Google. Comprueba que
client-idyclient-secretestán correctos. También asegúrate de que la URL de redirect coincide con la indicada en Google Cloud Console. - OAuth2 ignora el rol especificado en la configuración. Asegúrate de que tu proveedor envía roles en la respuesta. Si no, usa un
OAuth2UserServicepersonalizado. - El token expira rápido. Puede deberse a la configuración del tiempo de vida del token en el proveedor. Considera usar Refresh tokens para renovar el acceso.
Esto es todo por esta lección. Has aprendido a configurar OAuth2 en Spring Security, autenticar usuarios mediante servicios externos (Google, GitHub) y proteger recursos usando roles. En las próximas lecciones profundizaremos en JWT, Refresh tokens y la configuración de microservicios. ¡Nos vemos!
GO TO FULL VERSION