| @@ -35,6 +35,7 @@ public class SecurityConfig { | |||||
| public static final String REFRESH_TOKEN_URL = "/refresh-token"; | public static final String REFRESH_TOKEN_URL = "/refresh-token"; | ||||
| public static final String VERIFY_LOGIN = "/api/2fa/verify-login"; | public static final String VERIFY_LOGIN = "/api/2fa/verify-login"; | ||||
| public static final String VERIFY_LOGIN2 = "/2fa/verify-login"; | public static final String VERIFY_LOGIN2 = "/2fa/verify-login"; | ||||
| public static final String STATUS_2FA = "/api/2fa/status"; | |||||
| private static final String[] URL_WHITELIST = { | private static final String[] URL_WHITELIST = { | ||||
| INDEX_URL, | INDEX_URL, | ||||
| @@ -42,6 +43,7 @@ public class SecurityConfig { | |||||
| REFRESH_TOKEN_URL, | REFRESH_TOKEN_URL, | ||||
| VERIFY_LOGIN, | VERIFY_LOGIN, | ||||
| VERIFY_LOGIN2, | VERIFY_LOGIN2, | ||||
| STATUS_2FA, | |||||
| }; | }; | ||||
| @Lazy | @Lazy | ||||
| @@ -3,13 +3,14 @@ package com.ffii.lioner.modules.lioner.web; | |||||
| import dev.samstevens.totp.code.CodeVerifier; | import dev.samstevens.totp.code.CodeVerifier; | ||||
| import dev.samstevens.totp.qr.QrData; | import dev.samstevens.totp.qr.QrData; | ||||
| import dev.samstevens.totp.secret.SecretGenerator; | import dev.samstevens.totp.secret.SecretGenerator; | ||||
| import jakarta.annotation.security.PermitAll; | |||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.http.HttpStatus; | import org.springframework.http.HttpStatus; | ||||
| import org.springframework.http.ResponseEntity; | import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.security.core.Authentication; | import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | import org.springframework.security.core.userdetails.UserDetails; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.PostMapping; | import org.springframework.web.bind.annotation.PostMapping; | ||||
| import org.springframework.web.bind.annotation.RequestBody; | import org.springframework.web.bind.annotation.RequestBody; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||
| @@ -99,6 +100,28 @@ public class TwoFactorController { | |||||
| abilities.add(auth.get("authority").toString()) | abilities.add(auth.get("authority").toString()) | ||||
| ); | ); | ||||
| System.out.println("Validating code: " + code + " for user: " + username); | |||||
| System.out.println("Secret: " + user.getTwoFactorSecret()); | |||||
| boolean valid = codeVerifier.isValidCode(user.getTwoFactorSecret(), code); | |||||
| System.out.println("Validation result: " + valid); | |||||
| return ResponseEntity.ok(new JwtResponse(accessToken, refreshToken, null, user, abilities)); | return ResponseEntity.ok(new JwtResponse(accessToken, refreshToken, null, user, abilities)); | ||||
| } | } | ||||
| @GetMapping("/status") | |||||
| public ResponseEntity<Map<String, Boolean>> get2FAStatus(Authentication authentication) { | |||||
| User user = userService.getCurrentUser(authentication); | |||||
| return ResponseEntity.ok(Map.of("enabled", user.isTwoFactorEnabled())); | |||||
| } | |||||
| @PostMapping("/disable") | |||||
| public ResponseEntity<Map<String, String>> disable2FA(Authentication authentication) { | |||||
| User user = userService.getCurrentUser(authentication); | |||||
| user.setTwoFactorSecret(null); | |||||
| user.setTwoFactorEnabled(false); | |||||
| userService.save(user); | |||||
| return ResponseEntity.ok(Map.of("message", "2FA disabled successfully")); | |||||
| } | |||||
| } | } | ||||
| @@ -17,6 +17,9 @@ public class NewLionerUserReq { | |||||
| @NotNull | @NotNull | ||||
| private Boolean locked; | private Boolean locked; | ||||
| @NotNull | |||||
| private Boolean twoFactorEnabled; | |||||
| @Size(max = 30) | @Size(max = 30) | ||||
| @NotBlank | @NotBlank | ||||
| @Pattern(regexp = "^[A-Za-z0-9]+$") | @Pattern(regexp = "^[A-Za-z0-9]+$") | ||||
| @@ -71,7 +74,15 @@ public class NewLionerUserReq { | |||||
| this.locked = locked; | this.locked = locked; | ||||
| } | } | ||||
| public LocalDate getExpiryDate() { | |||||
| public Boolean getTwoFactorEnabled() { | |||||
| return twoFactorEnabled; | |||||
| } | |||||
| public void setTwoFactorEnabled(Boolean twoFactorEnabled) { | |||||
| this.twoFactorEnabled = twoFactorEnabled; | |||||
| } | |||||
| public LocalDate getExpiryDate() { | |||||
| return expiryDate; | return expiryDate; | ||||
| } | } | ||||
| @@ -14,6 +14,9 @@ public class UpdateUserReq { | |||||
| @NotNull | @NotNull | ||||
| private Boolean locked; | private Boolean locked; | ||||
| @NotNull | |||||
| private Boolean twoFactorEnabled; | |||||
| @Size(max = 90) | @Size(max = 90) | ||||
| @NotBlank | @NotBlank | ||||
| private String name; | private String name; | ||||
| @@ -157,4 +160,12 @@ public class UpdateUserReq { | |||||
| this.department = department; | this.department = department; | ||||
| } | } | ||||
| public Boolean getTwoFactorEnabled() { | |||||
| return twoFactorEnabled; | |||||
| } | |||||
| public void setTwoFactorEnabled(Boolean twoFactorEnabled) { | |||||
| this.twoFactorEnabled = twoFactorEnabled; | |||||
| } | |||||
| } | } | ||||
| @@ -200,6 +200,7 @@ public class UserService extends AbstractBaseEntityService<User, Long, UserRepos | |||||
| + " u.modifiedBy," | + " u.modifiedBy," | ||||
| + " u.username," | + " u.username," | ||||
| + " u.locked," | + " u.locked," | ||||
| + " u.twoFactorEnabled," | |||||
| + " u.name," | + " u.name," | ||||
| + " u.locale," | + " u.locale," | ||||
| + " u.firstname," | + " u.firstname," | ||||
| @@ -10,6 +10,7 @@ public class UserRecord { | |||||
| private String modifiedBy; | private String modifiedBy; | ||||
| private String username; | private String username; | ||||
| private Boolean locked; | private Boolean locked; | ||||
| private Boolean twoFactorEnabled; | |||||
| private String name; | private String name; | ||||
| private Integer companyId; | private Integer companyId; | ||||
| private Integer customerId; | private Integer customerId; | ||||
| @@ -171,5 +172,11 @@ public class UserRecord { | |||||
| public String getRemarks() { | public String getRemarks() { | ||||
| return remarks; | return remarks; | ||||
| } | } | ||||
| public Boolean getTwoFactorEnabled() { | |||||
| return twoFactorEnabled; | |||||
| } | |||||
| public void setTwoFactorEnabled(Boolean twoFactorEnabled) { | |||||
| this.twoFactorEnabled = twoFactorEnabled; | |||||
| } | |||||
| } | } | ||||