I'm trying to integrate SAML SSO into an existing application that uses Spring Security with users, groups, and roles/permissions stored in a MySQL database. The application currently uses <security:jdbc-user-service>
to get users and roles from the DB. The IDP in question offers only a unique username and an email address as attributes, so the application still has to store groups and roles associated with each user itself (as far as I understand).
So, I trying using both SAML and the DB by hooking the jdbc-user-service
up with the samlAuthenticationProvider
through the context configuration and a custom SAMLUserDetailsService
.
Here's the relevant part of my applicationContext.xml
:
<bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
<property name="userDetails" ref="customUserDetailService" />
</bean>
<bean id="customUserDetailService" class="org.myapp.CustomUserDetailsService">
<property name="jdbcUserService" ref="jdbcUserDetailService" />
</bean>
<bean id="jdbcUserDetailService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource" />
<property name="usersByUsernameQuery" value="select username,username as password,enabled from person where username=?" />
<property name="authoritiesByUsernameQuery" value="select u.username, p.name as authorities
from person u, group g, group_permissions up, permission p
where u.group = g.id and g.id = up.group and up.permissions = p.id and
u.username=?" />
</bean>
And this is the relevant part of CustomUserDetailsService
:
public class CustomUserDetailsService implements SAMLUserDetailsService {
private JdbcDaoImpl jdbcUserService;
@Override
public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {
UserDetails user = null;
String username = credential.getAttributeAsString("urn:mace:dir:attribute-def:cn");
try {
user = jdbcUserService.loadUserByUsername(username);
} catch (UsernameNotFoundException e) {
System.out.println("User not found in DB");
// TODO
}
return user;
}
@Autowired
public void setJdbcUserService(JdbcDaoImpl jdbcUserService) {
this.jdbcUserService = jdbcUserService;
}
public JdbcDaoImpl getJdbcUserService() {
return jdbcUserService;
}
}
My question is: Is this a good idea to use org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl in this way?
I figured that the official Spring Security implementation (JdbcDaoImpl) of role retrieval from a DB is much more well-maintained, flexible, and bug-free than what I would come up with myself.
My second question is: Will using select username, username as password
create a security problem in the app somehow?
Since my app never gets to see the password (because the user only enters it at the IDP), I have to replace it with something in the query. Should I take care to make this something hard to guess or is the password in the UserDetails not re-used anyway?