mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-02 18:45:21 +00:00
wip - refactoring
This commit is contained in:
parent
f58f299535
commit
d197285a56
@ -44,7 +44,7 @@ public class InstallationPathConfig {
|
||||
STATIC_PATH = CUSTOM_FILES_PATH + "static" + File.separator;
|
||||
TEMPLATES_PATH = CUSTOM_FILES_PATH + "templates" + File.separator;
|
||||
SIGNATURES_PATH = CUSTOM_FILES_PATH + "signatures" + File.separator;
|
||||
PRIVATE_KEY_PATH = CUSTOM_FILES_PATH + "keys" + File.separator;
|
||||
PRIVATE_KEY_PATH = CONFIG_PATH + "keys" + File.separator;
|
||||
}
|
||||
|
||||
private static String initializeBasePath() {
|
||||
|
@ -186,7 +186,7 @@ public class SecurityConfiguration {
|
||||
// Configure session management based on JWT setting
|
||||
http.sessionManagement(
|
||||
sessionManagement -> {
|
||||
if (v2Enabled && !securityProperties.isSaml2Active()) {
|
||||
if (v2Enabled) {
|
||||
sessionManagement.sessionCreationPolicy(
|
||||
SessionCreationPolicy.STATELESS);
|
||||
} else {
|
||||
|
@ -69,10 +69,11 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
}
|
||||
|
||||
String jwtToken = jwtService.extractToken(request);
|
||||
|
||||
// todo: X-API-KEY
|
||||
if (jwtToken == null) {
|
||||
// If they are unauthenticated and navigating to '/', redirect to '/login' instead of
|
||||
// sending a 401
|
||||
// todo: any unauthenticated requests should redirect to login
|
||||
if ("/".equals(request.getRequestURI())
|
||||
&& "GET".equalsIgnoreCase(request.getMethod())) {
|
||||
response.sendRedirect("/login");
|
||||
|
@ -43,13 +43,12 @@ public class JwtService implements JwtServiceInterface {
|
||||
private static final String ISSUER = "Stirling PDF";
|
||||
private static final long EXPIRATION = 3600000;
|
||||
|
||||
private final JwtKeystoreServiceInterface keystoreService;
|
||||
private final KeystoreServiceInterface keystoreService;
|
||||
private final boolean v2Enabled;
|
||||
|
||||
@Autowired
|
||||
public JwtService(
|
||||
@Qualifier("v2Enabled") boolean v2Enabled,
|
||||
JwtKeystoreServiceInterface keystoreService) {
|
||||
@Qualifier("v2Enabled") boolean v2Enabled, KeystoreServiceInterface keystoreService) {
|
||||
this.v2Enabled = v2Enabled;
|
||||
this.keystoreService = keystoreService;
|
||||
}
|
||||
@ -132,7 +131,8 @@ public class JwtService implements JwtServiceInterface {
|
||||
|
||||
if (keyId != null) {
|
||||
log.debug("Looking up key pair for key ID: {}", keyId);
|
||||
Optional<KeyPair> specificKeyPair = keystoreService.getKeyPairByKeyId(keyId);
|
||||
Optional<KeyPair> specificKeyPair =
|
||||
keystoreService.getKeyPairByKeyId(keyId); // todo: move to in-memory cache
|
||||
|
||||
if (specificKeyPair.isPresent()) {
|
||||
keyPair = specificKeyPair.get();
|
||||
@ -178,13 +178,8 @@ public class JwtService implements JwtServiceInterface {
|
||||
|
||||
@Override
|
||||
public String extractToken(HttpServletRequest request) {
|
||||
String authHeader = request.getHeader(AUTHORIZATION_HEADER);
|
||||
|
||||
if (authHeader != null && authHeader.startsWith(BEARER_PREFIX)) {
|
||||
return authHeader.substring(BEARER_PREFIX.length());
|
||||
}
|
||||
|
||||
Cookie[] cookies = request.getCookies();
|
||||
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (JWT_COOKIE_NAME.equals(cookie.getName())) {
|
||||
@ -203,7 +198,7 @@ public class JwtService implements JwtServiceInterface {
|
||||
ResponseCookie cookie =
|
||||
ResponseCookie.from(JWT_COOKIE_NAME, Newlines.stripAll(token))
|
||||
.httpOnly(true)
|
||||
.secure(true)
|
||||
// .secure(true) // todo: fix, make configurable
|
||||
.sameSite("Strict")
|
||||
.maxAge(EXPIRATION / 1000)
|
||||
.path("/")
|
||||
|
@ -17,6 +17,8 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.common.configuration.InstallationPathConfig;
|
||||
@ -27,16 +29,16 @@ import stirling.software.proprietary.security.model.JwtSigningKey;
|
||||
@Slf4j
|
||||
@Service
|
||||
@ConditionalOnBooleanProperty("v2")
|
||||
public class JwtKeyCleanupService {
|
||||
public class KeyPairCleanupService {
|
||||
|
||||
private final JwtSigningKeyRepository signingKeyRepository;
|
||||
private final JwtKeystoreService keystoreService;
|
||||
private final KeystoreService keystoreService;
|
||||
private final ApplicationProperties.Security.Jwt jwtProperties;
|
||||
|
||||
@Autowired
|
||||
public JwtKeyCleanupService(
|
||||
public KeyPairCleanupService(
|
||||
JwtSigningKeyRepository signingKeyRepository,
|
||||
JwtKeystoreService keystoreService,
|
||||
KeystoreService keystoreService,
|
||||
ApplicationProperties applicationProperties) {
|
||||
this.signingKeyRepository = signingKeyRepository;
|
||||
this.keystoreService = keystoreService;
|
||||
@ -44,6 +46,7 @@ public class JwtKeyCleanupService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@PostConstruct
|
||||
@Scheduled(fixedDelay = 24, timeUnit = TimeUnit.HOURS)
|
||||
public void cleanup() {
|
||||
if (!jwtProperties.isEnableKeyCleanup() || !keystoreService.isKeystoreEnabled()) {
|
||||
@ -113,7 +116,7 @@ public class JwtKeyCleanupService {
|
||||
}
|
||||
|
||||
Path privateKeyDirectory = Paths.get(InstallationPathConfig.getPrivateKeyPath());
|
||||
Path keyFile = privateKeyDirectory.resolve(keyId + JwtKeystoreService.KEY_SUFFIX);
|
||||
Path keyFile = privateKeyDirectory.resolve(keyId + KeystoreService.KEY_SUFFIX);
|
||||
|
||||
if (Files.exists(keyFile)) {
|
||||
Files.delete(keyFile);
|
@ -33,7 +33,7 @@ import stirling.software.proprietary.security.model.JwtSigningKey;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class JwtKeystoreService implements JwtKeystoreServiceInterface {
|
||||
public class KeystoreService implements KeystoreServiceInterface {
|
||||
|
||||
public static final String KEY_SUFFIX = ".key";
|
||||
private final JwtSigningKeyRepository signingKeyRepository;
|
||||
@ -43,7 +43,7 @@ public class JwtKeystoreService implements JwtKeystoreServiceInterface {
|
||||
private volatile String currentKeyId;
|
||||
|
||||
@Autowired
|
||||
public JwtKeystoreService(
|
||||
public KeystoreService(
|
||||
JwtSigningKeyRepository signingKeyRepository,
|
||||
ApplicationProperties applicationProperties) {
|
||||
this.signingKeyRepository = signingKeyRepository;
|
||||
@ -53,7 +53,6 @@ public class JwtKeystoreService implements JwtKeystoreServiceInterface {
|
||||
@PostConstruct
|
||||
public void initializeKeystore() {
|
||||
if (!isKeystoreEnabled()) {
|
||||
log.info("Keystore is disabled, using in-memory key generation");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -61,7 +60,7 @@ public class JwtKeystoreService implements JwtKeystoreServiceInterface {
|
||||
ensurePrivateKeyDirectoryExists();
|
||||
loadOrGenerateKeypair();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to initialize keystore, falling back to in-memory generation", e);
|
||||
log.error("Failed to initialize keystore, using in-memory generation", e);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package stirling.software.proprietary.security.service;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface JwtKeystoreServiceInterface {
|
||||
public interface KeystoreServiceInterface {
|
||||
|
||||
KeyPair getActiveKeyPair();
|
||||
|
@ -55,7 +55,7 @@ class JwtServiceTest {
|
||||
private HttpServletResponse response;
|
||||
|
||||
@Mock
|
||||
private JwtKeystoreServiceInterface keystoreService;
|
||||
private KeystoreServiceInterface keystoreService;
|
||||
|
||||
private JwtService jwtService;
|
||||
private KeyPair testKeyPair;
|
||||
|
@ -27,13 +27,13 @@ import stirling.software.proprietary.security.database.repository.JwtSigningKeyR
|
||||
import stirling.software.proprietary.security.model.JwtSigningKey;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class JwtKeyCleanupServiceTest {
|
||||
class KeyPairCleanupServiceTest {
|
||||
|
||||
@Mock
|
||||
private JwtSigningKeyRepository signingKeyRepository;
|
||||
|
||||
@Mock
|
||||
private JwtKeystoreService keystoreService;
|
||||
private KeystoreService keystoreService;
|
||||
|
||||
@Mock
|
||||
private ApplicationProperties applicationProperties;
|
||||
@ -47,7 +47,7 @@ class JwtKeyCleanupServiceTest {
|
||||
@TempDir
|
||||
private Path tempDir;
|
||||
|
||||
private JwtKeyCleanupService cleanupService;
|
||||
private KeyPairCleanupService cleanupService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
@ -59,7 +59,7 @@ class JwtKeyCleanupServiceTest {
|
||||
lenient().when(jwtConfig.getCleanupBatchSize()).thenReturn(100);
|
||||
lenient().when(keystoreService.isKeystoreEnabled()).thenReturn(true);
|
||||
|
||||
cleanupService = new JwtKeyCleanupService(signingKeyRepository, keystoreService, applicationProperties);
|
||||
cleanupService = new KeyPairCleanupService(signingKeyRepository, keystoreService, applicationProperties);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class JwtKeystoreServiceInterfaceTest {
|
||||
class KeystoreServiceInterfaceTest {
|
||||
|
||||
@Mock
|
||||
private JwtSigningKeyRepository repository;
|
||||
@ -49,7 +49,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
private JwtKeystoreService keystoreService;
|
||||
private KeystoreService keystoreService;
|
||||
private KeyPair testKeyPair;
|
||||
|
||||
@BeforeEach
|
||||
@ -70,7 +70,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
|
||||
assertEquals(keystoreEnabled, keystoreService.isKeystoreEnabled());
|
||||
}
|
||||
@ -82,7 +82,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
|
||||
KeyPair result = keystoreService.getActiveKeyPair();
|
||||
|
||||
@ -98,7 +98,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
keystoreService.initializeKeystore();
|
||||
|
||||
KeyPair result = keystoreService.getActiveKeyPair();
|
||||
@ -122,7 +122,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
keystoreService.initializeKeystore();
|
||||
|
||||
KeyPair result = keystoreService.getActiveKeyPair();
|
||||
@ -146,7 +146,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
|
||||
Optional<KeyPair> result = keystoreService.getKeyPairByKeyId(keyId);
|
||||
|
||||
@ -163,7 +163,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
|
||||
Optional<KeyPair> result = keystoreService.getKeyPairByKeyId(keyId);
|
||||
|
||||
@ -177,7 +177,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
|
||||
Optional<KeyPair> result = keystoreService.getKeyPairByKeyId("any-key");
|
||||
|
||||
@ -191,7 +191,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
keystoreService.initializeKeystore();
|
||||
|
||||
assertTrue(Files.exists(tempDir));
|
||||
@ -209,7 +209,7 @@ class JwtKeystoreServiceInterfaceTest {
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> mockedStatic = mockStatic(InstallationPathConfig.class)) {
|
||||
mockedStatic.when(InstallationPathConfig::getPrivateKeyPath).thenReturn(tempDir.toString());
|
||||
keystoreService = new JwtKeystoreService(repository, applicationProperties);
|
||||
keystoreService = new KeystoreService(repository, applicationProperties);
|
||||
keystoreService.initializeKeystore();
|
||||
|
||||
KeyPair result = keystoreService.getActiveKeyPair();
|
Loading…
x
Reference in New Issue
Block a user