diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/account/ResetPasswordController.java b/server/src/main/java/org/cloudfoundry/identity/uaa/account/ResetPasswordController.java index 61884331f92..42108794573 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/account/ResetPasswordController.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/account/ResetPasswordController.java @@ -161,6 +161,11 @@ public String emailSentPage(@ModelAttribute("code") String code, return "email_sent"; } + @RequestMapping(value = "/reset_password", method = RequestMethod.HEAD) + public void resetPassword() { + // Some mail providers initially send a HEAD request to check the validity of the link before redirecting users. + } + @RequestMapping(value = "/reset_password", method = RequestMethod.GET, params = {"code"}) public String resetPasswordPage(Model model, HttpServletResponse response, diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerTest.java index d27c3233e47..6f4c45e4024 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerTest.java @@ -45,6 +45,7 @@ import static org.mockito.Mockito.*; import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -282,6 +283,21 @@ void testResetPasswordPage() throws Exception { .andExpect(content().string(containsString(""))); } + @Test + void testResetPasswordPageWithPriorHeadRequest() throws Exception { + ExpiringCode code = codeStore.generateCode("{\"user_id\" : \"some-user-id\"}", new Timestamp(System.currentTimeMillis() + 1000000), null, IdentityZoneHolder.get().getId()); + mockMvc.perform(head("/reset_password").param("email", "user@example.com").param("code", code.getCode())) + .andExpect(status().isOk()); + mockMvc.perform(get("/reset_password").param("email", "user@example.com").param("code", code.getCode())) + .andExpect(status().isOk()) + .andDo(print()) + .andExpect(view().name("reset_password")) + .andExpect(model().attribute("email", "email")) + .andExpect(model().attribute("username", "username")) + .andExpect(content().string(containsString("