Details
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
index 1cd28fd..4adeddf 100755
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
@@ -73,74 +73,78 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
List<EntityDescriptorType.EDTChoiceType> choiceType = entityType.getChoiceType();
if (!choiceType.isEmpty()) {
- EntityDescriptorType.EDTChoiceType edtChoiceType = choiceType.get(0);
- List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
-
- if (!descriptors.isEmpty()) {
- EntityDescriptorType.EDTDescriptorChoiceType edtDescriptorChoiceType = descriptors.get(0);
- IDPSSODescriptorType idpDescriptor = edtDescriptorChoiceType.getIdpDescriptor();
-
- if (idpDescriptor != null) {
- SAMLIdentityProviderConfig samlIdentityProviderConfig = new SAMLIdentityProviderConfig();
- String singleSignOnServiceUrl = null;
- boolean postBinding = false;
- for (EndpointType endpoint : idpDescriptor.getSingleSignOnService()) {
- if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
- singleSignOnServiceUrl = endpoint.getLocation().toString();
- postBinding = true;
- break;
- } else if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
- singleSignOnServiceUrl = endpoint.getLocation().toString();
- }
- }
- String singleLogoutServiceUrl = null;
- for (EndpointType endpoint : idpDescriptor.getSingleLogoutService()) {
- if (postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
- singleLogoutServiceUrl = endpoint.getLocation().toString();
- break;
- } else if (!postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
- singleLogoutServiceUrl = endpoint.getLocation().toString();
- break;
- }
+ IDPSSODescriptorType idpDescriptor = null;
+
+ //Metadata documents can contain multiple Descriptors (See ADFS metadata documents) such as RoleDescriptor, SPSSODescriptor, IDPSSODescriptor.
+ //So we need to loop through to find the IDPSSODescriptor.
+ for(EntityDescriptorType.EDTChoiceType edtChoiceType : entityType.getChoiceType()) {
+ List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
+ if(!descriptors.isEmpty() && descriptors.get(0).getIdpDescriptor() != null) {
+ idpDescriptor = descriptors.get(0).getIdpDescriptor();
+ }
+ }
+
+ if (idpDescriptor != null) {
+ SAMLIdentityProviderConfig samlIdentityProviderConfig = new SAMLIdentityProviderConfig();
+ String singleSignOnServiceUrl = null;
+ boolean postBinding = false;
+ for (EndpointType endpoint : idpDescriptor.getSingleSignOnService()) {
+ if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
+ singleSignOnServiceUrl = endpoint.getLocation().toString();
+ postBinding = true;
+ break;
+ } else if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
+ singleSignOnServiceUrl = endpoint.getLocation().toString();
}
- samlIdentityProviderConfig.setSingleLogoutServiceUrl(singleLogoutServiceUrl);
- samlIdentityProviderConfig.setSingleSignOnServiceUrl(singleSignOnServiceUrl);
- samlIdentityProviderConfig.setWantAuthnRequestsSigned(idpDescriptor.isWantAuthnRequestsSigned());
- samlIdentityProviderConfig.setValidateSignature(idpDescriptor.isWantAuthnRequestsSigned());
- samlIdentityProviderConfig.setPostBindingResponse(postBinding);
- samlIdentityProviderConfig.setPostBindingAuthnRequest(postBinding);
-
- List<KeyDescriptorType> keyDescriptor = idpDescriptor.getKeyDescriptor();
- String defaultCertificate = null;
-
- if (keyDescriptor != null) {
- for (KeyDescriptorType keyDescriptorType : keyDescriptor) {
- Element keyInfo = keyDescriptorType.getKeyInfo();
- Element x509KeyInfo = DocumentUtil.getChildElement(keyInfo, new QName("dsig", "X509Certificate"));
-
- if (KeyTypes.SIGNING.equals(keyDescriptorType.getUse())) {
- samlIdentityProviderConfig.setSigningCertificate(x509KeyInfo.getTextContent());
- } else if (KeyTypes.ENCRYPTION.equals(keyDescriptorType.getUse())) {
- samlIdentityProviderConfig.setEncryptionPublicKey(x509KeyInfo.getTextContent());
- } else if (keyDescriptorType.getUse() == null) {
- defaultCertificate = x509KeyInfo.getTextContent();
- }
- }
+ }
+ String singleLogoutServiceUrl = null;
+ for (EndpointType endpoint : idpDescriptor.getSingleLogoutService()) {
+ if (postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
+ singleLogoutServiceUrl = endpoint.getLocation().toString();
+ break;
+ } else if (!postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
+ singleLogoutServiceUrl = endpoint.getLocation().toString();
+ break;
}
- if (defaultCertificate != null) {
- if (samlIdentityProviderConfig.getSigningCertificate() == null) {
- samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
+ }
+ samlIdentityProviderConfig.setSingleLogoutServiceUrl(singleLogoutServiceUrl);
+ samlIdentityProviderConfig.setSingleSignOnServiceUrl(singleSignOnServiceUrl);
+ samlIdentityProviderConfig.setWantAuthnRequestsSigned(idpDescriptor.isWantAuthnRequestsSigned());
+ samlIdentityProviderConfig.setValidateSignature(idpDescriptor.isWantAuthnRequestsSigned());
+ samlIdentityProviderConfig.setPostBindingResponse(postBinding);
+ samlIdentityProviderConfig.setPostBindingAuthnRequest(postBinding);
+
+ List<KeyDescriptorType> keyDescriptor = idpDescriptor.getKeyDescriptor();
+ String defaultCertificate = null;
+
+ if (keyDescriptor != null) {
+ for (KeyDescriptorType keyDescriptorType : keyDescriptor) {
+ Element keyInfo = keyDescriptorType.getKeyInfo();
+ Element x509KeyInfo = DocumentUtil.getChildElement(keyInfo, new QName("dsig", "X509Certificate"));
+
+ if (KeyTypes.SIGNING.equals(keyDescriptorType.getUse())) {
+ samlIdentityProviderConfig.setSigningCertificate(x509KeyInfo.getTextContent());
+ } else if (KeyTypes.ENCRYPTION.equals(keyDescriptorType.getUse())) {
+ samlIdentityProviderConfig.setEncryptionPublicKey(x509KeyInfo.getTextContent());
+ } else if (keyDescriptorType.getUse() == null) {
+ defaultCertificate = x509KeyInfo.getTextContent();
}
+ }
+ }
- if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
- samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
- }
+ if (defaultCertificate != null) {
+ if (samlIdentityProviderConfig.getSigningCertificate() == null) {
+ samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
}
- return samlIdentityProviderConfig.getConfig();
+ if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
+ samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
+ }
}
+
+ return samlIdentityProviderConfig.getConfig();
}
}
} catch (ParsingException pe) {
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml b/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
index 9a9e490..83ee9e3 100755
--- a/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
@@ -14,7 +14,7 @@
<outputDirectory>modules/system/layers/base</outputDirectory>
</fileSet>
<fileSet>
- <directory>../../../forms/common-themes/src/main/resources/theme</directory>
+ <directory>../../../../forms/common-themes/src/main/resources/theme</directory>
<outputDirectory>standalone/configuration/themes</outputDirectory>
<includes>
<include>**/**</include>
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
index d2f3545..c1a1a68 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
@@ -367,7 +367,7 @@ public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
}
if (sign) {
- builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getJavaSignatureAlgorithm());
+ builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getXmlSignatureMethod());
URI uri = builder.build();
String rawQuery = uri.getRawQuery();
Signature signature = signatureAlgorithm.createSignature();
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
index c377206..b86452d 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
@@ -120,11 +120,12 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
protected Document document;
public PostBindingBuilder(Document document) throws ProcessingException {
- if (encrypt) encryptDocument(document);
this.document = document;
if (signAssertions) {
signAssertion(document);
}
+ //Per SAML spec 6.2 Encrypting assertions must happen after the assertions are signed
+ if (encrypt) encryptDocument(document);
if (sign) {
signDocument(document);
}
@@ -151,11 +152,12 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
protected Document document;
public RedirectBindingBuilder(Document document) throws ProcessingException {
- if (encrypt) encryptDocument(document);
this.document = document;
if (signAssertions) {
signAssertion(document);
}
+ //Per SAML spec 6.2 Encrypting assertions must happen after the assertions are signed
+ if (encrypt) encryptDocument(document);
}
public Document getDocument() {
@@ -340,7 +342,7 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
}
if (sign) {
- builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getJavaSignatureAlgorithm());
+ builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getXmlSignatureMethod());
URI uri = builder.build();
String rawQuery = uri.getRawQuery();
Signature signature = signatureAlgorithm.createSignature();
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index e4e8f6e..54dff3a 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -448,8 +448,12 @@ public class SamlProtocol implements LoginProtocol {
if (roleListMapper == null) return;
AssertionType assertion = response.getAssertions().get(0).getAssertion();
AttributeStatementType attributeStatement = new AttributeStatementType();
- assertion.addStatement(attributeStatement);
roleListMapper.mapper.mapRoles(attributeStatement, roleListMapper.model, session, userSession, clientSession);
+
+ //SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
+ if(attributeStatement.getAttributes().size() > 0) {
+ assertion.addStatement(attributeStatement);
+ }
}
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index f95d7d8..9bbfcf5 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -64,11 +64,7 @@ import org.keycloak.services.validation.Validation;
import org.keycloak.social.SocialIdentityProvider;
import org.keycloak.util.ObjectUtil;
-import javax.ws.rs.GET;
-import javax.ws.rs.OPTIONS;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.QueryParam;
+import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
@@ -130,6 +126,12 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
this.event = new EventBuilder(realmModel, session, clientConnection).event(EventType.IDENTITY_PROVIDER_LOGIN);
}
+ @POST
+ @Path("/{provider_id}/login")
+ public Response performPostLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {
+ return performLogin(providerId, code);
+ }
+
@GET
@Path("/{provider_id}/login")
public Response performLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {