Defaulting JWT settings to false (#4416)

Defaulting the configuration settings for Stirling PDF's JWT to false to
avoid any unexpected issues
This commit is contained in:
Dario Ghunney Ware
2025-09-30 12:02:11 +01:00
committed by GitHub
parent 7bd31a954e
commit dabc52ef73
15 changed files with 111 additions and 107 deletions
@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
@@ -26,6 +27,9 @@ import stirling.software.proprietary.security.service.UserService;
@RequiredArgsConstructor
public class InitialSecuritySetup {
@Value("${v2:false}")
private boolean v2Enabled = false;
private final UserService userService;
private final TeamService teamService;
private final ApplicationProperties applicationProperties;
@@ -43,6 +47,7 @@ public class InitialSecuritySetup {
}
}
configureJWTSettings();
assignUsersToDefaultTeamIfMissing();
initializeInternalApiUser();
} catch (IllegalArgumentException | SQLException | UnsupportedProviderException e) {
@@ -51,6 +56,18 @@ public class InitialSecuritySetup {
}
}
private void configureJWTSettings() {
ApplicationProperties.Security.Jwt jwtProperties =
applicationProperties.getSecurity().getJwt();
boolean jwtEnabled = jwtProperties.isEnabled();
if (!v2Enabled || !jwtEnabled) {
log.debug("V2 enabled: {}, JWT enabled: {} - disabling all JWT features", v2Enabled, jwtEnabled);
jwtProperties.setKeyCleanup(false);
}
}
private void assignUsersToDefaultTeamIfMissing() {
Team defaultTeam = teamService.getOrCreateDefaultTeam();
Team internalTeam = teamService.getOrCreateInternalTeam();
@@ -40,7 +40,7 @@ public class KeyPairCleanupService {
@PostConstruct
@Scheduled(fixedDelay = 1, timeUnit = TimeUnit.DAYS)
public void cleanup() {
if (!jwtProperties.isEnableKeyCleanup() || !keyPersistenceService.isKeystoreEnabled()) {
if (!jwtProperties.isEnabled() || !jwtProperties.isKeyCleanup()) {
return;
}
@@ -71,7 +71,7 @@ public class KeyPairCleanupService {
}
private void removePrivateKey(String keyId) throws IOException {
if (!keyPersistenceService.isKeystoreEnabled()) {
if (!jwtProperties.isEnabled()) {
return;
}
@@ -84,7 +84,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface {
@PostConstruct
public void initializeKeystore() {
if (!isKeystoreEnabled()) {
if (!jwtProperties.isEnabled()) {
return;
}
@@ -132,7 +132,7 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface {
@Override
public Optional<KeyPair> getKeyPair(String keyId) {
if (!isKeystoreEnabled()) {
if (!jwtProperties.isEnabled()) {
return Optional.empty();
}
@@ -155,11 +155,6 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface {
}
}
@Override
public boolean isKeystoreEnabled() {
return jwtProperties.isEnableKeystore();
}
@Override
public JwtVerificationKey refreshActiveKeyPair() {
return generateAndStoreKeypair();
@@ -268,4 +263,8 @@ public class KeyPersistenceService implements KeyPersistenceServiceInterface {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
public boolean isKeystoreEnabled() {
return jwtProperties.isEnabled();
}
}
@@ -16,8 +16,6 @@ public interface KeyPersistenceServiceInterface {
Optional<KeyPair> getKeyPair(String keyId);
boolean isKeystoreEnabled();
JwtVerificationKey refreshActiveKeyPair();
List<JwtVerificationKey> getKeysEligibleForCleanup(LocalDateTime cutoffDate);
@@ -1,6 +1,5 @@
package stirling.software.proprietary.security.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -21,8 +20,6 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
@@ -58,23 +55,7 @@ class KeyPersistenceServiceInterfaceTest {
lenient().when(applicationProperties.getSecurity()).thenReturn(security);
lenient().when(security.getJwt()).thenReturn(jwtConfig);
lenient().when(jwtConfig.isEnableKeystore()).thenReturn(true); // Default value
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testKeystoreEnabled(boolean keystoreEnabled) {
when(jwtConfig.isEnableKeystore()).thenReturn(keystoreEnabled);
try (MockedStatic<InstallationPathConfig> mockedStatic =
mockStatic(InstallationPathConfig.class)) {
mockedStatic
.when(InstallationPathConfig::getPrivateKeyPath)
.thenReturn(tempDir.toString());
keyPersistenceService = new KeyPersistenceService(applicationProperties, cacheManager);
assertEquals(keystoreEnabled, keyPersistenceService.isKeystoreEnabled());
}
lenient().when(jwtConfig.isEnabled()).thenReturn(true);
}
@Test
@@ -177,7 +158,7 @@ class KeyPersistenceServiceInterfaceTest {
@Test
void testGetKeyPairWhenKeystoreDisabled() {
when(jwtConfig.isEnableKeystore()).thenReturn(false);
when(jwtConfig.isEnabled()).thenReturn(false);
try (MockedStatic<InstallationPathConfig> mockedStatic =
mockStatic(InstallationPathConfig.class)) {