Skip to content

Commit 10c7265

Browse files
committed
feat: enhance login functionality with auditing support and improved authentication flow
1 parent e610219 commit 10c7265

File tree

2 files changed

+44
-26
lines changed

2 files changed

+44
-26
lines changed

backend/src/main/java/com/park/utmstack/web/rest/UserJWTController.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.park.utmstack.domain.User;
88
import com.park.utmstack.domain.application_events.enums.ApplicationEventType;
99
import com.park.utmstack.domain.federation_service.UtmFederationServiceClient;
10+
import com.park.utmstack.loggin.LogContextBuilder;
1011
import com.park.utmstack.repository.federation_service.UtmFederationServiceClientRepository;
1112
import com.park.utmstack.security.TooMuchLoginAttemptsException;
1213
import com.park.utmstack.security.jwt.JWTFilter;
@@ -36,8 +37,10 @@
3637
import org.springframework.util.StringUtils;
3738
import org.springframework.web.bind.annotation.*;
3839

40+
import javax.servlet.http.HttpServletRequest;
3941
import javax.validation.Valid;
4042
import java.util.List;
43+
import java.util.Map;
4144
import java.util.stream.Collectors;
4245

4346
/**
@@ -57,18 +60,17 @@ public class UserJWTController {
5760
private final MailService mailService;
5861
private final LoginAttemptService loginAttemptService;
5962
private final UtmFederationServiceClientRepository fsClientRepository;
60-
private final PasswordEncoder passwordEncoder;
63+
private final LogContextBuilder logContextBuilder;
6164

6265

6366
@AuditEvent(
6467
attemptType = ApplicationEventType.AUTH_ATTEMPT,
6568
attemptMessage = "Authentication attempt registered",
66-
successType = ApplicationEventType.AUTH_SUCCESS,
67-
successMessage = "Authentication successful"
69+
successType = ApplicationEventType.UNDEFINED,
70+
successMessage = ""
6871
)
6972
@PostMapping("/authenticate")
70-
public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginVM loginVM) {
71-
73+
public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginVM loginVM, HttpServletRequest request) {
7274

7375
if (loginAttemptService.isBlocked()) {
7476
String ip = loginAttemptService.getClientIP();
@@ -85,12 +87,24 @@ public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginVM loginVM) {
8587
SecurityContextHolder.getContext().setAuthentication(authentication);
8688

8789
String jwt = tokenProvider.createToken(authentication, rememberMe, authenticated);
90+
Map<String, Object> args = logContextBuilder.buildArgs(request);
8891

8992
if (!authenticated) {
9093
String secret = tfaService.generateSecret();
9194
String code = tfaService.generateCode(secret);
9295
User user = userService.updateUserTfaSecret(loginVM.getUsername(), secret);
96+
97+
applicationEventService.createEvent(
98+
"TFA challenge issued for user '" + user.getLogin(),
99+
ApplicationEventType.TFA_CODE_SENT,
100+
args
101+
);
93102
mailService.sendTfaVerificationCode(user, code);
103+
} else {
104+
applicationEventService.createEvent(
105+
"Login successfully completed for user '" + loginVM.getUsername() + "'",
106+
ApplicationEventType.AUTH_SUCCESS,
107+
args);
94108
}
95109

96110
HttpHeaders httpHeaders = new HttpHeaders();
@@ -146,6 +160,12 @@ public ResponseEntity<JWTToken> authorizeFederationServiceManager(@Valid @Reques
146160

147161
}
148162

163+
@AuditEvent(
164+
attemptType = ApplicationEventType.TFA_CODE_VERIFY_ATTEMPT,
165+
attemptMessage = "Verification attempt for second-factor authentication",
166+
successType = ApplicationEventType.AUTH_SUCCESS,
167+
successMessage = "Login successfully completed"
168+
)
149169
@GetMapping("/tfa/verifyCode")
150170
public ResponseEntity<JWTToken> verifyCode(@RequestParam String code) {
151171

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,50 @@
11
package com.park.utmstack.web.rest.vm;
22

3+
import com.park.utmstack.service.dto.auditable.AuditableDTO;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
37
import javax.validation.constraints.NotNull;
48
import javax.validation.constraints.Size;
9+
import java.util.HashMap;
10+
import java.util.Map;
511

612
/**
713
* View Model object for storing a user's credentials.
814
*/
9-
public class LoginVM {
15+
@Setter
16+
public class LoginVM implements AuditableDTO {
1017

18+
@Getter
1119
@NotNull
1220
@Size(min = 1, max = 50)
1321
private String username;
1422

23+
@Getter
1524
@NotNull
1625
@Size(min = ManagedUserVM.PASSWORD_MIN_LENGTH, max = ManagedUserVM.PASSWORD_MAX_LENGTH)
1726
private String password;
1827

1928
private Boolean rememberMe;
2029

21-
public String getUsername() {
22-
return username;
23-
}
24-
25-
public void setUsername(String username) {
26-
this.username = username;
27-
}
28-
29-
public String getPassword() {
30-
return password;
31-
}
32-
33-
public void setPassword(String password) {
34-
this.password = password;
35-
}
36-
3730
public Boolean isRememberMe() {
3831
return rememberMe;
3932
}
4033

41-
public void setRememberMe(Boolean rememberMe) {
42-
this.rememberMe = rememberMe;
43-
}
44-
4534
@Override
4635
public String toString() {
4736
return "LoginVM{" +
4837
"username='" + username + '\'' +
4938
", rememberMe=" + rememberMe +
5039
'}';
5140
}
41+
42+
@Override
43+
public Map<String, Object> toAuditMap() {
44+
Map<String, Object> context = new HashMap<>();
45+
46+
context.put("loginAttempt", this.username);
47+
48+
return context;
49+
}
5250
}

0 commit comments

Comments
 (0)