diff --git a/pom.xml b/pom.xml
index 89d0a60..49ac77e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,10 +64,9 @@
0.11.5
- org.projectlombok
- lombok
- 1.18.20
- provided
+ jakarta.validation
+ jakarta.validation-api
+ 2.0.2
diff --git a/src/main/java/com/faf223/expensetrackerfaf/config/SecurityConfiguration.java b/src/main/java/com/faf223/expensetrackerfaf/config/SecurityConfiguration.java
index b494885..430f3ff 100644
--- a/src/main/java/com/faf223/expensetrackerfaf/config/SecurityConfiguration.java
+++ b/src/main/java/com/faf223/expensetrackerfaf/config/SecurityConfiguration.java
@@ -4,7 +4,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
@@ -14,7 +14,7 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
-@EnableGlobalMethodSecurity(prePostEnabled = true)
+@EnableMethodSecurity
public class SecurityConfiguration {
private final JwtAuthenticationFilter jwtAuthFilter;
diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationController.java b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationController.java
index 1f375ea..43c25df 100644
--- a/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationController.java
+++ b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationController.java
@@ -23,4 +23,9 @@ public class AuthenticationController {
public ResponseEntity authenticate(@RequestBody AuthenticationRequest request) {
return ResponseEntity.ok(service.authenticate(request));
}
+
+ @PostMapping("/refresh")
+ public ResponseEntity refreshAccessToken(@RequestBody TokenRefreshRequest refreshRequest) {
+ return ResponseEntity.ok(service.refreshAccessToken(refreshRequest));
+ }
}
diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationResponse.java b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationResponse.java
index bc92552..b182217 100644
--- a/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationResponse.java
+++ b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/AuthenticationResponse.java
@@ -1,5 +1,6 @@
package com.faf223.expensetrackerfaf.controller.auth;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -11,5 +12,8 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
public class AuthenticationResponse {
- private String token;
+ @JsonProperty("access_token")
+ private String accessToken;
+ @JsonProperty("refresh_token")
+ private String refreshToken;
}
diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/auth/TokenRefreshRequest.java b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/TokenRefreshRequest.java
new file mode 100644
index 0000000..bffe531
--- /dev/null
+++ b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/TokenRefreshRequest.java
@@ -0,0 +1,8 @@
+package com.faf223.expensetrackerfaf.controller.auth;
+
+import lombok.Data;
+
+@Data
+public class TokenRefreshRequest {
+ private String refreshToken;
+}
diff --git a/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java b/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java
index d370b0a..e044309 100644
--- a/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java
+++ b/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java
@@ -7,4 +7,6 @@ import java.util.Optional;
public interface UserRepository extends JpaRepository {
Optional getUserByUserUuid(String userUuid);
+
+ Optional findByUsername(String username);
}
diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java b/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java
index 96cb4a4..bbc0440 100644
--- a/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java
+++ b/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java
@@ -4,6 +4,7 @@ import com.faf223.expensetrackerfaf.config.JwtService;
import com.faf223.expensetrackerfaf.controller.auth.AuthenticationRequest;
import com.faf223.expensetrackerfaf.controller.auth.AuthenticationResponse;
import com.faf223.expensetrackerfaf.controller.auth.RegisterRequest;
+import com.faf223.expensetrackerfaf.controller.auth.TokenRefreshRequest;
import com.faf223.expensetrackerfaf.model.Credential;
import com.faf223.expensetrackerfaf.model.User;
import com.faf223.expensetrackerfaf.repository.CredentialRepository;
@@ -12,10 +13,14 @@ import com.faf223.expensetrackerfaf.security.PersonDetails;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
+import java.io.IOException;
+import java.util.Optional;
+
@Service
@RequiredArgsConstructor
public class AuthenticationService {
@@ -38,9 +43,13 @@ public class AuthenticationService {
Credential credential = new Credential(user, request.getEmail(), passwordEncoder.encode(request.getPassword()));
credentialRepository.save(credential);
- String jwtToken = jwtService.generateToken(new PersonDetails(credential));
+ UserDetails userDetails = new PersonDetails(credential);
+ String jwtToken = jwtService.generateToken(userDetails);
+ String refreshToken = jwtService.generateToken(userDetails);
+
return AuthenticationResponse.builder()
- .token(jwtToken)
+ .accessToken(jwtToken)
+ .refreshToken(refreshToken)
.build();
}
@@ -49,10 +58,30 @@ public class AuthenticationService {
Credential credential = credentialRepository.findByEmail(request.getEmail()).orElseThrow((() -> new UsernameNotFoundException("User not found")));
- String jwtToken = jwtService.generateToken(new PersonDetails(credential));
+ UserDetails userDetails = new PersonDetails(credential);
+ String jwtToken = jwtService.generateToken(userDetails);
+ String refreshToken = jwtService.generateToken(userDetails);
return AuthenticationResponse.builder()
- .token(jwtToken)
+ .accessToken(jwtToken)
+ .refreshToken(refreshToken)
.build();
}
+ public AuthenticationResponse refreshAccessToken(TokenRefreshRequest refreshRequest) {
+ String refreshToken = refreshRequest.getRefreshToken();
+
+ Optional credential = credentialRepository.findByEmail(jwtService.extractUsername(refreshToken));
+ if (credential.isPresent()) {
+ UserDetails userDetails = new PersonDetails(credential.get());
+
+ String jwtToken = jwtService.generateToken(userDetails);
+ return AuthenticationResponse.builder()
+ .accessToken(jwtToken)
+ .refreshToken(refreshToken) // Return the same refresh token
+ .build();
+ }else {
+ throw new RuntimeException("Invalid or expired refresh token");
+ }
+ }
+
}