diff --git a/.github/workflows/PR-Demo-Comment-with-react.yml b/.github/workflows/PR-Demo-Comment-with-react.yml index dd0c48b17..6902f6eab 100644 --- a/.github/workflows/PR-Demo-Comment-with-react.yml +++ b/.github/workflows/PR-Demo-Comment-with-react.yml @@ -156,10 +156,8 @@ jobs: - name: Run Gradle Command run: | if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then - export DOCKER_ENABLE_SECURITY=true export ADDITIONAL_FEATURES_OFF=false else - export DOCKER_ENABLE_SECURITY=false export ADDITIONAL_FEATURES_OFF=true fi ./gradlew clean build @@ -225,7 +223,6 @@ jobs: - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw - /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "${DOCKER_SECURITY}" # todo: change DOCKER_SECURITY? ADDITIONAL_FEATURES_OFF: "${DOCKER_SECURITY}" SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}" SYSTEM_DEFAULTLOCALE: en-GB diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e0b65e93..01cc8e75d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,13 +40,11 @@ jobs: - name: Build with Gradle and no spring security run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true - name: Build with Gradle and with spring security run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: true ADDITIONAL_FEATURES_OFF: false - name: Upload Test Reports diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index 8e0ef3837..d10d8e8b6 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -80,7 +80,6 @@ jobs: - name: Generate jar (With Security=${{ matrix.enable_security }}) run: ./gradlew clean createExe env: - DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }} ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false @@ -177,7 +176,6 @@ jobs: - name: Build Installer run: ./gradlew build jpackage -x test --info env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true STIRLING_PDF_DESKTOP_UI: true BROWSER_OPEN: true diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 96abfd822..e84d2296f 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -37,7 +37,6 @@ jobs: - name: Run Gradle Command run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true STIRLING_PDF_DESKTOP_UI: false diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml index 476ae8a9c..09ad89312 100644 --- a/.github/workflows/releaseArtifacts.yml +++ b/.github/workflows/releaseArtifacts.yml @@ -47,7 +47,6 @@ jobs: - name: Generate jar (With Security=${{ matrix.enable_security }}) run: ./gradlew clean createExe env: - DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }} ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }} STIRLING_PDF_DESKTOP_UI: false diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index 4c12b819a..5509d74bc 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -33,7 +33,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - DOCKER_ENABLE_SECURITY: true ADDITIONAL_FEATURES_OFF: false STIRLING_PDF_DESKTOP_UI: true run: | diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml index 976bb1c39..8162510c5 100644 --- a/.github/workflows/testdriver.yml +++ b/.github/workflows/testdriver.yml @@ -28,7 +28,6 @@ jobs: - name: Build with Gradle run: ./gradlew clean build env: - DOCKER_ENABLE_SECURITY: false ADDITIONAL_FEATURES_OFF: true - name: Set up Docker Buildx @@ -77,7 +76,6 @@ jobs: - /stirling/test-${{ github.sha }}/config:/configs:rw - /stirling/test-${{ github.sha }}/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "false" ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-GB diff --git a/DeveloperGuide.md b/DeveloperGuide.md index 675e5b4db..cb4c4827a 100644 --- a/DeveloperGuide.md +++ b/DeveloperGuide.md @@ -55,7 +55,7 @@ Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, do Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE. 5. Add environment variable -For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DOCKER_ENABLE_SECURITY=true or ADDITIONAL_FEATURES_OFF=false to your system and/or IDE build/run step. +For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag ADDITIONAL_FEATURES_OFF=false to your system and/or IDE build/run step. ## 4. Project Structure @@ -141,7 +141,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 @@ -171,7 +170,6 @@ Stirling-PDF uses different Docker images for various configurations. The build 1. Set the security environment variable: ```bash - export DOCKER_ENABLE_SECURITY=false # or true for security-enabled builds export ADDITIONAL_FEATURES_OFF=true # or false for security-enabled builds ``` @@ -198,7 +196,6 @@ Stirling-PDF uses different Docker images for various configurations. The build For the fat version (with security enabled): ```bash - export DOCKER_ENABLE_SECURITY=true export ADDITIONAL_FEATURES_OFF=false docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat . ``` diff --git a/Dockerfile b/Dockerfile index 8e9b992df..f6bb9fa37 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,8 +23,7 @@ LABEL org.opencontainers.image.version="${VERSION_TAG}" LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, convert, OCR, watermark" # Set Environment Variables -ENV DOCKER_ENABLE_SECURITY=false \ - ADDITIONAL_FEATURES_OFF=true \ +ENV ADDITIONAL_FEATURES_OFF=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.fat b/Dockerfile.fat index eeb5936f6..ed1f46e8f 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -15,9 +15,8 @@ WORKDIR /app # Copy the entire project to the working directory COPY . . -# Build the application with DOCKER_ENABLE_SECURITY=true/ADDITIONAL_FEATURES_OFF=false -RUN DOCKER_ENABLE_SECURITY=true \ - ADDITIONAL_FEATURES_OFF=false \ +# Build the application with ADDITIONAL_FEATURES_OFF=false +RUN ADDITIONAL_FEATURES_OFF=false \ STIRLING_PDF_DESKTOP_UI=false \ ./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube @@ -33,8 +32,7 @@ COPY --from=build /app/build/libs/*.jar app.jar ARG VERSION_TAG # Set Environment Variables -ENV DOCKER_ENABLE_SECURITY=false \ - ADDITIONAL_FEATURES_OFF=true \ +ENV ADDITIONAL_FEATURES_OFF=true \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ JAVA_CUSTOM_OPTS="" \ diff --git a/Dockerfile.ultra-lite b/Dockerfile.ultra-lite index 04b15c90a..ba689ceb1 100644 --- a/Dockerfile.ultra-lite +++ b/Dockerfile.ultra-lite @@ -4,8 +4,7 @@ FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff45 ARG VERSION_TAG # Set Environment Variables -ENV DOCKER_ENABLE_SECURITY=false \ - ADDITIONAL_FEATURES_OFF=true \ +ENV ADDITIONAL_FEATURES_OFF=true \ HOME=/home/stirlingpdfuser \ VERSION_TAG=$VERSION_TAG \ JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \ diff --git a/build.gradle b/build.gradle index 7992d41fe..12563a628 100644 --- a/build.gradle +++ b/build.gradle @@ -51,12 +51,14 @@ licenseReport { sourceSets { main { java { - if (System.getenv("DOCKER_ENABLE_SECURITY") == "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "true") { - exclude "stirling/software/proprietary/security/**" + if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'false' + || (project.hasProperty('ADDITIONAL_FEATURES_OFF') + && System.getProperty('ADDITIONAL_FEATURES_OFF'))) { + exclude 'stirling/software/proprietary/security/**' } - if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { - exclude "stirling/software/SPDF/UI/impl/**" + if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') { + exclude 'stirling/software/SPDF/UI/impl/**' } } @@ -64,12 +66,14 @@ sourceSets { test { java { - if (System.getenv("DOCKER_ENABLE_SECURITY") == "false" || System.getenv("ADDITIONAL_FEATURES_OFF") == "true") { - exclude "stirling/software/proprietary/security/**" + if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'false' + || (project.hasProperty('ADDITIONAL_FEATURES_OFF') + && System.getProperty('ADDITIONAL_FEATURES_OFF'))) { + exclude 'stirling/software/proprietary/security/**' } - if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { - exclude "stirling/software/SPDF/UI/impl/**" + if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') { + exclude 'stirling/software/SPDF/UI/impl/**' } } } diff --git a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml index 63b0a7467..4f3b25948 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml @@ -20,7 +20,6 @@ services: - ./stirling/latest/logs:/logs:rw - ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml index 318065e05..f38ed84e2 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security-postgres.yml @@ -20,7 +20,6 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-fat-security.yml b/exampleYmlFiles/docker-compose-latest-fat-security.yml index 8d9ebeff4..88441ee9a 100644 --- a/exampleYmlFiles/docker-compose-latest-fat-security.yml +++ b/exampleYmlFiles/docker-compose-latest-fat-security.yml @@ -18,7 +18,6 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "false" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml index 36cbfe868..947ddc447 100644 --- a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml +++ b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" SECURITY_OAUTH2_ENABLED: "true" diff --git a/exampleYmlFiles/docker-compose-latest-security.yml b/exampleYmlFiles/docker-compose-latest-security.yml index d6d90bf0a..fa8d76888 100644 --- a/exampleYmlFiles/docker-compose-latest-security.yml +++ b/exampleYmlFiles/docker-compose-latest-security.yml @@ -18,7 +18,6 @@ services: - ./stirling/latest/config:/configs:rw - ./stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml index b3cb57cd1..434bbcd61 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" SYSTEM_DEFAULTLOCALE: en-US diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml index f6c1b703a..484acf269 100644 --- a/exampleYmlFiles/docker-compose-latest-ultra-lite.yml +++ b/exampleYmlFiles/docker-compose-latest-ultra-lite.yml @@ -17,7 +17,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "false" ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" SYSTEM_DEFAULTLOCALE: en-US diff --git a/exampleYmlFiles/docker-compose-latest.yml b/exampleYmlFiles/docker-compose-latest.yml index 3a296b84a..46cfe3553 100644 --- a/exampleYmlFiles/docker-compose-latest.yml +++ b/exampleYmlFiles/docker-compose-latest.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "false" ADDITIONAL_FEATURES_OFF: "true" SECURITY_ENABLELOGIN: "false" LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID" diff --git a/exampleYmlFiles/test_cicd.yml b/exampleYmlFiles/test_cicd.yml index f92c80d8f..c76471bd8 100644 --- a/exampleYmlFiles/test_cicd.yml +++ b/exampleYmlFiles/test_cicd.yml @@ -18,7 +18,6 @@ services: - /stirling/latest/config:/configs:rw - /stirling/latest/logs:/logs:rw environment: - DOCKER_ENABLE_SECURITY: "true" ADDITIONAL_FEATURES_OFF: "false" SECURITY_ENABLELOGIN: "true" PUID: 1002 diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java index ee726b9fb..47ad7671c 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationFailureHandler.java @@ -1,11 +1,8 @@ package stirling.software.proprietary.security; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.InternalAuthenticationServiceException; @@ -13,6 +10,13 @@ import org.springframework.security.authentication.LockedException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.service.LoginAttemptService; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java index b9379ec74..8b6ea1dec 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomAuthenticationSuccessHandler.java @@ -1,14 +1,18 @@ package stirling.software.proprietary.security; +import java.io.IOException; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.SavedRequest; + import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import java.io.IOException; + import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.savedrequest.SavedRequest; + import stirling.software.common.util.RequestUriUtils; import stirling.software.proprietary.security.service.LoginAttemptService; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java index 244e16da0..44046eb71 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/CustomLogoutSuccessHandler.java @@ -1,22 +1,27 @@ package stirling.software.proprietary.security; -import com.coveo.saml.SamlClient; -import com.coveo.saml.SamlException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.springframework.core.io.Resource; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; + +import com.coveo.saml.SamlClient; +import com.coveo.saml.SamlException; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; @@ -171,8 +176,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { private SamlClient getSamlClient( String registrationId, SAML2 samlConf, List certificates) throws SamlException { - String serverUrl = - appConfig.getBaseUrl() + ":" + appConfig.getServerPort(); + String serverUrl = appConfig.getBaseUrl() + ":" + appConfig.getServerPort(); String relyingPartyIdentifier = serverUrl + "/saml2/service-provider-metadata/" + registrationId; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java b/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java index 1353f2151..6568ac3b0 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/InitialSecuritySetup.java @@ -1,14 +1,18 @@ package stirling.software.proprietary.security; -import jakarta.annotation.PostConstruct; import java.sql.SQLException; import java.util.UUID; + +import org.springframework.stereotype.Component; + +import jakarta.annotation.PostConstruct; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; + import stirling.software.common.model.ApplicationProperties; -import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.enumeration.Role; +import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.proprietary.security.service.DatabaseServiceInterface; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java b/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java index 4faeb9041..25b3c5096 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/RateLimitResetScheduler.java @@ -1,8 +1,10 @@ package stirling.software.proprietary.security; -import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; + import stirling.software.proprietary.security.filter.IPRateLimitingFilter; @Component diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java index 5507580a4..2feab9a46 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/DatabaseConfig.java @@ -1,8 +1,7 @@ package stirling.software.proprietary.security.configuration; import javax.sql.DataSource; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.domain.EntityScan; @@ -11,6 +10,10 @@ import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.exception.UnsupportedProviderException; @@ -65,15 +68,17 @@ public class DatabaseConfig { private DataSource useDefaultDataSource(DataSourceBuilder dataSourceBuilder) { log.info("Using default H2 database"); - dataSourceBuilder.url(DATASOURCE_DEFAULT_URL) - .driverClassName(DatabaseDriver.H2.getDriverClassName()) - .username(DEFAULT_USERNAME); + dataSourceBuilder + .url(DATASOURCE_DEFAULT_URL) + .driverClassName(DatabaseDriver.H2.getDriverClassName()) + .username(DEFAULT_USERNAME); return dataSourceBuilder.build(); } @ConditionalOnBooleanProperty(name = "premium.enabled") - private DataSource useCustomDataSource(DataSourceBuilder dataSourceBuilder) throws UnsupportedProviderException { + private DataSource useCustomDataSource(DataSourceBuilder dataSourceBuilder) + throws UnsupportedProviderException { log.info("Using custom database configuration"); if (!datasource.getCustomDatabaseUrl().isBlank()) { @@ -85,11 +90,11 @@ public class DatabaseConfig { } else { dataSourceBuilder.driverClassName(getDriverClassName(datasource.getType())); dataSourceBuilder.url( - generateCustomDataSourceUrl( - datasource.getType(), - datasource.getHostName(), - datasource.getPort(), - datasource.getName())); + generateCustomDataSourceUrl( + datasource.getType(), + datasource.getHostName(), + datasource.getPort(), + datasource.getName())); } dataSourceBuilder.username(datasource.getUsername()); dataSourceBuilder.password(datasource.getPassword()); diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java index 82d794d6e..c9b6e9d77 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/MailConfig.java @@ -10,6 +10,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; /** diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java index cec19214a..b49e19c08 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/configuration/SecurityConfiguration.java @@ -1,7 +1,7 @@ package stirling.software.proprietary.security.configuration; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; @@ -26,6 +26,9 @@ import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.NullRequestCache; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.CustomAuthenticationFailureHandler; @@ -71,22 +74,22 @@ public class SecurityConfiguration { private final OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver; public SecurityConfiguration( - PersistentLoginRepository persistentLoginRepository, - CustomUserDetailsService userDetailsService, - @Lazy UserService userService, - @Qualifier("loginEnabled") boolean loginEnabledValue, - @Qualifier("runningProOrHigher") boolean runningProOrHigher, - AppConfig appConfig, - ApplicationProperties applicationProperties, - UserAuthenticationFilter userAuthenticationFilter, - LoginAttemptService loginAttemptService, - FirstLoginFilter firstLoginFilter, - SessionPersistentRegistry sessionRegistry, - @Autowired(required = false) GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper, - @Autowired(required = false) - RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations, - @Autowired(required = false) - OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver) { + PersistentLoginRepository persistentLoginRepository, + CustomUserDetailsService userDetailsService, + @Lazy UserService userService, + @Qualifier("loginEnabled") boolean loginEnabledValue, + @Qualifier("runningProOrHigher") boolean runningProOrHigher, + AppConfig appConfig, + ApplicationProperties applicationProperties, + UserAuthenticationFilter userAuthenticationFilter, + LoginAttemptService loginAttemptService, + FirstLoginFilter firstLoginFilter, + SessionPersistentRegistry sessionRegistry, + @Autowired(required = false) GrantedAuthoritiesMapper oAuth2userAuthoritiesMapper, + @Autowired(required = false) + RelyingPartyRegistrationRepository saml2RelyingPartyRegistrations, + @Autowired(required = false) + OpenSaml4AuthenticationRequestResolver saml2AuthenticationRequestResolver) { this.userDetailsService = userDetailsService; this.userService = userService; this.loginEnabledValue = loginEnabledValue; @@ -116,180 +119,183 @@ public class SecurityConfiguration { if (loginEnabledValue) { http.addFilterBefore( - userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); if (!applicationProperties.getSecurity().getCsrfDisabled()) { CookieCsrfTokenRepository cookieRepo = - CookieCsrfTokenRepository.withHttpOnlyFalse(); + CookieCsrfTokenRepository.withHttpOnlyFalse(); CsrfTokenRequestAttributeHandler requestHandler = - new CsrfTokenRequestAttributeHandler(); + new CsrfTokenRequestAttributeHandler(); requestHandler.setCsrfRequestAttributeName(null); http.csrf( - csrf -> - csrf.ignoringRequestMatchers( - request -> { - String apiKey = request.getHeader("X-API-KEY"); - // If there's no API key, don't ignore CSRF - // (return false) - if (apiKey == null || apiKey.trim().isEmpty()) { - return false; - } - // Validate API key using existing UserService - try { - Optional user = - userService.getUserByApiKey(apiKey); - // If API key is valid, ignore CSRF (return - // true) - // If API key is invalid, don't ignore CSRF - // (return false) - return user.isPresent(); - } catch (Exception e) { - // If there's any error validating the API - // key, don't ignore CSRF - return false; - } - }) - .csrfTokenRepository(cookieRepo) - .csrfTokenRequestHandler(requestHandler)); + csrf -> + csrf.ignoringRequestMatchers( + request -> { + String apiKey = request.getHeader("X-API-KEY"); + // If there's no API key, don't ignore CSRF + // (return false) + if (apiKey == null || apiKey.trim().isEmpty()) { + return false; + } + // Validate API key using existing UserService + try { + Optional user = + userService.getUserByApiKey(apiKey); + // If API key is valid, ignore CSRF (return + // true) + // If API key is invalid, don't ignore CSRF + // (return false) + return user.isPresent(); + } catch (Exception e) { + // If there's any error validating the API + // key, don't ignore CSRF + return false; + } + }) + .csrfTokenRepository(cookieRepo) + .csrfTokenRequestHandler(requestHandler)); } http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class); http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class); http.sessionManagement( - sessionManagement -> - sessionManagement - .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) - .maximumSessions(10) - .maxSessionsPreventsLogin(false) - .sessionRegistry(sessionRegistry) - .expiredUrl("/login?logout=true")); + sessionManagement -> + sessionManagement + .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) + .maximumSessions(10) + .maxSessionsPreventsLogin(false) + .sessionRegistry(sessionRegistry) + .expiredUrl("/login?logout=true")); http.authenticationProvider(daoAuthenticationProvider()); http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache())); http.logout( - logout -> - logout.logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/logout")) - .logoutSuccessHandler( - new CustomLogoutSuccessHandler(applicationProperties, appConfig)) - .clearAuthentication(true) - .invalidateHttpSession(true) - .deleteCookies("JSESSIONID", "remember-me")); + logout -> + logout.logoutRequestMatcher( + PathPatternRequestMatcher.withDefaults() + .matcher("/logout")) + .logoutSuccessHandler( + new CustomLogoutSuccessHandler( + applicationProperties, appConfig)) + .clearAuthentication(true) + .invalidateHttpSession(true) + .deleteCookies("JSESSIONID", "remember-me")); http.rememberMe( - rememberMeConfigurer -> // Use the configurator directly + rememberMeConfigurer -> // Use the configurator directly rememberMeConfigurer - .tokenRepository(persistentTokenRepository()) - .tokenValiditySeconds( // 14 days - 14 * 24 * 60 * 60) - .userDetailsService( // Your existing UserDetailsService - userDetailsService) - .useSecureCookie( // Enable secure cookie - true) - .rememberMeParameter( // Form parameter name - "remember-me") - .rememberMeCookieName( // Cookie name - "remember-me") - .alwaysRemember(false)); + .tokenRepository(persistentTokenRepository()) + .tokenValiditySeconds( // 14 days + 14 * 24 * 60 * 60) + .userDetailsService( // Your existing UserDetailsService + userDetailsService) + .useSecureCookie( // Enable secure cookie + true) + .rememberMeParameter( // Form parameter name + "remember-me") + .rememberMeCookieName( // Cookie name + "remember-me") + .alwaysRemember(false)); http.authorizeHttpRequests( - authz -> - authz.requestMatchers( - req -> { - String uri = req.getRequestURI(); - String contextPath = req.getContextPath(); - // Remove the context path from the URI - String trimmedUri = - uri.startsWith(contextPath) - ? uri.substring( - contextPath.length()) - : uri; - return trimmedUri.startsWith("/login") - || trimmedUri.startsWith("/oauth") - || trimmedUri.startsWith("/saml2") - || trimmedUri.endsWith(".svg") - || trimmedUri.startsWith("/register") - || trimmedUri.startsWith("/error") - || trimmedUri.startsWith("/images/") - || trimmedUri.startsWith("/public/") - || trimmedUri.startsWith("/css/") - || trimmedUri.startsWith("/fonts/") - || trimmedUri.startsWith("/js/") - || trimmedUri.startsWith( - "/api/v1/info/status"); - }) - .permitAll() - .anyRequest() - .authenticated()); + authz -> + authz.requestMatchers( + req -> { + String uri = req.getRequestURI(); + String contextPath = req.getContextPath(); + // Remove the context path from the URI + String trimmedUri = + uri.startsWith(contextPath) + ? uri.substring( + contextPath.length()) + : uri; + return trimmedUri.startsWith("/login") + || trimmedUri.startsWith("/oauth") + || trimmedUri.startsWith("/saml2") + || trimmedUri.endsWith(".svg") + || trimmedUri.startsWith("/register") + || trimmedUri.startsWith("/error") + || trimmedUri.startsWith("/images/") + || trimmedUri.startsWith("/public/") + || trimmedUri.startsWith("/css/") + || trimmedUri.startsWith("/fonts/") + || trimmedUri.startsWith("/js/") + || trimmedUri.startsWith( + "/api/v1/info/status"); + }) + .permitAll() + .anyRequest() + .authenticated()); // Handle User/Password Logins if (applicationProperties.getSecurity().isUserPass()) { http.formLogin( - formLogin -> - formLogin - .loginPage("/login") - .successHandler( - new CustomAuthenticationSuccessHandler( - loginAttemptService, userService)) - .failureHandler( - new CustomAuthenticationFailureHandler( - loginAttemptService, userService)) - .defaultSuccessUrl("/") - .permitAll()); + formLogin -> + formLogin + .loginPage("/login") + .successHandler( + new CustomAuthenticationSuccessHandler( + loginAttemptService, userService)) + .failureHandler( + new CustomAuthenticationFailureHandler( + loginAttemptService, userService)) + .defaultSuccessUrl("/") + .permitAll()); } // Handle OAUTH2 Logins if (applicationProperties.getSecurity().isOauth2Active()) { http.oauth2Login( - oauth2 -> - oauth2.loginPage("/oauth2") - /* - This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. - If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser' - is set as true, else login fails with an error message advising the same. - */ - .successHandler( - new CustomOAuth2AuthenticationSuccessHandler( - loginAttemptService, - applicationProperties, - userService)) - .failureHandler( - new CustomOAuth2AuthenticationFailureHandler()) - . // Add existing Authorities from the database - userInfoEndpoint( - userInfoEndpoint -> - userInfoEndpoint - .oidcUserService( - new CustomOAuth2UserService( - applicationProperties, - userService, - loginAttemptService)) - .userAuthoritiesMapper( - oAuth2userAuthoritiesMapper)) - .permitAll()); + oauth2 -> + oauth2.loginPage("/oauth2") + /* + This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. + If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser' + is set as true, else login fails with an error message advising the same. + */ + .successHandler( + new CustomOAuth2AuthenticationSuccessHandler( + loginAttemptService, + applicationProperties, + userService)) + .failureHandler( + new CustomOAuth2AuthenticationFailureHandler()) + . // Add existing Authorities from the database + userInfoEndpoint( + userInfoEndpoint -> + userInfoEndpoint + .oidcUserService( + new CustomOAuth2UserService( + applicationProperties, + userService, + loginAttemptService)) + .userAuthoritiesMapper( + oAuth2userAuthoritiesMapper)) + .permitAll()); } // Handle SAML if (applicationProperties.getSecurity().isSaml2Active() && runningProOrHigher) { // Configure the authentication provider OpenSaml4AuthenticationProvider authenticationProvider = - new OpenSaml4AuthenticationProvider(); + new OpenSaml4AuthenticationProvider(); authenticationProvider.setResponseAuthenticationConverter( - new CustomSaml2ResponseAuthenticationConverter(userService)); + new CustomSaml2ResponseAuthenticationConverter(userService)); http.authenticationProvider(authenticationProvider) - .saml2Login( - saml2 -> { - try { - saml2.loginPage("/saml2") - .relyingPartyRegistrationRepository( - saml2RelyingPartyRegistrations) - .authenticationManager( - new ProviderManager(authenticationProvider)) - .successHandler( - new CustomSaml2AuthenticationSuccessHandler( - loginAttemptService, - applicationProperties, - userService)) - .failureHandler( - new CustomSaml2AuthenticationFailureHandler()) - .authenticationRequestResolver( - saml2AuthenticationRequestResolver); - } catch (Exception e) { - log.error("Error configuring SAML 2 login", e); - throw new RuntimeException(e); - } - }); + .saml2Login( + saml2 -> { + try { + saml2.loginPage("/saml2") + .relyingPartyRegistrationRepository( + saml2RelyingPartyRegistrations) + .authenticationManager( + new ProviderManager(authenticationProvider)) + .successHandler( + new CustomSaml2AuthenticationSuccessHandler( + loginAttemptService, + applicationProperties, + userService)) + .failureHandler( + new CustomSaml2AuthenticationFailureHandler()) + .authenticationRequestResolver( + saml2AuthenticationRequestResolver); + } catch (Exception e) { + log.error("Error configuring SAML 2 login", e); + throw new RuntimeException(e); + } + }); } } else { log.debug("Login is not enabled."); diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java index bbc84821f..dec64c46f 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/DatabaseController.java @@ -26,6 +26,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import stirling.software.proprietary.security.database.H2SQLCondition; import stirling.software.proprietary.security.service.DatabaseService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index dec5905ba..e1abb6989 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -29,11 +29,11 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import stirling.software.proprietary.security.model.AuthenticationType; -import stirling.software.common.model.enumeration.Role; -import stirling.software.proprietary.security.model.User; import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.exception.UnsupportedProviderException; +import stirling.software.proprietary.security.model.AuthenticationType; +import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.model.api.user.UsernameAndPass; import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java index 311f81a4f..bdf1df32e 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/controller/web/AccountWebController.java @@ -29,12 +29,12 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.common.model.ApplicationProperties.Security.SAML2; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.oauth2.GitHubProvider; import stirling.software.common.model.oauth2.GoogleProvider; import stirling.software.common.model.oauth2.KeycloakProvider; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java index 835dc1917..6821414aa 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/ScheduledTasks.java @@ -1,10 +1,13 @@ package stirling.software.proprietary.security.database; import java.sql.SQLException; -import lombok.RequiredArgsConstructor; + import org.springframework.context.annotation.Conditional; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; + import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.proprietary.security.service.DatabaseServiceInterface; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java index a7773d859..e8d74ec01 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/AuthorityRepository.java @@ -4,6 +4,7 @@ import java.util.Set; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; + import stirling.software.proprietary.security.model.Authority; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java index b98a8094f..ec7a0078b 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/JPATokenRepositoryImpl.java @@ -5,6 +5,7 @@ import java.util.Date; import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import org.springframework.transaction.annotation.Transactional; + import stirling.software.proprietary.security.model.PersistentLogin; public class JPATokenRepositoryImpl implements PersistentTokenRepository { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java index a9ddf8a37..2ab956676 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/PersistentLoginRepository.java @@ -2,6 +2,7 @@ package stirling.software.proprietary.security.database.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; + import stirling.software.proprietary.security.model.PersistentLogin; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java index b7a7d7a84..78206b259 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/SessionRepository.java @@ -1,13 +1,16 @@ package stirling.software.proprietary.security.database.repository; -import jakarta.transaction.Transactional; import java.util.Date; import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; + +import jakarta.transaction.Transactional; + import stirling.software.proprietary.security.model.SessionEntity; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java index dcf84ee19..2a8d42096 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/database/repository/UserRepository.java @@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; + import stirling.software.proprietary.security.model.User; @Repository diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java index a96e6e769..3bae72195 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/FirstLoginFilter.java @@ -1,20 +1,24 @@ package stirling.software.proprietary.security.filter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Optional; + +import org.springframework.context.annotation.Lazy; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Optional; + import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; + import stirling.software.common.util.RequestUriUtils; import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java index ebc0f949e..028768c08 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/IPRateLimitingFilter.java @@ -1,15 +1,18 @@ package stirling.software.proprietary.security.filter; +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; + import lombok.RequiredArgsConstructor; + import stirling.software.common.util.RequestUriUtils; @RequiredArgsConstructor diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java index de97ec785..e9addd239 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java @@ -1,13 +1,9 @@ package stirling.software.proprietary.security.filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; @@ -20,6 +16,14 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.SAML2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java index 31db979b0..4d1d7bbed 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserBasedRateLimitingFilter.java @@ -1,17 +1,10 @@ package stirling.software.proprietary.security.filter; -import io.github.bucket4j.Bandwidth; -import io.github.bucket4j.Bucket; -import io.github.bucket4j.ConsumptionProbe; -import io.github.pixee.security.Newlines; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.time.Duration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; + import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; @@ -20,6 +13,17 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; + +import io.github.bucket4j.Bandwidth; +import io.github.bucket4j.Bucket; +import io.github.bucket4j.ConsumptionProbe; +import io.github.pixee.security.Newlines; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + import stirling.software.common.model.enumeration.Role; @Component diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 6dc32a85d..b364f3738 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -14,6 +14,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; + import stirling.software.common.model.enumeration.Role; @Entity diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java index 8fe3cebe6..4e9421aba 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/model/api/Email.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; + import stirling.software.common.model.api.GeneralFile; @Data diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java index 92b053b8a..7175a5b5d 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationFailureHandler.java @@ -1,10 +1,7 @@ package stirling.software.proprietary.security.oauth2; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; @@ -13,6 +10,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + @Slf4j public class CustomOAuth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java index 1c4d04e55..71bd42a85 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/CustomOAuth2AuthenticationSuccessHandler.java @@ -1,18 +1,22 @@ package stirling.software.proprietary.security.oauth2; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.sql.SQLException; -import lombok.RequiredArgsConstructor; + import org.springframework.security.authentication.LockedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.savedrequest.SavedRequest; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import lombok.RequiredArgsConstructor; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.exception.UnsupportedProviderException; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java index cb2771cc0..6516cc7d7 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/oauth2/OAuth2Configuration.java @@ -1,13 +1,16 @@ package stirling.software.proprietary.security.oauth2; +import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE; +import static stirling.software.common.util.ProviderUtils.validateProvider; +import static stirling.software.common.util.ValidationUtils.isStringEmpty; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; -import lombok.extern.slf4j.Slf4j; + import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -20,20 +23,20 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.oauth2.client.registration.ClientRegistrations; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.common.model.enumeration.UsernameAttribute; -import stirling.software.proprietary.security.model.exception.NoProviderFoundException; import stirling.software.common.model.oauth2.GitHubProvider; import stirling.software.common.model.oauth2.GoogleProvider; import stirling.software.common.model.oauth2.KeycloakProvider; import stirling.software.common.model.oauth2.Provider; import stirling.software.proprietary.security.model.User; +import stirling.software.proprietary.security.model.exception.NoProviderFoundException; import stirling.software.proprietary.security.service.UserService; -import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE; -import static stirling.software.common.util.ProviderUtils.validateProvider; -import static stirling.software.common.util.ValidationUtils.isStringEmpty; @Slf4j @Configuration diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java index c2957e241..fff03fd4f 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CertificateUtils.java @@ -6,6 +6,7 @@ import java.nio.charset.StandardCharsets; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; + import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java index 055ac8f4e..a39a39092 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticatedPrincipal.java @@ -3,6 +3,7 @@ package stirling.software.proprietary.security.saml2; import java.io.Serializable; import java.util.List; import java.util.Map; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java index a7e663aac..7bf0c3a3b 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationFailureHandler.java @@ -1,9 +1,7 @@ package stirling.software.proprietary.security.saml2; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import lombok.extern.slf4j.Slf4j; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.authentication.ProviderNotFoundException; import org.springframework.security.core.AuthenticationException; @@ -11,6 +9,11 @@ import org.springframework.security.saml2.core.Saml2Error; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + @Slf4j @ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java index 47391e4d0..2170a9632 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2AuthenticationSuccessHandler.java @@ -1,17 +1,21 @@ package stirling.software.proprietary.security.saml2; +import java.io.IOException; +import java.sql.SQLException; + +import org.springframework.security.authentication.LockedException; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.SavedRequest; + import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import java.io.IOException; -import java.sql.SQLException; + import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.LockedException; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.savedrequest.SavedRequest; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; import stirling.software.common.model.exception.UnsupportedProviderException; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java index d1c24b420..e8326c1e3 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/CustomSaml2ResponseAuthenticationConverter.java @@ -5,8 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.Attribute; @@ -17,6 +16,10 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.proprietary.security.model.User; import stirling.software.proprietary.security.service.UserService; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java index 836419ea0..233bcaadd 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/saml2/SAML2Configuration.java @@ -1,11 +1,9 @@ package stirling.software.proprietary.security.saml2; -import jakarta.servlet.http.HttpServletRequest; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.UUID; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.opensaml.saml.saml2.core.AuthnRequest; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -21,6 +19,12 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository; import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; + +import jakarta.servlet.http.HttpServletRequest; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.SAML2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java index 5687a3b92..19e300585 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/AppUpdateAuthService.java @@ -1,10 +1,13 @@ package stirling.software.proprietary.security.service; import java.util.Optional; -import lombok.RequiredArgsConstructor; + import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + import stirling.software.common.configuration.interfaces.ShowAdminInterface; import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.database.repository.UserRepository; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java index b889a06e5..0b286e894 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomOAuth2UserService.java @@ -1,7 +1,7 @@ package stirling.software.proprietary.security.service; import java.util.Optional; -import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.LockedException; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; @@ -10,6 +10,9 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.enumeration.UsernameAttribute; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java index 014666971..6ece48a4e 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/CustomUserDetailsService.java @@ -2,7 +2,7 @@ package stirling.software.proprietary.security.service; import java.util.Collection; import java.util.Set; -import lombok.RequiredArgsConstructor; + import org.springframework.security.authentication.LockedException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -10,6 +10,9 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + import stirling.software.proprietary.security.database.repository.UserRepository; import stirling.software.proprietary.security.model.Authority; import stirling.software.proprietary.security.model.User; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java index 37de87cf4..6474ae7ea 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/DatabaseService.java @@ -18,11 +18,15 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; + import javax.sql.DataSource; -import lombok.extern.slf4j.Slf4j; + import org.springframework.jdbc.datasource.init.CannotReadScriptException; import org.springframework.jdbc.datasource.init.ScriptException; import org.springframework.stereotype.Service; + +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.FileInfo; @@ -235,27 +239,27 @@ public class DatabaseService implements DatabaseServiceInterface { private boolean isH2Database() { boolean isTypeH2 = - datasourceProps.getType().equalsIgnoreCase(ApplicationProperties.Driver.H2.name()); + datasourceProps.getType().equalsIgnoreCase(ApplicationProperties.Driver.H2.name()); boolean isDBUrlH2 = - datasourceProps.getCustomDatabaseUrl().contains("h2") - || datasourceProps.getCustomDatabaseUrl().contains("H2"); + datasourceProps.getCustomDatabaseUrl().contains("h2") + || datasourceProps.getCustomDatabaseUrl().contains("H2"); boolean isCustomDatabase = datasourceProps.isEnableCustomDatabase(); if (isCustomDatabase) { if (isTypeH2 && !isDBUrlH2) { log.warn( - "Datasource type is H2, but the URL does not contain 'h2'. " - + "Please check your configuration."); + "Datasource type is H2, but the URL does not contain 'h2'. " + + "Please check your configuration."); throw new IllegalStateException( - "Datasource type is H2, but the URL does not contain 'h2'. Please check" - + " your configuration."); + "Datasource type is H2, but the URL does not contain 'h2'. Please check" + + " your configuration."); } else if (!isTypeH2 && isDBUrlH2) { log.warn( - "Datasource URL contains 'h2', but the type is not H2. " - + "Please check your configuration."); + "Datasource URL contains 'h2', but the type is not H2. " + + "Please check your configuration."); throw new IllegalStateException( - "Datasource URL contains 'h2', but the type is not H2. Please check your" - + " configuration."); + "Datasource URL contains 'h2', but the type is not H2. Please check your" + + " configuration."); } } boolean isH2 = isTypeH2 && isDBUrlH2; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java index 852fc8ab9..ecc04bac5 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/LoginAttemptService.java @@ -1,11 +1,15 @@ package stirling.software.proprietary.security.service; -import jakarta.annotation.PostConstruct; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; + +import org.springframework.stereotype.Service; + +import jakarta.annotation.PostConstruct; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; + import stirling.software.common.model.ApplicationProperties; import stirling.software.proprietary.security.model.AttemptCounter; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java b/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java index 7bf3e2643..0823f748b 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java @@ -1,6 +1,5 @@ package stirling.software.proprietary.security.service; -import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; @@ -9,8 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; + import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -25,10 +23,14 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import stirling.software.common.model.ApplicationProperties; +import stirling.software.common.model.enumeration.Role; import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.service.UserServiceInterface; -import stirling.software.common.model.enumeration.Role; import stirling.software.proprietary.security.database.repository.AuthorityRepository; import stirling.software.proprietary.security.database.repository.UserRepository; import stirling.software.proprietary.security.model.AuthenticationType; @@ -84,7 +86,7 @@ public class UserService implements UserServiceInterface { public Authentication getAuthentication(String apiKey) { Optional user = getUserByApiKey(apiKey); - if (!user.isPresent()) { + if (user.isEmpty()) { throw new UsernameNotFoundException("API key is not valid"); } // Convert the user into an Authentication object @@ -301,9 +303,7 @@ public class UserService implements UserServiceInterface { } public void changeUsername(User user, String newUsername) - throws IllegalArgumentException, - SQLException, - UnsupportedProviderException { + throws IllegalArgumentException, SQLException, UnsupportedProviderException { if (!isUsernameValid(newUsername)) { throw new IllegalArgumentException(getInvalidUsernameMessage()); } diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java index 7ed0f6506..b69dfaefb 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/CustomHttpSessionListener.java @@ -1,15 +1,17 @@ package stirling.software.proprietary.security.session; +import org.springframework.stereotype.Component; + import jakarta.servlet.http.HttpSessionEvent; import jakarta.servlet.http.HttpSessionListener; + import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; @Component @Slf4j public class CustomHttpSessionListener implements HttpSessionListener { - private SessionPersistentRegistry sessionPersistentRegistry; + private final SessionPersistentRegistry sessionPersistentRegistry; public CustomHttpSessionListener(SessionPersistentRegistry sessionPersistentRegistry) { super(); diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java index 5d482e94d..8931866ad 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionPersistentRegistry.java @@ -1,6 +1,5 @@ package stirling.software.proprietary.security.session; -import jakarta.transaction.Transactional; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -8,13 +7,18 @@ import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Optional; -import lombok.RequiredArgsConstructor; + import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; + +import jakarta.transaction.Transactional; + +import lombok.RequiredArgsConstructor; + import stirling.software.proprietary.security.database.repository.SessionRepository; import stirling.software.proprietary.security.model.SessionEntity; import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal; diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java index 75afbea9b..eccd7332e 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionRegistryConfig.java @@ -3,6 +3,7 @@ package stirling.software.proprietary.security.session; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.session.SessionRegistryImpl; + import stirling.software.proprietary.security.database.repository.SessionRepository; @Configuration @@ -14,7 +15,8 @@ public class SessionRegistryConfig { } @Bean - public SessionPersistentRegistry sessionPersistentRegistry(SessionRepository sessionRepository) { + public SessionPersistentRegistry sessionPersistentRegistry( + SessionRepository sessionRepository) { return new SessionPersistentRegistry(sessionRepository); } } diff --git a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java index 83403f9f7..1f491bf4d 100644 --- a/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java +++ b/proprietary/src/main/java/stirling/software/proprietary/security/session/SessionScheduled.java @@ -4,11 +4,13 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.List; -import lombok.RequiredArgsConstructor; + import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.core.session.SessionInformation; import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; + @Component @RequiredArgsConstructor public class SessionScheduled { diff --git a/scripts/download-security-jar.sh b/scripts/download-security-jar.sh index 8216179fa..bee188d97 100644 --- a/scripts/download-security-jar.sh +++ b/scripts/download-security-jar.sh @@ -1,6 +1,6 @@ echo "Running Stirling PDF with ADDITIONAL_FEATURES_OFF=${ADDITIONAL_FEATURES_OFF} and VERSION_TAG=${VERSION_TAG}" -# Check for DOCKER_ENABLE_SECURITY and download the appropriate JAR if required -if [ "$DOCKER_ENABLE_SECURITY" = "true" ] || [ "$ADDITIONAL_FEATURES_OFF" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then +# Check for $ADDITIONAL_FEATURES_OFF and download the appropriate JAR if required +if [ "$ADDITIONAL_FEATURES_OFF" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then if [ ! -f app-security.jar ]; then echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar" curl -L -o app-security.jar https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar diff --git a/testing/test.sh b/testing/test.sh index f1169ec17..0891c6bbd 100644 --- a/testing/test.sh +++ b/testing/test.sh @@ -214,7 +214,6 @@ main() { export DOCKER_CLI_EXPERIMENTAL=enabled export COMPOSE_DOCKER_CLI_BUILD=0 - export DOCKER_ENABLE_SECURITY=false export ADDITIONAL_FEATURES_OFF=true # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then @@ -243,7 +242,6 @@ main() { # run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml" # docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down - export DOCKER_ENABLE_SECURITY=true export ADDITIONAL_FEATURES_OFF=false # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then