3

I'm using spring-security-saml2-service-provider to authenticate my SpringBoot webapp against a SAML IdP - this works. I can also access the SAML assertions within a REST Controller using @AuthenticationPrincipal Saml2AuthenticatedPrincipal principal, but what I would like to do is restrict access by url using the values within the assertions within the Saml2AuthenticatedPrincipal principal - its a common approach within SAML federations to release values of eduPersonEntitlement, and decide access based on this. Has anyone done this? All my research/trials on this have come up with nothing. Here's what I have so far:

@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();
    }
}

I think I need to swap out authenticated() with something maybe to do with roles, and somehow set roles for users as they log in, but have got nowhere with this. Any ideas?

Jim ReesPotter
  • 445
  • 1
  • 3
  • 10

1 Answers1

3

OK, got it working....you need to customize the saml2Login - replace withDefaults() method with a new Customizer (Saml2LoginSettings below):

SAMLSecurityconfig.java:

@EnableWebSecurity
public class SAMLSecurityConfig extends WebSecurityConfigurerAdapter {
  
    @Autowired
    RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;

    @Autowired
    Saml2LoginSettings settings;
    
    protected void configure(HttpSecurity http) throws Exception {

        RelyingPartyRegistrationResolver relyingPartyRegistrationResolver =
        new DefaultRelyingPartyRegistrationResolver(this.relyingPartyRegistrationRepository);

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

        http
            .saml2Login(settings)
                .addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class).antMatcher("/**")  // 
            .authorizeRequests()
            .antMatchers("/attributes").hasAuthority("ADMIN")
            .anyRequest().authenticated();

With Saml2LoginSettings.java:

@Component
class Saml2LoginSettings implements Customizer <Saml2LoginConfigurer<HttpSecurity>> {

    @Override
    public void customize(Saml2LoginConfigurer<HttpSecurity> t) {
   
        t.successHandler(new SavedRequestAwareAuthenticationSuccessHandler() {

            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                    Authentication authentication) throws IOException, ServletException {

                authentication = assignAuthorities (authentication, request);
                super.onAuthenticationSuccess(request, response, authentication);
            }
        }); 
    }

Assigning authorities is a bit cumbersome but this works:

    private Authentication assignAuthorities (Authentication authentication, HttpServletRequest request) {
        Collection<SimpleGrantedAuthority> oldAuthorities = (Collection<SimpleGrantedAuthority>)SecurityContextHolder.getContext()
                .getAuthentication().getAuthorities();

        DefaultSaml2AuthenticatedPrincipal princ = (DefaultSaml2AuthenticatedPrincipal) authentication.getPrincipal();
        if (princ.getAttribute("urn:oid:1.3.6.1.4.1.5923.1.1.1.7").contains("urn:mace:dir:entitlement:common-lib-terms")) {

            List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
            updatedAuthorities.addAll(oldAuthorities);
            updatedAuthorities.add(new SimpleGrantedAuthority("ADMIN"));
            Saml2Authentication sAuth = (Saml2Authentication) authentication;

            sAuth = new Saml2Authentication(
                    (AuthenticatedPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal(),
                    sAuth.getSaml2Response(),
                    updatedAuthorities
            );
            SecurityContextHolder.getContext().setAuthentication(sAuth);

            return sAuth;
        }
        else 
            return authentication;
    }

Sample code here

Jim ReesPotter
  • 445
  • 1
  • 3
  • 10