Uploaded image for project: 'Spring Web Services'
  1. Spring Web Services
  2. SWS-972

SpringSecurityPasswordValidationCallbackHandler throws NPE when UserDetailsService does not find user

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Critical
    • Resolution: Complete
    • Affects Version/s: 2.3.0, 3.0.0.RC1
    • Fix Version/s: 3.0.0.RELEASE, 2.4.2
    • Component/s: Security
    • Labels:
      None
    • 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".

        Activity

          People

          • Assignee:
            gregturn Greg Turnquist
            Reporter:
            joshis Petr Dvorak
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: