Search code examples
spring-bootspring-mvcspring-securitycas

How to retrieve attributes and username sent by the CAS server with Spring Security


I have a spring boot application, which is MVC in nature. All page of this application are being authenticated by CAS SSO. I have used "spring-security-cas" as described at https://www.baeldung.com/spring-security-cas-sso Everything working fine as expected. However, I have one problem - that is, I cannot retrieve attributes and username sent by the CAS server in the following @Bean. What need I do to retrieve all the attributes and and username sent by the CAS server?

@Bean
public CasAuthenticationProvider casAuthenticationProvider() {

    CasAuthenticationProvider provider = new CasAuthenticationProvider();
    provider.setServiceProperties(serviceProperties());
    provider.setTicketValidator(ticketValidator());
    provider.setUserDetailsService(
      s -> new User("casuser", "Mellon", true, true, true, true,
        AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
    provider.setKey("CAS_PROVIDER_LOCALHOST_9000");
    return provider;
}


Solution

  • First you will need to configure the attributeRepository source and the attributes to be retrieved, in attributeRepository section in CAS server, like:

    cas.authn.attributeRepository.jdbc[0].singleRow=false
    cas.authn.attributeRepository.jdbc[0].sql=SELECT * FROM USERATTRS WHERE {0}
    cas.authn.attributeRepository.jdbc[0].username=username
    cas.authn.attributeRepository.jdbc[0].role=role 
    cas.authn.attributeRepository.jdbc[0].email=email
    cas.authn.attributeRepository.jdbc[0].url=jdbc:hsqldb:hsql://localhost:9001/xdb
    cas.authn.attributeRepository.jdbc[0].columnMappings.attrname=attrvalue
    
    cas.authn.attributeRepository.defaultAttributesToRelease=username,email,role
    

    Check this example from CAS blog.

    Then you need to implement an AuthenticationUserDetailsService at the service to read attributes returned from CAS authentication, something like:

    @Component
    public class CasUserDetailService implements AuthenticationUserDetailsService {
    
        @Override
        public UserDetails loadUserDetails(Authentication authentication) throws UsernameNotFoundException {
            CasAssertionAuthenticationToken casAssertionAuthenticationToken = (CasAssertionAuthenticationToken) authentication;
            AttributePrincipal principal = casAssertionAuthenticationToken.getAssertion().getPrincipal();
            Map attributes = principal.getAttributes();
            String uname = (String) attributes.get("username");
            String email = (String) attributes.get("email");
            String role = (String) attributes.get("role");
            String username = authentication.getName();
            Collection<SimpleGrantedAuthority> collection = new ArrayList<SimpleGrantedAuthority>();
            collection.add(new SimpleGrantedAuthority(role));
            return new User(username, "", collection);
        }
    }
    

    Then, adjust your authenticationProvider with provider.setAuthenticationUserDetailsService(casUserDetailService);