]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20920 Add details about signature and encryption on the SAML Test page
authorMatteo Mara <matteo.mara@sonarsource.com>
Wed, 1 Nov 2023 16:32:04 +0000 (17:32 +0100)
committersonartech <sonartech@sonarsource.com>
Tue, 7 Nov 2023 20:02:50 +0000 (20:02 +0000)
server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticationStatus.java
server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticator.java
server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlStatusChecker.java
server/sonar-auth-saml/src/main/resources/samlAuthResult.html
server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlAuthStatusPageGeneratorTest.java
server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlStatusCheckerTest.java

index cb503d83f329e927617b02655a5ae41a64fcd99c..7ed5335d13d395348d5da55063739aab8ce4652e 100644 (file)
@@ -37,6 +37,10 @@ public class SamlAuthenticationStatus {
 
   private List<String> warnings = new ArrayList<>();
 
+  private boolean encryptionEnabled = false;
+
+  private boolean signatureEnabled = false;
+
   public String getStatus() {
     return status;
   }
@@ -76,4 +80,20 @@ public class SamlAuthenticationStatus {
   public void setWarnings(List<String> warnings) {
     this.warnings = warnings;
   }
+
+  public boolean isEncryptionEnabled() {
+    return encryptionEnabled;
+  }
+
+  public void setEncryptionEnabled(boolean encryptionEnabled) {
+    this.encryptionEnabled = encryptionEnabled;
+  }
+
+  public boolean isSignatureEnabled() {
+    return signatureEnabled;
+  }
+
+  public void setSignatureEnabled(boolean signatureEnabled) {
+    this.signatureEnabled = signatureEnabled;
+  }
 }
index 0504d35e96164399e59e8cf6698371d544952b76..f2917ebe24aa75741e2045ec3fa1bdf634e9d34f 100644 (file)
@@ -224,7 +224,7 @@ public class SamlAuthenticator {
   public String getAuthenticationStatusPage(HttpRequest request, HttpResponse response) {
     try {
       Auth auth = initSamlAuth(request, response);
-      return getSamlAuthStatusHtml(request, getSamlAuthenticationStatus(auth, samlSettings));
+      return getSamlAuthStatusHtml(request, getSamlAuthenticationStatus(request.getParameter("SAMLResponse"), auth, samlSettings));
     } catch (IllegalStateException e) {
       return getSamlAuthStatusHtml(request, getSamlAuthenticationStatus(String.format("%s due to: %s", e.getMessage(), e.getCause().getMessage())));
     }
index ec96d2aaa0bee084366e202589a19e96e21bc0fe..fe32cb6c7050e148887cf472863e0c86dc3d6e80 100644 (file)
 package org.sonar.auth.saml;
 
 import com.onelogin.saml2.Auth;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.annotation.Nullable;
 
 import static org.sonar.auth.saml.SamlSettings.GROUP_NAME_ATTRIBUTE;
 import static org.sonar.auth.saml.SamlSettings.USER_EMAIL_ATTRIBUTE;
@@ -35,11 +40,13 @@ import static org.sonar.auth.saml.SamlSettings.USER_NAME_ATTRIBUTE;
 
 public final class SamlStatusChecker {
 
+  private static final Pattern encryptedAssertionPattern = Pattern.compile("<saml:EncryptedAssertion|<EncryptedAssertion");
+
   private SamlStatusChecker() {
     throw new IllegalStateException("This Utility class cannot be instantiated");
   }
 
-  public static SamlAuthenticationStatus getSamlAuthenticationStatus(Auth auth, SamlSettings samlSettings) {
+  public static SamlAuthenticationStatus getSamlAuthenticationStatus(String samlResponse, Auth auth, SamlSettings samlSettings) {
 
     SamlAuthenticationStatus samlAuthenticationStatus = new SamlAuthenticationStatus();
 
@@ -59,6 +66,9 @@ public final class SamlStatusChecker {
     samlAuthenticationStatus.setAvailableAttributes(auth.getAttributes());
     samlAuthenticationStatus.setMappedAttributes(getAttributesMapping(auth, samlSettings));
 
+    samlAuthenticationStatus.setSignatureEnabled(isSignatureEnabled(auth, samlSettings));
+    samlAuthenticationStatus.setEncryptionEnabled(isEncryptionEnabled(auth, samlResponse));
+
     samlAuthenticationStatus.setWarnings(samlAuthenticationStatus.getErrors().isEmpty() ? generateWarnings(auth, samlSettings) : new ArrayList<>());
     samlAuthenticationStatus.setStatus(samlAuthenticationStatus.getErrors().isEmpty() ? "success" : "error");
 
@@ -136,4 +146,20 @@ public final class SamlStatusChecker {
       .map(entry -> String.format("Mapping found for the property %s, but the field %s is empty in the SAML response.", entry.getKey(), entry.getValue()))
       .toList();
   }
+
+  private static boolean isSignatureEnabled(Auth auth, SamlSettings samlSettings) {
+    return auth.isAuthenticated() && samlSettings.isSignRequestsEnabled();
+  }
+
+  private static boolean isEncryptionEnabled(Auth auth, @Nullable String samlResponse) {
+    if (samlResponse != null) {
+      byte[] decoded = Base64.getDecoder().decode(samlResponse);
+      String decodedResponse = new String(decoded, StandardCharsets.UTF_8);
+      Matcher matcher = encryptedAssertionPattern.matcher(decodedResponse);
+      //We assume that the presence of an encrypted assertion means that the response is encrypted
+      return matcher.find() && auth.isAuthenticated();
+    }
+    return false;
+  }
+
 }
index c7cf2554b3a762a98710cccee9b2f386bc3b2828..bff1c9ef20db6b39fadd5ff445a82bbc9e4aa647 100644 (file)
@@ -42,6 +42,7 @@
     <style>
       body {
         background-color: #f3f3f3;
+        font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
       }
 
       h1 {
       }
 
       .success {
-        background-color: #008a25;
+        background-color: #008223;
       }
+
+      .success-label {
+        color: #008223;
+      }
+
+      .label {
+        font-size: 20px;
+      }
+
+      .spacer-right {
+        margin-right: 10px;
+      }
+
     </style>
   </head>
 
         return node;
       }
 
+      function createEnabledLabel() {
+        const node = document.createElement("p");
+        node.innerHTML = '<svg class="spacer-right" height="16" version="1.1" viewBox="0 0 16 16" width="16" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule: evenodd; clip-rule: evenodd; stroke-linejoin: round; stroke-miterlimit: 1.41421;"><path d="M14.92 4.804q0 0.357-0.25 0.607l-7.679 7.679q-0.25 0.25-0.607 0.25t-0.607-0.25l-4.446-4.446q-0.25-0.25-0.25-0.607t0.25-0.607l1.214-1.214q0.25-0.25 0.607-0.25t0.607 0.25l2.625 2.634 5.857-5.866q0.25-0.25 0.607-0.25t0.607 0.25l1.214 1.214q0.25 0.25 0.25 0.607z" style="fill: currentcolor;"></path></svg>Enabled';
+        node.classList.add("success-label");
+        node.classList.add("label");
+        return node;
+      }
+
+      function createDisabledLabel() {
+        const node = document.createElement("p");
+        node.textContent = "Disabled";
+        node.classList.add("label");
+        return node;
+      }
+
       function createList(arr, className = "") {
         const list = document.createElement("ul");
 
       const mappings = decodedStatus.mappedAttributes;
       const errors = decodedStatus.errors;
       const warnings = decodedStatus.warnings;
+      const signatureEnabled = decodedStatus.signatureEnabled;
+      const encryptionEnabled = decodedStatus.encryptionEnabled;
 
       // Switch status class
       const statusNode = document.querySelector("#status");
         if (mappings && Object.keys(mappings).length > 0) {
           addSection(container, "Attribute mappings", createTable(mappings));
         }
+
+        addSection(container, "Signature of SAML requests", signatureEnabled ? createEnabledLabel() : createDisabledLabel());
+        addSection(container, "Encryption of SAML assertions", encryptionEnabled ? createEnabledLabel() : createDisabledLabel());
       }
       });
     </script>
index 2f84a89a6d740c5b98a98827783c03dc505214e6..56e867ae072efa876cc68c884229c8b622581e6c 100644 (file)
  */
 package org.sonar.auth.saml;
 
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import org.junit.Test;
 import org.sonar.api.server.http.HttpRequest;
 
@@ -30,22 +34,42 @@ import static org.mockito.Mockito.when;
 import static org.sonar.auth.saml.SamlAuthStatusPageGenerator.getSamlAuthStatusHtml;
 
 public class SamlAuthStatusPageGeneratorTest {
-  private static final String EMPTY_DATA_RESPONSE = "eyJ3YXJuaW5ncyI6W10sImF2YWlsYWJsZUF0dHJpYnV0ZXMiOnt9LCJlcnJvcnMiOltdLCJtYXBwZWRBdHRyaWJ1dGVzIjp7fX0=";
 
   @Test
   public void getSamlAuthStatusHtml_whenCalled_shouldGeneratePageWithData() {
     SamlAuthenticationStatus samlAuthenticationStatus = mock(SamlAuthenticationStatus.class);
     HttpRequest request = mock(HttpRequest.class);
 
-    when(samlAuthenticationStatus.getStatus()).thenReturn(null);
+    when(samlAuthenticationStatus.getStatus()).thenReturn("success");
     when(samlAuthenticationStatus.getErrors()).thenReturn(new ArrayList<>());
     when(samlAuthenticationStatus.getWarnings()).thenReturn(new ArrayList<>());
     when(samlAuthenticationStatus.getAvailableAttributes()).thenReturn(new HashMap<>());
     when(samlAuthenticationStatus.getMappedAttributes()).thenReturn(new HashMap<>());
+    when(samlAuthenticationStatus.isEncryptionEnabled()).thenReturn(false);
+    when(samlAuthenticationStatus.isSignatureEnabled()).thenReturn(false);
     when(request.getContextPath()).thenReturn("context");
 
-    String completeHtmlTemplate = getSamlAuthStatusHtml(request, samlAuthenticationStatus);
+    String decodedDataResponse = getDecodedDataResponse(getSamlAuthStatusHtml(request, samlAuthenticationStatus));
 
-    assertThat(completeHtmlTemplate).contains(EMPTY_DATA_RESPONSE);
+    assertThat(decodedDataResponse).contains(
+      "\"encryptionEnabled\":false",
+      "\"signatureEnabled\":false",
+      "\"errors\":[]",
+      "\"warnings\":[]",
+      "\"status\":\"success\"",
+      "\"availableAttributes\":{}",
+      "\"mappedAttributes\":{}");
+  }
+
+  private static String getDecodedDataResponse(String completeHtmlTemplate) {
+    String pattern = "data-response=\"([^\"]+)\"";
+    Pattern regex = Pattern.compile(pattern);
+    Matcher matcher = regex.matcher(completeHtmlTemplate);
+    if (matcher.find()) {
+      String dataResponseValue = matcher.group(1);
+      byte[] decoded = Base64.getDecoder().decode(dataResponseValue);
+      return new String(decoded, StandardCharsets.UTF_8);
+    }
+    return "";
   }
 }
index 74c93afe70b7b9e1f2ce332e6f34be8ce4b18c0c..a183e25a94213e60aa96825dae775de867212045 100644 (file)
@@ -21,7 +21,9 @@ package org.sonar.auth.saml;
 
 import com.onelogin.saml2.Auth;
 import com.onelogin.saml2.settings.Saml2Settings;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -47,9 +49,26 @@ import static org.sonar.auth.saml.SamlStatusChecker.getSamlAuthenticationStatus;
 public class SamlStatusCheckerTest {
 
   private static final String IDP_CERTIFICATE = "-----BEGIN CERTIFICATE-----MIIF5zCCA8+gAwIBAgIUIXv9OVs/XUicgR1bsV9uccYhHfowDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAkFVMQ8wDQYDVQQIDAZHRU5FVkExEDAOBgNVBAcMB1ZFUk5JRVIxDjAMBgNVBAoMBVNPTkFSMQ0wCwYDVQQLDARRVUJFMQ8wDQYDVQQDDAZaaXBlbmcxIDAeBgkqhkiG9w0BCQEWEW5vcmVwbHlAZ21haWwuY29tMB4XDTIyMDYxMzEzMTQyN1oXDTMyMDYxMDEzMTQyN1owgYIxCzAJBgNVBAYTAkFVMQ8wDQYDVQQIDAZHRU5FVkExEDAOBgNVBAcMB1ZFUk5JRVIxDjAMBgNVBAoMBVNPTkFSMQ0wCwYDVQQLDARRVUJFMQ8wDQYDVQQDDAZaaXBlbmcxIDAeBgkqhkiG9w0BCQEWEW5vcmVwbHlAZ21haWwuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu3nFXYvIYedpR84aZkdo/3yB5XHM+YCFJcDsVO10zEblLknfQsiMPa1Xd9Ustnpxw6P/SyzIJmO9jiMOdeCeY98a74jP7d4JPaO6h3l9IbWAcYeijQg956nlsVFY3FHDGr+7Pb8QcOAyV3v89jiF9DFB8wXS+5UfYr2OfoRRb4li39ezDyDdl5OLlM11nEss2z1mEv+sUUloTcyrgj37Psgewkvyym6tFGSgkV9Za4SVRhHFyThY1VFrYZSJFTnapUYaRc7kMxzwX/AAHUDJrmYcaVc5B8ODp4w2AxDJheQyCVfXjPFaUqBMG2U/rYfVXu0Za7Pn/vUo4UaSThwCBKDehCwz+65TLdA+NxyGDxnvY/SksOyLLGCmu8tKkXdu0pznnIhBXEGvjUIVS7d6a/8geg91NoTWau3i0RF+Dw/5N9DSzpld15bPtb5Ce3Bie19uvfvuH9eg+D8x/hfF6f3il4sPlIKdO/OVdM28LRfmDqmqQNPudvbqz7xy4ARuxk6ARa4d+aT9zovpwvxNGTr7h1mdgOUtUCdIXL3SHNjdwdAAz0uCWzvExbFu+NQ+V5+Xnkx71hyPFv9+DLVGIu7JhdYs806wKshO13Nga38ig6gu37lpVhfpZXhKywUiigG6LXAeyWWkMk+vlf9McZdMBD16dZP4kTsvP+rPVnUCAwEAAaNTMFEwHQYDVR0OBBYEFI5UVLtTySvbGqH7UP8xTL4wxZq3MB8GA1UdIwQYMBaAFI5UVLtTySvbGqH7UP8xTL4wxZq3MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBABAtXsKNWx0sDDFA53qZ1zRyWKWAMoh95pawFCrKgTEW4ZrA73pa790eE1Y+vT6qUXKI4li9skIDa+6psCdxhZIrHPRAnVZVeB2373Bxr5bw/XQ8elRCjWeMULbYJ9tgsLV0I9CiEP0a6Tm8t0yDVXNUfx36E5fkgLSrxoRo8XJzxHbJCnLVXHdaNBxOT7jVcom6Wo4PB2bsjVzhHm6amn5hZp4dMHm0Mv0ln1wH8jVnizHQBLsGMzvvl58+9s1pP17ceRDkpNDz+EQyA+ZArqkW1MqtwVhbzz8QgMprhflKkArrsC7v06Jv8fqUbn9LvtYK9IwHTX7J8dFcsO/gUC5PevYT3nriN3Azb20ggSQ1yOEMozvj5T96S6itfHPit7vyEQ84JPrEqfuQDZQ/LKZQqfvuXX1aAG3TU3TMWB9VMMFsTuMFS8bfrhMX77g0Ud4qJcBOYOH3hR59agSdd2QZNLP3zZsYQHLLQkq94jdTXKTqm/w7mlPFKV59HjTbHBhTtxBHMft/mvvLEuC9KKFfAOXYQ6V+s9Nk0BW4ggEfewaX58OBuy7ISqRtRFPGia18YRzzHqkhjubJYMPkIfYpFVd+C0II3F0kdy8TtpccjyKo9bcHMLxO4n8PDAl195CPthMi8gUvT008LGEotr+3kXsouTEZTT0glXKLdO2W-----END CERTIFICATE-----";
-
   private static final String SP_CERTIFICATE = "MIICoTCCAYkCBgGBXPscaDANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlzb25hcnF1YmUwHhcNMjIwNjEzMTIxMTA5WhcNMzIwNjEzMTIxMjQ5WjAUMRIwEAYDVQQDDAlzb25hcnF1YmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSFoT371C0/klZuPgvKbGItkmTaf5CweNXL8u389d98aOXRpDQ7maTXdV/W+VcL8vUWg8yG6nn8CRwweYnGTNdn9UAdhgknvxQe3pq3EwOJyls4Fpiq6YTh+DQfiZUQizjFjDOr/GG5O2lNvTRkI4XZj/XnWjRqVZwttiA5tm1sKkvGdyOQljwn4Jja/VbITdV8GASumx66Bil/wamSsqIzm2RjsOOGSsf5VjYUPwDobpuSf+j4DLtWjem/9vIzI2wcE30uC8LBAgO3JAlIS9NQrchjS9xhMJRohOoitaSPmqsOy7D2BH0h7XX6TNgv/WYTkBY4eZPao3PsL2A6AmhAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAMBmTHUK4w+DX21tmhqdwq0WqLH5ZAkwtiocDxFXiJ4GRrUWUh3BaXsgOHB8YYnNTDfScjaU0sZMEyfC0su1zsN8B7NFckg7RcZCHuBYdgIEAmvK4YM6s6zNsiKKwt66p2MNeL+o0acrT2rYjQ1L5QDj0gpfJQAT4N7xTZfuSc2iwjotaQfvcgsO8EZlcDVrL4UuyWLbuRUlSQjxHWGYaxCW+I3enK1+8fGpF3O+k9ZQ8xt5nJsalpsZvHcPLA4IBOmjsSHqSkhg4EIAWL/sJZ1KNct4hHh5kToUTu+Q6e949VeBkWgj4O+rcGDgiN2frGiEEc0EMv8KCSENRRRrO2k=";
   private static final String SP_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDSFoT371C0/klZuPgvKbGItkmTaf5CweNXL8u389d98aOXRpDQ7maTXdV/W+VcL8vUWg8yG6nn8CRwweYnGTNdn9UAdhgknvxQe3pq3EwOJyls4Fpiq6YTh+DQfiZUQizjFjDOr/GG5O2lNvTRkI4XZj/XnWjRqVZwttiA5tm1sKkvGdyOQljwn4Jja/VbITdV8GASumx66Bil/wamSsqIzm2RjsOOGSsf5VjYUPwDobpuSf+j4DLtWjem/9vIzI2wcE30uC8LBAgO3JAlIS9NQrchjS9xhMJRohOoitaSPmqsOy7D2BH0h7XX6TNgv/WYTkBY4eZPao3PsL2A6AmhAgMBAAECggEBAJj11HJAR96/leBBkFGmZaBIOGGgNoOcb023evfADhGgsZ8evamhKgX5t8w2uFPaaOl/eLje82Hvslh2lH+7FW8BRDBFy2Y+ay6d+I99PdLAKKUg5C4bE5v8vm6OqpGGbPAZ5AdYit3QKEa2MKG0QgA/bhQqg3rDdDA0sIWJjtF9MLv7LI7Tm0qgiHOKsI0MEBFk+ZoibgKWYh/dnfGDRWyC3Puqe13rdSheNJYUDR/0QMkd/EJNpLWv06uk+w8w2lU4RgN6TiV76ZZUIGZAAHFgMELJysgtBTCkOQY5roPu17OmMZjKfxngeIfNyd42q3/T6DmUbbwNYfP2HRMoiMECgYEA6SVc1mZ4ykytC9M61rZwT+2zXtJKudQVa0qpTtkf0aznRmnDOuc1bL7ewKIIIp9r5HKVteO6SKgpHmrP+qmvbwZ0Pz51Zg0MetoSmT9m0599/tOU2k6OI09dvQ4Xa3ccN5Czl61Q/HkMeAIDny8MrhGVBwhallE4J4fm/OjuVK0CgYEA5q6IVgqZtfcV1azIF6uOFt6blfn142zrwq0fF39jog2f+4jXaBKw6L4aP0HvIL83UArGppYY31894bLb6YL4EjS2JNbABM2VnJpJd4oGopOE42GCZlZRpf751zOptYAN23NFSujLlfaUfMbyrqIbRFC2DCdzNTU50GT5SAXX80UCgYEAlyvQvHwJCjMZaTd3SU1WGZ1o1qzIIyHvGXh5u1Rxm0TfWPquyfys2WwRhxoI6FoyXRgnFp8oZIAU2VIstL1dsUGgEnnvKVKAqw/HS3Keu80IpziNpdeVtjN59mGysc2zkBvVNx38Cxh6Cz5TFt4s/JkN5ld2VU0oeglWrtph3qkCgYALszZ/BrKdJBcba1QKv0zJpCjIBpGOI2whx54YFwH6qi4/F8W1JZ2LcHjsVG/IfWpUyPciY+KHEdGVrPiyc04Zvkquu6WpmLPJ6ZloUrvbaxgGYF+4yRADF1ecrqYg6onJY6NUFVKeHI+TdJPCf75aTK2vGCEjxbtU8ooiOQmm8QKBgEGe9ZdrwTP9rMQ35jYtzU+dT06k1r9BE9Q8CmrXl0HwK717ZWboX4J0YoFjxZC8PDsMl3p46MJ83rKbLU728uKig1AkZo7/OedxTWvezjZ1+lDyjC2EguXbgY1ecSC2HbJh9g+v8RUuhWxuA7RYoW92xVtKj+6l4vMadVP4Myp8-----END PRIVATE KEY-----";
+  public static final String ENCRYPTED_SAML_RESPONSE = """
+    <samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+                    Destination="https:/localhost:8080/oauth2/callback/saml" ID="ID_3f1d5c29-691c-41b6-a9d4-c5ed2edc75bc"
+                    InResponseTo="ONELOGIN_3cb68484-6883-4bfe-926a-88b705312eae" IssueInstant="2023-11-02T10:40:12.085Z" Version="2.0">
+    <saml:EncryptedAssertion> Assertion Very Encrypted
+    </saml:EncryptedAssertion>
+    </samlp:Response>
+    """;
+  public static final String PLAIN_SAML_RESPONSE = """
+    <samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+                    Destination="https:/localhost:8080/oauth2/callback/saml" ID="ID_3f1d5c29-691c-41b6-a9d4-c5ed2edc75bc"
+                    InResponseTo="ONELOGIN_3cb68484-6883-4bfe-926a-88b705312eae" IssueInstant="2023-11-02T10:40:12.085Z" Version="2.0">
+    <saml:Assertion Assertion
+    </saml:Assertion>
+    </samlp:Response>
+    """;
+  public static final String BASE64_ENCRYPTED_SAML_RESPONSE = new String(Base64.getEncoder().encode(ENCRYPTED_SAML_RESPONSE.getBytes()), StandardCharsets.UTF_8);
+  public static final String BASE64_SAML_RESPONSE = new String(Base64.getEncoder().encode(PLAIN_SAML_RESPONSE.getBytes()), StandardCharsets.UTF_8);
 
   private final MapSettings settings = new MapSettings(new PropertyDefinitions(System2.INSTANCE, SamlSettings.definitions()));
 
@@ -66,7 +85,6 @@ public class SamlStatusCheckerTest {
 
   @Test
   public void authentication_status_has_errors_when_no_idp_certificate_is_provided() {
-
     samlAuthenticationStatus = getSamlAuthenticationStatus("error message");
 
     assertEquals("error", samlAuthenticationStatus.getStatus());
@@ -80,7 +98,7 @@ public class SamlStatusCheckerTest {
 
     getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value));
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("success", samlAuthenticationStatus.getStatus());
     assertTrue(samlAuthenticationStatus.getErrors().isEmpty());
@@ -93,7 +111,7 @@ public class SamlStatusCheckerTest {
     when(auth.getLastErrorReason()).thenReturn("Authentication failed due to a missing parameter.");
     when(auth.getAttributes()).thenReturn(getEmptyAttributes());
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("error", samlAuthenticationStatus.getStatus());
     assertFalse(samlAuthenticationStatus.getErrors().isEmpty());
@@ -112,7 +130,7 @@ public class SamlStatusCheckerTest {
     }
     when(auth.getAttributes()).thenReturn(getEmptyAttributes());
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("error", samlAuthenticationStatus.getStatus());
     assertFalse(samlAuthenticationStatus.getErrors().isEmpty());
@@ -129,7 +147,7 @@ public class SamlStatusCheckerTest {
 
     getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value));
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("success", samlAuthenticationStatus.getStatus());
     assertTrue(samlAuthenticationStatus.getErrors().isEmpty());
@@ -147,7 +165,7 @@ public class SamlStatusCheckerTest {
     settings.setProperty(USER_NAME_ATTRIBUTE, "wrongNameField");
     getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value));
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("error", samlAuthenticationStatus.getStatus());
     assertTrue(samlAuthenticationStatus.getWarnings().isEmpty());
@@ -164,7 +182,7 @@ public class SamlStatusCheckerTest {
     when(auth.getAttributes()).thenReturn(getEmptyAttributes());
     getEmptyAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value));
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("error", samlAuthenticationStatus.getStatus());
     assertTrue(samlAuthenticationStatus.getWarnings().isEmpty());
@@ -183,7 +201,7 @@ public class SamlStatusCheckerTest {
     settings.setProperty(GROUP_NAME_ATTRIBUTE, (String) null);
     getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value));
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("success", samlAuthenticationStatus.getStatus());
     assertTrue(samlAuthenticationStatus.getErrors().isEmpty());
@@ -195,7 +213,7 @@ public class SamlStatusCheckerTest {
     setSettings();
     getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value));
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("success", samlAuthenticationStatus.getStatus());
     assertTrue(samlAuthenticationStatus.getErrors().isEmpty());
@@ -210,7 +228,7 @@ public class SamlStatusCheckerTest {
     settings.setProperty("sonar.auth.saml.sp.privateKey.secured", (String) null);
     getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value));
 
-    samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig()));
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
 
     assertEquals("success", samlAuthenticationStatus.getStatus());
     assertTrue(samlAuthenticationStatus.getErrors().isEmpty());
@@ -222,6 +240,69 @@ public class SamlStatusCheckerTest {
     assertTrue(samlAuthenticationStatus.getMappedAttributes().keySet().containsAll(Set.of("User login value", "User name value", "User email value", "Groups value")));
   }
 
+  @Test
+  public void givenSignatureEnabled_whenUserIsAuthenticated_thenSamlStatusReportsItEnabled() {
+    setSettings();
+    settings.setProperty("sonar.auth.saml.signature.enabled", true);
+    when(auth.isAuthenticated()).thenReturn(true);
+
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
+
+    assertTrue(samlAuthenticationStatus.isSignatureEnabled());
+  }
+
+  @Test
+  public void givenSignatureDisabled_whenUserIsAuthenticated_thenSamlStatusReportsItDisabled() {
+    setSettings();
+    settings.setProperty("sonar.auth.saml.signature.enabled", false);
+    when(auth.isAuthenticated()).thenReturn(true);
+
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
+
+    assertFalse(samlAuthenticationStatus.isSignatureEnabled());
+  }
+
+  @Test
+  public void givenEncryptionEnabled_whenUserIsAuthenticated_thenSamlStatusReportsItEnabled() {
+    setSettings();
+    when(auth.isAuthenticated()).thenReturn(true);
+
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_ENCRYPTED_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
+
+    assertTrue(samlAuthenticationStatus.isEncryptionEnabled());
+  }
+
+  @Test
+  public void givenEncryptionDisabled_whenUserIsAuthenticated_thenSamlStatusReportsItDisabled() {
+    setSettings();
+    when(auth.isAuthenticated()).thenReturn(true);
+
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
+
+    assertFalse(samlAuthenticationStatus.isEncryptionEnabled());
+  }
+
+  @Test
+  public void whenUserIsNotAuthenticated_thenBothSignatureAndEncryptionAreReportedDisabled() {
+    setSettings();
+    when(auth.isAuthenticated()).thenReturn(false);
+    settings.setProperty("sonar.auth.saml.signature.enabled", true);
+
+    samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_ENCRYPTED_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig()));
+
+    assertFalse(samlAuthenticationStatus.isEncryptionEnabled());
+    assertFalse(samlAuthenticationStatus.isSignatureEnabled());
+  }
+
+  @Test
+  public void whenSamlResponseIsNull_thenEncryptionIsReportedDisabled() {
+    setSettings();
+
+    samlAuthenticationStatus = getSamlAuthenticationStatus(null, auth, new SamlSettings(settings.asConfig()));
+
+    assertFalse(samlAuthenticationStatus.isEncryptionEnabled());
+  }
+
   private void setSettings() {
     settings.setProperty("sonar.auth.saml.applicationId", "MyApp");
     settings.setProperty("sonar.auth.saml.providerId", "http://localhost:8080/auth/realms/sonarqube");