[SWS-972] SpringSecurityPasswordValidationCallbackHandler throws NPE when UserDetailsService does not find user Created: 29/Sep/16  Updated: 27/Oct/17  Resolved: 27/Oct/17

Status: Closed
Project: Spring Web Services
Component/s: Security
Affects Version/s: 2.3.0, 3.0.0.RC1
Fix Version/s: 3.0.0.RELEASE, 2.4.2

Type: Bug Priority: Critical
Reporter: Petr Dvorak Assignee: Greg Turnquist
Resolution: Complete Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

OS: Mac OS X 10.12
Server: Apache Tomcat, 8.0.28
Java:
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)



 Description   

I implemented UserDetailsService class like so:

@Service
public class IntegrationUserDetailsService implements UserDetailsService {
 
    private IntegrationRepository integrationRepository;
 
    @Autowired
    public IntegrationUserDetailsService(IntegrationRepository integrationRepository) {
        this.integrationRepository = integrationRepository;
    }
 
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        IntegrationEntity integration = integrationRepository.findFirstByClientToken(username);
        if (integration != null) {
            List<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
            return new User(integration.getClientToken(), integration.getClientSecret(), authorities);
        } else {
            throw new UsernameNotFoundException("No integration found for client token: " + username);
        }
    }
 
}

Then, I use this service in the webservice configuration:

@Bean
public SpringSecurityPasswordValidationCallbackHandler securityCallbackHandler() {
    SpringSecurityPasswordValidationCallbackHandler callbackHandler = new SpringSecurityPasswordValidationCallbackHandler();
    callbackHandler.setUserDetailsService(userDetailsService);
    return callbackHandler;
}

However, this code causes issues, because SpringSecurityPasswordValidationCallbackHandler.java contains:

private UserDetails loadUserDetails(String username) throws DataAccessException {
    UserDetails user = this.userCache.getUserFromCache(username);
    if(user == null) {
        try {
            user = this.userDetailsService.loadUserByUsername(username);
        } catch (UsernameNotFoundException var4) {
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Username \'" + username + "\' not found");
            }
            return null; // <= HERE - EXCEPTION CAUGHT, NULL RETURNED
        }
 
        this.userCache.putUserInCache(user);
    }
 
    return user;
}
 
// ...
 
protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
    UserDetails details = this.loadUserDetails(callback.getIdentifier()); // <= HERE IS RETURNED THE NULL FROM ABOVE CODE
    callback.setPassword(details.getPassword()); // <= NPE THROWN
}

Affected code:

https://github.com/spring-projects/spring-ws/blob/master/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/SpringSecurityPasswordValidationCallbackHandler.java

Note that this is "wss4j2" - the code seems correct in "wss4j".



 Comments   
Comment by Petr Dvorak [ 11/Jul/17 ]

Sorry for the bump, but this issue is still present in 2.4.0 and it makes Spring-WS with basic username / password WS-Security pretty useless even in the most basic scenarios.

In case a user with provided username does not exist, the current code raises NPE that cannot be reasonably handled anywhere.

The issue is present only in wss4j2 version, not in wss4j. However, wss4j version is marked as deprecated and we would like to avoid having deprecated code in our projects.

Comment by jaminh [ 17/Aug/17 ]

Here is my attempt to fix this issue https://github.com/jaminh/spring-ws/tree/feature/SWS-972.

Comment by jaminh [ 27/Oct/17 ]

I have pull request for the 2.4 and 3.0 branches https://github.com/spring-projects/spring-ws/pull/104 and https://github.com/spring-projects/spring-ws/pull/103

Comment by Greg Turnquist [ 27/Oct/17 ]

Resolved! Thanks for the efforts to get this into both versions.

Generated at Mon Dec 18 11:02:24 UTC 2017 using JIRA 6.4.14#64029-sha1:ae256fe0fbb912241490ff1cecfb323ea0905ca5.