diff --git a/pom.xml b/pom.xml
index 15851ec3b..edaf48b00 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
org.owasp.webgoat
webgoat
- 2023.3
+ 2023.4-SNAPSHOT
jar
WebGoat
@@ -675,7 +675,7 @@
${project.build.directory}/webgoat-${project.version}.jar
false
- http://localhost:${webgoat.port}/WebGoat/
+ http://localhost:${webgoat.port}/WebGoat/actuator/health
diff --git a/src/main/java/org/owasp/webgoat/lessons/passwordreset/ResetLinkAssignment.java b/src/main/java/org/owasp/webgoat/lessons/passwordreset/ResetLinkAssignment.java
index ace84be78..4dacce209 100644
--- a/src/main/java/org/owasp/webgoat/lessons/passwordreset/ResetLinkAssignment.java
+++ b/src/main/java/org/owasp/webgoat/lessons/passwordreset/ResetLinkAssignment.java
@@ -57,6 +57,7 @@ import org.springframework.web.servlet.ModelAndView;
})
public class ResetLinkAssignment extends AssignmentEndpoint {
+ private static final String VIEW_FORMATTER = "lessons/passwordreset/templates/%s.html";
static final String PASSWORD_TOM_9 =
"somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
static final String TOM_EMAIL = "tom@webgoat-cloud.org";
@@ -65,15 +66,18 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
static List resetLinks = new ArrayList<>();
static final String TEMPLATE =
- "Hi, you requested a password reset link, please use this link to reset your"
- + " password.\n"
- + " \n\n"
- + "If you did not request this password change you can ignore this message.\n"
- + "If you have any comments or questions, please do not hesitate to reach us at"
- + " support@webgoat-cloud.org\n\n"
- + "Kind regards, \n"
- + "Team WebGoat";
+ """
+ Hi, you requested a password reset link, please use this link to reset your
+ password.
+
+ If you did not request this password change you can ignore this message.
+ If you have any comments or questions, please do not hesitate to reach us at
+ support@webgoat-cloud.org
+
+ Kind regards,
+ Team WebGoat
+ """;
@PostMapping("/PasswordReset/reset/login")
@ResponseBody
@@ -98,20 +102,14 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
form.setResetLink(link);
model.addAttribute("form", form);
modelAndView.addObject("form", form);
- modelAndView.setViewName("password_reset"); // Display html page for changing password
+ modelAndView.setViewName(
+ VIEW_FORMATTER.formatted("password_reset")); // Display html page for changing password
} else {
- modelAndView.setViewName("password_link_not_found");
+ modelAndView.setViewName(VIEW_FORMATTER.formatted("password_link_not_found"));
}
return modelAndView;
}
- @GetMapping("/PasswordReset/reset/change-password")
- public ModelAndView illegalCall() {
- ModelAndView modelAndView = new ModelAndView();
- modelAndView.setViewName("password_link_not_found");
- return modelAndView;
- }
-
@PostMapping("/PasswordReset/reset/change-password")
public ModelAndView changePassword(
@ModelAttribute("form") PasswordChangeForm form, BindingResult bindingResult) {
@@ -120,17 +118,17 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
bindingResult.rejectValue("password", "not.empty");
}
if (bindingResult.hasErrors()) {
- modelAndView.setViewName("password_reset");
+ modelAndView.setViewName(VIEW_FORMATTER.formatted("password_reset"));
return modelAndView;
}
if (!resetLinks.contains(form.getResetLink())) {
- modelAndView.setViewName("password_link_not_found");
+ modelAndView.setViewName(VIEW_FORMATTER.formatted("password_link_not_found"));
return modelAndView;
}
if (checkIfLinkIsFromTom(form.getResetLink())) {
usersToTomPassword.put(getWebSession().getUserName(), form.getPassword());
}
- modelAndView.setViewName("lessons/passwordreset/templates/success.html");
+ modelAndView.setViewName(VIEW_FORMATTER.formatted("success"));
return modelAndView;
}
diff --git a/src/test/java/org/owasp/webgoat/container/plugins/LessonTest.java b/src/test/java/org/owasp/webgoat/container/plugins/LessonTest.java
index 465046c67..6d7ec5ed2 100644
--- a/src/test/java/org/owasp/webgoat/container/plugins/LessonTest.java
+++ b/src/test/java/org/owasp/webgoat/container/plugins/LessonTest.java
@@ -18,7 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
diff --git a/src/test/java/org/owasp/webgoat/lessons/passwordreset/ResetLinkAssignmentTest.java b/src/test/java/org/owasp/webgoat/lessons/passwordreset/ResetLinkAssignmentTest.java
new file mode 100644
index 000000000..6010c432d
--- /dev/null
+++ b/src/test/java/org/owasp/webgoat/lessons/passwordreset/ResetLinkAssignmentTest.java
@@ -0,0 +1,103 @@
+package org.owasp.webgoat.lessons.passwordreset;
+
+import static org.mockito.Mockito.when;
+import static org.owasp.webgoat.lessons.passwordreset.ResetLinkAssignment.TOM_EMAIL;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.owasp.webgoat.container.plugins.LessonTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.http.HttpHeaders;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+@ExtendWith(SpringExtension.class)
+class ResetLinkAssignmentTest extends LessonTest {
+
+ @Value("${webwolf.host}")
+ private String webWolfHost;
+
+ @Value("${webwolf.port}")
+ private String webWolfPort;
+
+ @Autowired private ResourceLoader resourceLoader;
+
+ @BeforeEach
+ public void setup() {
+ when(webSession.getCurrentLesson()).thenReturn(new PasswordReset());
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+ }
+
+ @Test
+ void wrongResetLink() throws Exception {
+ MvcResult mvcResult =
+ mockMvc
+ .perform(
+ MockMvcRequestBuilders.get("/PasswordReset/reset/reset-password/{link}", "test"))
+ .andExpect(status().isOk())
+ .andExpect(view().name("lessons/passwordreset/templates/password_link_not_found.html"))
+ .andReturn();
+ Assertions.assertThat(resourceLoader.getResource(mvcResult.getModelAndView().getViewName()))
+ .isNotNull();
+ }
+
+ @Test
+ void changePasswordWithoutPasswordShouldReturnPasswordForm() throws Exception {
+ MvcResult mvcResult =
+ mockMvc
+ .perform(MockMvcRequestBuilders.post("/PasswordReset/reset/change-password"))
+ .andExpect(status().isOk())
+ .andExpect(view().name("lessons/passwordreset/templates/password_reset.html"))
+ .andReturn();
+ Assertions.assertThat(resourceLoader.getResource(mvcResult.getModelAndView().getViewName()))
+ .isNotNull();
+ }
+
+ @Test
+ void changePasswordWithoutLinkShouldReturnPasswordLinkNotFound() throws Exception {
+ MvcResult mvcResult =
+ mockMvc
+ .perform(
+ MockMvcRequestBuilders.post("/PasswordReset/reset/change-password")
+ .param("password", "new_password"))
+ .andExpect(status().isOk())
+ .andExpect(view().name("lessons/passwordreset/templates/password_link_not_found.html"))
+ .andReturn();
+ Assertions.assertThat(resourceLoader.getResource(mvcResult.getModelAndView().getViewName()))
+ .isNotNull();
+ }
+
+ @Test
+ void knownLinkShouldReturnPasswordResetPage() throws Exception {
+ // Create a reset link
+ mockMvc
+ .perform(
+ MockMvcRequestBuilders.post("/PasswordReset/ForgotPassword/create-password-reset-link")
+ .param("email", TOM_EMAIL)
+ .header(HttpHeaders.HOST, webWolfHost + ":" + webWolfPort))
+ .andExpect(status().isOk());
+ Assertions.assertThat(ResetLinkAssignment.resetLinks).isNotEmpty();
+
+ // With a known link you should be
+ MvcResult mvcResult =
+ mockMvc
+ .perform(
+ MockMvcRequestBuilders.get(
+ "/PasswordReset/reset/reset-password/{link}",
+ ResetLinkAssignment.resetLinks.get(0)))
+ .andExpect(status().isOk())
+ .andExpect(view().name("lessons/passwordreset/templates/password_reset.html"))
+ .andReturn();
+
+ Assertions.assertThat(resourceLoader.getResource(mvcResult.getModelAndView().getViewName()))
+ .isNotNull();
+ }
+}