Handled Download API by not passing sensitive info

This commit is contained in:
2025-07-27 15:05:33 +05:30
parent 063bfa794a
commit b2147537ca
5 changed files with 38 additions and 97 deletions
@@ -9,10 +9,7 @@ import com.skycrate.backend.skycrateBackend.entity.RefreshToken;
import com.skycrate.backend.skycrateBackend.entity.User; import com.skycrate.backend.skycrateBackend.entity.User;
import com.skycrate.backend.skycrateBackend.repository.UserRepository; import com.skycrate.backend.skycrateBackend.repository.UserRepository;
import com.skycrate.backend.skycrateBackend.security.TokenBlacklistService; import com.skycrate.backend.skycrateBackend.security.TokenBlacklistService;
import com.skycrate.backend.skycrateBackend.services.AuthenticationService; import com.skycrate.backend.skycrateBackend.services.*;
import com.skycrate.backend.skycrateBackend.services.JwtService;
import com.skycrate.backend.skycrateBackend.services.RateLimiterService;
import com.skycrate.backend.skycrateBackend.services.RefreshTokenService;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -25,6 +22,7 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/api/auth") @RequestMapping("/api/auth")
public class AuthController { public class AuthController {
private static final Logger log = LoggerFactory.getLogger(FileService.class);
private final AuthenticationManager authManager; private final AuthenticationManager authManager;
private final JwtService jwtService; private final JwtService jwtService;
private final UserRepository userRepository; private final UserRepository userRepository;
@@ -86,23 +84,6 @@ public class AuthController {
return ResponseEntity.ok(new LoginResponse(accessToken, refreshToken.getToken())); return ResponseEntity.ok(new LoginResponse(accessToken, refreshToken.getToken()));
} }
// @PostMapping("/logout")
// public ResponseEntity<?> logout(HttpServletRequest request) {
// String authHeader = request.getHeader("Authorization");
// if (authHeader == null || !authHeader.startsWith("Bearer ")) {
// return ResponseEntity.badRequest().body("Missing or invalid Authorization header");
// }
//
// String token = authHeader.substring(7);
//
// tokenBlacklistService.blacklistToken(token);
//
// String email = jwtService.extractUsername(token);
// userRepository.findByEmail(email).ifPresent(refreshTokenService::deleteByUser);
//
// return ResponseEntity.ok("Logged out successfully");
// }
@PostMapping("/logout") @PostMapping("/logout")
public ResponseEntity<?> logout(HttpServletRequest request) { public ResponseEntity<?> logout(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization"); String authHeader = request.getHeader("Authorization");
@@ -126,30 +107,15 @@ public class AuthController {
return ResponseEntity.ok("Logged out successfully"); return ResponseEntity.ok("Logged out successfully");
} }
// @PostMapping("/refresh")
// public ResponseEntity<?> refresh(@RequestBody TokenRefreshRequest request) {
// String requestToken = request.getRefreshToken();
//
// return refreshTokenService.findByToken(requestToken)
// .map(token -> {
// if (refreshTokenService.isExpired(token)) {
// return ResponseEntity.status(403).body("Refresh token expired");
// }
//
// User user = token.getUser();
// String newAccessToken = jwtService.generateToken(user);
// return ResponseEntity.ok(new TokenRefreshResponse(newAccessToken, requestToken));
// })
// .orElseGet(() -> ResponseEntity.status(403).body("Invalid refresh token"));
// }
@PostMapping("/refresh") @PostMapping("/refresh")
public ResponseEntity<?> refresh(@RequestBody TokenRefreshRequest request) { public ResponseEntity<?> refresh(@RequestBody TokenRefreshRequest request) {
String requestToken = request.getRefreshToken(); String requestToken = request.getRefreshToken();
log.error("Received refresh token: " + requestToken);
return refreshTokenService.findByToken(requestToken) return refreshTokenService.findByToken(requestToken)
.map(token -> { .map(token -> {
if (refreshTokenService.isExpired(token)) { if (refreshTokenService.isExpired(token)) {
log.error("Refresh token expired for user: " + token.getUser().getUsername());
// Clear the cached key on token expiry // Clear the cached key on token expiry
authenticationService.clearDecryptedPrivateKeyCache(token.getUser().getId().toString()); authenticationService.clearDecryptedPrivateKeyCache(token.getUser().getId().toString());
return ResponseEntity.status(403).body("Refresh token expired"); return ResponseEntity.status(403).body("Refresh token expired");
@@ -157,8 +123,12 @@ public class AuthController {
User user = token.getUser(); User user = token.getUser();
String newAccessToken = jwtService.generateToken(user); String newAccessToken = jwtService.generateToken(user);
log.info("Generated new access token for user: " + user.getUsername());
return ResponseEntity.ok(new TokenRefreshResponse(newAccessToken, requestToken)); return ResponseEntity.ok(new TokenRefreshResponse(newAccessToken, requestToken));
}) })
.orElseGet(() -> ResponseEntity.status(403).body("Invalid refresh token")); .orElseGet(() -> {
log.error("Invalid refresh token: " + requestToken);
return ResponseEntity.status(403).body("Invalid refresh token");
});
} }
} }
@@ -1,5 +1,6 @@
package com.skycrate.backend.skycrateBackend.controller; package com.skycrate.backend.skycrateBackend.controller;
import com.skycrate.backend.skycrateBackend.dto.FileDownloadRequest;
import com.skycrate.backend.skycrateBackend.services.FileService; import com.skycrate.backend.skycrateBackend.services.FileService;
import com.skycrate.backend.skycrateBackend.services.JwtService; import com.skycrate.backend.skycrateBackend.services.JwtService;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@@ -39,20 +40,20 @@ public class FileController {
} }
} }
@GetMapping("/download/{filename}") @GetMapping("/download")
public ResponseEntity<?> downloadFile( public ResponseEntity<?> downloadFile(
@PathVariable String filename, @RequestBody FileDownloadRequest fileDownloadRequest,
@RequestParam("password") String password,
HttpServletRequest request HttpServletRequest request
) { ) {
try { try {
String token = extractToken(request); String token = extractToken(request);
String username = jwtService.extractUsername(token); String username = jwtService.extractUsername(token);
byte[] decryptedData = fileService.downloadDecryptedFile(username, password, filename); // Use the password and filename from the FileDownloadRequest DTO
byte[] decryptedData = fileService.downloadDecryptedFile(username, fileDownloadRequest.getPassword(), fileDownloadRequest.getFilename());
return ResponseEntity.ok() return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"") .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileDownloadRequest.getFilename() + "\"")
.contentLength(decryptedData.length) .contentLength(decryptedData.length)
.contentType(MediaType.APPLICATION_OCTET_STREAM) .contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(decryptedData); .body(decryptedData);
@@ -0,0 +1,23 @@
package com.skycrate.backend.skycrateBackend.dto;
public class FileDownloadRequest {
private String filename;
private String password;
// Getters and Setters
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@@ -30,11 +30,6 @@ public class FileService {
private final FileMetadataRepository fileMetadataRepository; private final FileMetadataRepository fileMetadataRepository;
private final UserRepository userRepository; private final UserRepository userRepository;
// public FileService(FileMetadataRepository fileMetadataRepository, UserRepository userRepository) {
// this.fileMetadataRepository = fileMetadataRepository;
// this.userRepository = userRepository;
// }
@Autowired @Autowired
public FileService(FileMetadataRepository fileMetadataRepository, UserRepository userRepository, AuthenticationService authenticationService) { public FileService(FileMetadataRepository fileMetadataRepository, UserRepository userRepository, AuthenticationService authenticationService) {
this.fileMetadataRepository = fileMetadataRepository; this.fileMetadataRepository = fileMetadataRepository;
@@ -91,37 +86,6 @@ public class FileService {
} }
} }
// public byte[] downloadDecryptedFile(String username, String password, String filename) throws Exception {
// log.info("Download request: user={}, file={}", username, filename);
// try {
// User user = userRepository.findByUsername(username)
// .orElseThrow(() -> new RuntimeException("User not found: " + username));
//
// Path filePath = new Path("/" + username + "/" + filename);
// FileMetadata metadata = fileMetadataRepository.findByUsernameAndFilePath(username, filePath.toString())
// .orElseThrow(() -> new RuntimeException("File metadata not found for: " + filePath));
//
// SecretKey derivedKey = EncryptionUtil.deriveKey(password.toCharArray(), user.getPrivateKeySalt());
// byte[] decryptedPrivateKeyBytes = EncryptionUtil.decrypt(user.getPrivateKey(), derivedKey, user.getPrivateKeyIv());
// PrivateKey privateKey = RSAKeyUtil.decodePrivateKey(decryptedPrivateKeyBytes);
//
// byte[] aesKeyBytes = EncryptionUtil.decryptRSA(metadata.getEncryptedKey(), privateKey);
// SecretKey aesKey = EncryptionUtil.rebuildAESKey(aesKeyBytes);
//
// FileSystem fs = HDFSConfig.getHDFS();
// byte[] encryptedData;
// try (FSDataInputStream in = fs.open(filePath)) {
// encryptedData = in.readAllBytes();
// }
//
// return EncryptionUtil.decrypt(encryptedData, aesKey, metadata.getIv());
//
// } catch (Exception e) {
// log.error("Download failed for user={}, file={}: {}", username, filename, e.getMessage(), e);
// throw e;
// }
// }
public byte[] downloadDecryptedFile(String username, String password, String filename) throws Exception { public byte[] downloadDecryptedFile(String username, String password, String filename) throws Exception {
log.info("Download request: user={}, file={}", username, filename); log.info("Download request: user={}, file={}", username, filename);
try { try {
@@ -23,18 +23,6 @@ public class RefreshTokenService {
this.refreshTokenRepo = refreshTokenRepo; this.refreshTokenRepo = refreshTokenRepo;
} }
// @Transactional
// public RefreshToken createRefreshToken(User user) {
// refreshTokenRepo.deleteByUser(user);
// refreshTokenRepo.flush();
//
// RefreshToken token = new RefreshToken();
// token.setUser(user);
// token.setExpiryDate(Instant.now().plusMillis(refreshTokenDurationMs));
// token.setToken(UUID.randomUUID().toString());
// return refreshTokenRepo.save(token);
// }
@Transactional @Transactional
public RefreshToken createRefreshToken(User user) { public RefreshToken createRefreshToken(User user) {
refreshTokenRepo.deleteByUser(user); refreshTokenRepo.deleteByUser(user);
@@ -55,11 +43,6 @@ public class RefreshTokenService {
public boolean isExpired(RefreshToken token) { public boolean isExpired(RefreshToken token) {
return token.getExpiryDate().isBefore(Instant.now()); return token.getExpiryDate().isBefore(Instant.now());
} }
//
// @Transactional
// public void deleteByUser(User user) {
// refreshTokenRepo.deleteByUser(user);
// }
@Transactional @Transactional
public void deleteByUser(User user) { public void deleteByUser(User user) {