diff --git a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
index 682f179..f4a89dd 100644
--- a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
+++ b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/profile/AbstractSamlAuthenticationHandler.java
@@ -51,10 +51,12 @@ import org.keycloak.saml.SAML2AuthnRequestBuilder;
import org.keycloak.saml.SAMLRequestParser;
import org.keycloak.saml.SignatureAlgorithm;
import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.util.Base64;
+import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
@@ -72,10 +74,14 @@ import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.util.*;
+
+import javax.xml.namespace.QName;
+
import org.keycloak.dom.saml.v2.SAML2Object;
import org.keycloak.dom.saml.v2.protocol.ExtensionsType;
import org.keycloak.rotation.KeyLocator;
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
+import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
/**
*
@@ -208,7 +214,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
return AuthOutcome.FAILED;
}
}
- return handleLoginResponse((ResponseType) statusResponse, postBinding, onCreateSession);
+ return handleLoginResponse(holder, postBinding, onCreateSession);
} finally {
sessionStore.setCurrentAction(SamlSessionStore.CurrentAction.NONE);
}
@@ -310,7 +316,8 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
return false;
}
- protected AuthOutcome handleLoginResponse(final ResponseType responseType, boolean postBinding, OnSessionCreated onCreateSession) {
+ protected AuthOutcome handleLoginResponse(SAMLDocumentHolder responseHolder, boolean postBinding, OnSessionCreated onCreateSession) {
+ final ResponseType responseType = (ResponseType) responseHolder.getSamlObject();
AssertionType assertion = null;
if (! isSuccessfulSamlResponse(responseType) || responseType.getAssertions() == null || responseType.getAssertions().isEmpty()) {
challenge = new AuthChallenge() {
@@ -355,11 +362,12 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
if (deployment.getIDP().getSingleSignOnService().validateAssertionSignature()) {
try {
- validateSamlSignature(new SAMLDocumentHolder(AssertionUtil.asDocument(assertion)), postBinding, GeneralConstants.SAML_RESPONSE_KEY);
+ validateSamlSignature(new SAMLDocumentHolder(buildAssertionDocument(responseHolder, assertion)), postBinding, GeneralConstants.SAML_RESPONSE_KEY);
} catch (VerificationException e) {
log.error("Failed to verify saml assertion signature", e);
challenge = new AuthChallenge() {
+
@Override
public boolean challenge(HttpFacade exchange) {
SamlAuthenticationError error = new SamlAuthenticationError(SamlAuthenticationError.Reason.INVALID_SIGNATURE, responseType);
@@ -374,8 +382,24 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
}
};
return AuthOutcome.FAILED;
- } catch (ProcessingException e) {
- e.printStackTrace();
+ } catch (Exception e) {
+ log.error("Error processing validation of SAML assertion: " + e.getMessage());
+ challenge = new AuthChallenge() {
+
+ @Override
+ public boolean challenge(HttpFacade exchange) {
+ SamlAuthenticationError error = new SamlAuthenticationError(SamlAuthenticationError.Reason.EXTRACTION_FAILURE);
+ exchange.getRequest().setError(error);
+ exchange.getResponse().sendError(403);
+ return true;
+ }
+
+ @Override
+ public int getResponseCode() {
+ return 403;
+ }
+ };
+ return AuthOutcome.FAILED;
}
}
@@ -473,6 +497,21 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
&& Objects.equals(responseType.getStatus().getStatusCode().getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get());
}
+ private Document buildAssertionDocument(final SAMLDocumentHolder responseHolder, AssertionType assertion) throws ConfigurationException, ProcessingException {
+ Element encryptedAssertion = org.keycloak.saml.common.util.DocumentUtil.getElement(responseHolder.getSamlDocument(), new QName(JBossSAMLConstants.ENCRYPTED_ASSERTION.get()));
+ if (encryptedAssertion != null) {
+ // encrypted assertion.
+ // We'll need to decrypt it first.
+ Document encryptedAssertionDocument = DocumentUtil.createDocument();
+ encryptedAssertionDocument.appendChild(encryptedAssertionDocument.importNode(encryptedAssertion, true));
+ Element assertionElement = XMLEncryptionUtil.decryptElementInDocument(encryptedAssertionDocument, deployment.getDecryptionKey());
+ Document assertionDocument = DocumentUtil.createDocument();
+ assertionDocument.appendChild(assertionDocument.importNode(assertionElement, true));
+ return assertionDocument;
+ }
+ return AssertionUtil.asDocument(assertion);
+ }
+
private String getAttributeValue(Object attrValue) {
String value = null;
if (attrValue instanceof String) {