CodeGym /Cursos /Módulo 5. Spring /Lección 109: Protección de recursos con OAuth2

Lección 109: Protección de recursos con OAuth2

Módulo 5. Spring
Nivel 18 , Lección 8
Disponible

Cualquier aplicación, ya sea una tienda online gigante o un servicio de notas pequeño, tiene ciertos recursos que necesitan protección: pueden ser datos de usuarios, información confidencial u operaciones que cambian el estado del sistema. Y nuestra tarea como desarrolladores es hacer que esos recursos estén disponibles solo para quienes tienen derecho a acceder.

Sin un nivel de protección adecuado, cualquiera con software básico (sí, estamos mirando hacia Postman) podrá acceder a la API, y eso es algo que no queremos permitir.

OAuth2 ofrece una herramienta excelente para gestionar el acceso: los tokens. Hoy veremos cómo configurar tu proyecto Spring Boot para asegurar estrictamente los recursos.


Componentes para proteger recursos

Antes de meternos en la práctica, definamos brevemente los componentes clave que necesitaremos para proteger recursos con OAuth2:

  1. Servidor de recursos (Resource Server):
    • El componente que sirve los datos protegidos y verifica los tokens antes de conceder acceso. Aquí es donde normalmente desplegarías tus REST API.
  2. Token de acceso (Access Token):
    • Un token especial con el que el cliente puede llamar al servidor de recursos. El token contiene información, por ejemplo, qué acciones están permitidas y para qué usuario.
  3. Roles y permisos de acceso:
    • Gestión del acceso mediante roles (por ejemplo, ROLE_USER, ROLE_ADMIN) y scopes, que definen las capacidades funcionales del usuario.
  4. Spring Security:
    • El framework que te permite organizar la verificación de permisos a recursos, la validación de tokens y la configuración de políticas de seguridad.

Implementación de la protección de recursos en Spring Boot

Pongámonos prácticos. Vamos a configurar una aplicación Spring Boot en el rol de servidor de recursos, usando OAuth2 y JWT.

Preparación del proyecto

Asegúrate de tener el siguiente conjunto de dependencias en tu pom.xml (o build.gradle):


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Estas dependencias añaden soporte para el servidor de recursos y Spring Security.


Configuración del servidor de recursos

1. Configuración de los filtros de security

Crea una clase de configuración para Spring Security:


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll() // Recursos públicos
                .antMatchers("/admin/**").hasRole("ADMIN") // Solo para administradores
                .antMatchers("/user/**").hasRole("USER") // Solo para usuarios
                .anyRequest().authenticated() // Todas las demás requieren autenticación
            .and()
            .oauth2ResourceServer()
                .jwt(); // Usamos JWT para validar el token
    }
}

Aquí definimos:

  • Qué endpoints son públicos.
  • Qué recursos requieren roles específicos.
  • Configuramos el OAuth2 resource server usando JWT.

2. Configuración de tokens JWT

Añade en application.yml (o application.properties) los parámetros para indicar dónde buscar la clave pública para verificar la firma de los tokens JWT:


spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://auth-server.example.com/realms/myrealm
# Aquí debe ir la URL de tu servidor de autorización (Issuer URI)

El parámetro issuer-uri le dice a Spring Security dónde está el servidor de autorización (por ejemplo, Keycloak o Auth0) para obtener la información de configuración de los tokens.


Ejemplo de un controlador protegido

Creemos un REST controller que muestra el uso de roles y scopes.


@RestController
@RequestMapping("/api")
public class ResourceController {

    @GetMapping("/public")
    public String publicEndpoint() {
        return "¡Este es un recurso público, accesible para todos!";
    }

    @GetMapping("/user/hello")
    public String userEndpoint(@AuthenticationPrincipal Jwt jwt) {
        return "¡Hola, usuario " + jwt.getClaimAsString("preferred_username") + "!";
    }

    @GetMapping("/admin/dashboard")
    public String adminEndpoint() {
        return "Este es un recurso administrativo. ¡Bienvenido, gran administrador!";
    }
}
  • El endpoint /public está disponible para todos.
  • El endpoint /user/hello requiere el role USER y muestra información desde el token JWT (por ejemplo, preferred_username).
  • El endpoint /admin/dashboard está disponible solo para administradores.

¿Cómo comprobar que el servidor funciona?

  • Paso 1: obtén un token JWT. Hazlo a través del servidor de autorización (por ejemplo, Keycloak o Auth0).
  • Paso 2: envía la petición con el header Authorization: Bearer <tu token> a los endpoints protegidos.
  • Paso 3: asegúrate de que el acceso se concede o se rechaza según el role y el scope.

Gestión de roles y permisos

Los roles en OAuth2 y JWT juegan un papel clave para dar acceso a recursos. Por ejemplo, el rol ROLE_ADMIN permite acceso a recursos administrativos, y ROLE_USER a recursos de usuario.

El token JWT puede incluir scopes y roles como claims adicionales. Ejemplo de la estructura de un token:


{
  "sub": "user123",
  "scope": "read write",
  "roles": ["USER", "ADMIN"],
  "exp": 1698777600
}

¿Cómo comprobar roles en Spring? Spring Security convierte automáticamente los roles del token en autoridad. Puedes usar anotaciones:

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/secure/admin")
public String securedAdminEndpoint() {
    return "¡Solo para administradores!";
}


Errores típicos y cómo solucionarlos

  1. Error "403 Forbidden" al acceder con un token válido — probablemente tengas mal configurados los roles o los scopes. Asegúrate de que los roles incluidos en el token coinciden con los esperados.
  2. Error de verificación de la firma JWT — normalmente significa que tu resource server no pudo obtener la clave pública del servidor de autorización. Revisa el parámetro issuer-uri y verifica que el servidor de autorización esté accesible.
  3. Token caducado — asegúrate de que tus clientes usan Refresh tokens para renovar los access tokens.

Aplicación en la vida real

Usar OAuth2 y JWT para proteger recursos ofrece una seguridad fiable y escalable para arquitecturas de microservicios. Este enfoque se usa en muchos proyectos reales, desde aplicaciones corporativas hasta plataformas de autenticación social.

La próxima vez que entres a un sitio y veas el botón "Entrar con Google", ya sabrás que ahí está funcionando OAuth2.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION