es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Autenticación SAML2 con autorización basada en las afirmaciones SAML.

Estoy utilizando spring-security-saml2-service-provider para autenticar mi aplicación web de SpringBoot con un SAML IdP, esto funciona. También puedo acceder a las afirmaciones SAML dentro de un controlador REST utilizando @AuthenticationPrincipal Saml2AuthenticatedPrincipal principal, pero lo que me gustaría hacer es restringir el acceso por URL utilizando los valores dentro de las afirmaciones dentro del Saml2AuthenticatedPrincipal principal; es un enfoque común dentro de las federaciones SAML liberar valores de eduPersonEntitlement y decidir el acceso basado en esto. ¿Alguien ha hecho esto? Todas mis investigaciones/pruebas al respecto no han dado resultados.

Aquí está lo que tengo hasta ahora:

@EnableWebSecurity
public class SAMLSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;

    protected void configure(HttpSecurity http) throws Exception {

        RelyingPartyRegistrationResolver relyingPartyRegistrationResolver =
            new DefaultRelyingPartyRegistrationResolver(this.relyingPartyRegistrationRepository);

        Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());

        http
            .saml2Login(withDefaults())
                .addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class).antMatcher("/**")
            .authorizeRequests()
                .anyRequest().authenticated();
    }
}

Creo que necesito reemplazar authenticated() con algo relacionado con roles y, de alguna manera, establecer roles para los usuarios al iniciar sesión, pero no he avanzado en esto. ¿Algún consejo?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Una posible solución para restringir el acceso por URL utilizando valores dentro de las afirmaciones de SAML es usar el control de acceso basado en roles de Spring Security. Esto requiere asignar valores de atributos específicos en las afirmaciones de SAML a roles que luego pueden asignarse a los usuarios.

    Para lograr esto, puedes crear una implementación personalizada de Saml2AuthoritiesPopulator que extraiga los valores de las afirmaciones de SAML y los asigne a roles. Por ejemplo, suponiendo que el atributo eduPersonEntitlement contiene cadenas separadas por comas que representan roles, puedes extraer estos valores y convertirlos en roles de Spring Security:

    @Component
    public class CustomSaml2AuthoritiesPopulator implements Saml2AuthoritiesPopulator {
    
        @Override
        public Collection<grantedauthority> getGrantedAuthorities(Saml2Authentication authentication, 
                                                                   Saml2AuthenticatedPrincipal authenticatedPrincipal) {
    
            List<string> entitlements = authenticatedPrincipal.getAttributeAsStringList("eduPersonEntitlement");
    
            List<grantedauthority> authorities = new ArrayList<>();
            for (String entitlement : entitlements) {
                List<string> roles = Arrays.asList(entitlement.split(","));
                authorities.addAll(roles.stream()
                        .map(role -> new SimpleGrantedAuthority("ROLE_" + role.trim()))
                        .collect(Collectors.toList()));
            }
    
            return authorities;
        }
    }
    

    A continuación, debes configurar Spring Security para usar este autorizador de autoridades personalizado:

    @EnableWebSecurity
    public class ConfiguracionSAMLSecurity extends WebSecurityConfigurerAdapter {
    
        @Autowired
        RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
    
        @Autowired
        Saml2AuthoritiesPopulator saml2AuthoritiesPopulator;
    
        protected void configure(HttpSecurity http) throws Exception {
    
            RelyingPartyRegistrationResolver relyingPartyRegistrationResolver =
                    new DefaultRelyingPartyRegistrationResolver(this.relyingPartyRegistrationRepository);
    
            Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());
    
            http
                .saml2Login(withDefaults())
                    .addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class).antMatcher("/**")
                    .defaultSuccessURL("/home", true)
                .authorizeRequests()
                    .antMatchers("/admin/**").hasRole("ADMIN")
                    .anyRequest().authenticated();
    
            http.apply(new Saml2DefaultLogoutConfigurer<>())
                .logoutSuccessUrl("/");
    
            http.saml2Logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout/saml", "GET"))
                .logoutSuccessHandler(logoutSuccessHandler());
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            Saml2AuthProvider saml2AuthProvider = new Saml2AuthProvider();
            saml2AuthProvider.setAuthoritiesMapper(new Saml2AuthoritiesMapper(saml2AuthoritiesPopulator));
            auth.authenticationProvider(saml2AuthProvider);
        }
    }
    

    Aquí hemos agregado el método configure(AuthenticationManagerBuilder auth) para configurar Saml2AuthProvider con un Saml2AuthoritiesMapper personalizado que utiliza el autorizador de autoridades personalizado.

    Finalmente, puedes usar el método hasRole() en HttpSecurity.authorizeRequests() para restringir el acceso por URL basado en los roles asignados al usuario en las afirmaciones de SAML:

    .antMatchers("/admin/**").hasRole("ADMIN")
    

    Esto permitirá que solo los usuarios con un rol de “ADMIN” (o cualquier otro rol que definas) accedan a las URL que comiencen con “/admin/”.

Comments are closed.