diff --git a/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java b/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java index e970e9326e1..ece060698d9 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java +++ b/web/src/main/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.java @@ -225,6 +225,8 @@ public void onLoginSuccess(HttpServletRequest request, HttpServletResponse respo } if (!StringUtils.hasLength(password)) { UserDetails user = getUserDetailsService().loadUserByUsername(username); + Assert.notNull(user, () -> "UserDetailsService " + getUserDetailsService() + " returned null for username " + + username + ". " + "This is an interface contract violation"); password = user.getPassword(); if (!StringUtils.hasLength(password)) { this.logger.debug("Unable to obtain password for user: " + username); diff --git a/web/src/test/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServicesTests.java b/web/src/test/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServicesTests.java index 0de8ffd59f0..c1090320fa7 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServicesTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServicesTests.java @@ -361,6 +361,20 @@ public void loginSuccessIgnoredIfParameterNotSetOrFalse() { assertThat(cookie).isNull(); } + @Test + public void loginSuccessFailsIfUserServiceMisconfigured() { + udsWillReturnNull(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addParameter(AbstractRememberMeServices.DEFAULT_PARAMETER, "true"); + MockHttpServletResponse response = new MockHttpServletResponse(); + // the token carries no credentials, so the password is looked up via the + // UserDetailsService + Authentication authentication = new TestingAuthenticationToken("someone", null, "ROLE_ABC"); + assertThatIllegalArgumentException() + .isThrownBy(() -> this.services.loginSuccess(request, response, authentication)) + .withMessageContaining("interface contract violation"); + } + @Test public void loginSuccessNormalWithNonUserDetailsBasedPrincipalSetsExpectedCookie() { // SEC-822