From d2046c64d8495ab76dad143477e03f151cad5cba Mon Sep 17 00:00:00 2001 From: Ludy Date: Sun, 27 Oct 2024 23:17:36 +0100 Subject: [PATCH] Optimierung der SAML2-Integration und Verbesserung der Zertifikats- und Fehlerbehandlung (#2105) * certificate processing * Hides dialog when provider list is empty * removed: unused --- .../security/saml2/CertificateUtils.java | 50 ++++++++----------- .../controller/web/AccountWebController.java | 21 ++++++-- src/main/resources/templates/addUsers.html | 20 -------- 3 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/main/java/stirling/software/SPDF/config/security/saml2/CertificateUtils.java b/src/main/java/stirling/software/SPDF/config/security/saml2/CertificateUtils.java index 6a01ce0a..4f0d2488 100644 --- a/src/main/java/stirling/software/SPDF/config/security/saml2/CertificateUtils.java +++ b/src/main/java/stirling/software/SPDF/config/security/saml2/CertificateUtils.java @@ -1,48 +1,42 @@ package stirling.software.SPDF.config.security.saml2; import java.io.ByteArrayInputStream; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Base64; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; import org.springframework.core.io.Resource; -import org.springframework.util.FileCopyUtils; public class CertificateUtils { public static X509Certificate readCertificate(Resource certificateResource) throws Exception { - String certificateString = - new String( - FileCopyUtils.copyToByteArray(certificateResource.getInputStream()), - StandardCharsets.UTF_8); - String certContent = - certificateString - .replace("-----BEGIN CERTIFICATE-----", "") - .replace("-----END CERTIFICATE-----", "") - .replaceAll("\\R", "") - .replaceAll("\\s+", ""); - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - byte[] decodedCert = Base64.getDecoder().decode(certContent); - return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decodedCert)); + try (PemReader pemReader = + new PemReader( + new InputStreamReader( + certificateResource.getInputStream(), StandardCharsets.UTF_8))) { + PemObject pemObject = pemReader.readPemObject(); + byte[] decodedCert = pemObject.getContent(); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(decodedCert)); + } } public static RSAPrivateKey readPrivateKey(Resource privateKeyResource) throws Exception { - String privateKeyString = - new String( - FileCopyUtils.copyToByteArray(privateKeyResource.getInputStream()), - StandardCharsets.UTF_8); - String privateKeyContent = - privateKeyString - .replace("-----BEGIN PRIVATE KEY-----", "") - .replace("-----END PRIVATE KEY-----", "") - .replaceAll("\\R", "") - .replaceAll("\\s+", ""); - KeyFactory kf = KeyFactory.getInstance("RSA"); - byte[] decodedKey = Base64.getDecoder().decode(privateKeyContent); - return (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(decodedKey)); + try (PemReader pemReader = + new PemReader( + new InputStreamReader( + privateKeyResource.getInputStream(), StandardCharsets.UTF_8))) { + PemObject pemObject = pemReader.readPemObject(); + byte[] decodedKey = pemObject.getContent(); + return (RSAPrivateKey) + KeyFactory.getInstance("RSA") + .generatePrivate(new PKCS8EncodedKeySpec(decodedKey)); + } } } diff --git a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java index 8dcb2a9a..b4629020 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java @@ -89,10 +89,9 @@ public class AccountWebController { } SAML2 saml2 = securityProps.getSaml2(); - if (saml2 != null) { - if (saml2.getEnabled()) { - providerList.put("/saml2/authenticate/" + saml2.getRegistrationId(), "SAML 2"); - } + if (securityProps.isSaml2Activ() + && applicationProperties.getSystem().getEnableAlphaFunctionality()) { + providerList.put("/saml2/authenticate/" + saml2.getRegistrationId(), "SAML 2"); } // Remove any null keys/values from the providerList providerList @@ -101,7 +100,8 @@ public class AccountWebController { model.addAttribute("providerlist", providerList); model.addAttribute("loginMethod", securityProps.getLoginMethod()); - model.addAttribute("altLogin", securityProps.isAltLogin()); + boolean altLogin = providerList.size() > 0 ? securityProps.isAltLogin() : false; + model.addAttribute("altLogin", altLogin); model.addAttribute("currentPage", "login"); @@ -164,6 +164,17 @@ public class AccountWebController { case "userIsDisabled": erroroauth = "login.userIsDisabled"; break; + case "invalid_destination": + erroroauth = "login.invalid_destination"; + break; + // Valid InResponseTo was not available from the validation context, unable to + // evaluate + case "invalid_in_response_to": + erroroauth = "login.invalid_in_response_to"; + break; + case "not_authentication_provider_found": + erroroauth = "login.not_authentication_provider_found"; + break; default: break; } diff --git a/src/main/resources/templates/addUsers.html b/src/main/resources/templates/addUsers.html index e17e165a..ba020c4f 100644 --- a/src/main/resources/templates/addUsers.html +++ b/src/main/resources/templates/addUsers.html @@ -283,25 +283,5 @@ - \ No newline at end of file