test(auth): login response never leaks the password field
Pin the @JsonProperty(WRITE_ONLY) invariant on AppUser.password. If the annotation is ever dropped — or a new field aliases the hash — the CI run that ships the regression flags it the next morning rather than waiting for a security review. Addresses PR #612 / Nora concern (regression test). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -100,6 +100,31 @@ class AuthSessionControllerTest {
|
|||||||
verify(sessionAuthenticationStrategy).onAuthentication(eq(auth), any(), any());
|
verify(sessionAuthenticationStrategy).onAuthentication(eq(auth), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void login_response_body_does_not_contain_password_field() throws Exception {
|
||||||
|
// Regression guard: AppUser.password is @JsonProperty(WRITE_ONLY). If anyone
|
||||||
|
// ever drops that annotation, this assertion catches the credential leak on
|
||||||
|
// the very next CI run.
|
||||||
|
UUID userId = UUID.randomUUID();
|
||||||
|
AppUser appUser = AppUser.builder()
|
||||||
|
.id(userId)
|
||||||
|
.email("leak@test.de")
|
||||||
|
.password("$2a$10$shouldnotappearinresponse")
|
||||||
|
.build();
|
||||||
|
Authentication auth = mock(Authentication.class);
|
||||||
|
when(authService.login(anyString(), anyString(), anyString(), anyString()))
|
||||||
|
.thenReturn(new LoginResult(appUser, auth));
|
||||||
|
|
||||||
|
mockMvc.perform(post("/api/auth/login")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content("{\"email\":\"leak@test.de\",\"password\":\"pass\"}"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.password").doesNotExist())
|
||||||
|
.andExpect(jsonPath("$.pwd").doesNotExist())
|
||||||
|
.andExpect(content().string(org.hamcrest.Matchers.not(
|
||||||
|
org.hamcrest.Matchers.containsString("$2a$10$shouldnotappearinresponse"))));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void login_does_not_set_cookie_on_failure() throws Exception {
|
void login_does_not_set_cookie_on_failure() throws Exception {
|
||||||
when(authService.login(anyString(), anyString(), anyString(), anyString()))
|
when(authService.login(anyString(), anyString(), anyString(), anyString()))
|
||||||
|
|||||||
Reference in New Issue
Block a user