6

I have a Spring project and I'm converting my current authentication to use SAML2.

I have everything working as far as authentication, but I'm having difficulty in getting the SAML2 extension to insert my custom UserDetails object into the Spring Security Context authentication object.

I have a custom UserDetailsService, defined below:

public class SAMLAuthManager implements SAMLUserDetailsService {

    private static final Logger logger = Logger.getLogger(JDBCAuthManager.class);

    @Override
    public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {
        logger.info("Credential attributes: " + credential.getAttributes());
        for (int x = 0; x < credential.getAttributes().size(); x++) {
            Attribute attr = credential.getAttributes().get(x);
            List<XMLObject> attrValues = attr.getAttributeValues();
            StringBuilder strBuilder = new StringBuilder();
            for (int g = 0; g < attrValues.size(); g++) {
                XMLObject currObj = attrValues.get(g);
                strBuilder.append(currObj.toString()).append(",");
            }
            strBuilder.deleteCharAt(strBuilder.length() - 1);
            logger.info(attr.getFriendlyName() + ", " + strBuilder.toString());
        }
        String username = credential.getNameID().getValue();
            userWrapper.setStaff(s);
            logger.info("Returning wrapper: " + userWrapper);
            return userWrapper;
        } else {
            return null;
        }
    }

}

I have also configured this userDetails in my security context config:

    <bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
        <property name="userDetails" ref="samlUserDetails" />
    </bean>

However, when I inspect the SecurityContextHolder, post authentication, this line:

SecurityContextHolder.getContext().getAuthentication().getCredentials();

returns an object of type org.springframework.security.saml.SAMLCredential.

I checked to see if Spring populated the Principal with the custom object (SecurityContextHolder.getContext().getAuthentication().getPrincipal()) but it did not, that's just a String with the username populated.

Any ideas? Thanks

alessandro ferrucci
  • 1,261
  • 2
  • 24
  • 48
  • Ok - So I see that Spring populates `SecurityContextHolder.getContext().getAuthentication().getDetails()` with the custom UserDetails object. This is different from how other Authentication managers I have used work (for example the LDAP one). Any reason for this? – alessandro ferrucci Nov 12 '15 at 02:02
  • Normally I've seen Spring Security fills the SecurityContextHolder().getContext().getDetails() with an object of type `org.springframework.security.web.authentication.WebAuthenticationDetails` so it seems to me that Spring SAML extension may be doing things differently? – alessandro ferrucci Nov 12 '15 at 03:05

1 Answers1

6

The principal is by default forced to be String (in order to always permit replication of Principal which was earlier an un-serializable NameID).

This can be changed by setting forcePrincipalAsString in SAMLAuthenticationProvider to false, which will make Spring SAML include your object provided by SAMLUserDetailsService as principal in the Authentication object.

The result of call to SAMLUserDetailsService is always available under SecurityContextHolder.getContext().getAuthentication().getDetails().

Vladimír Schäfer
  • 15,375
  • 2
  • 51
  • 71