commit
9dc54815eb
6 changed files with 88 additions and 76 deletions
|
@ -73,75 +73,79 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
|
||||||
List<EntityDescriptorType.EDTChoiceType> choiceType = entityType.getChoiceType();
|
List<EntityDescriptorType.EDTChoiceType> choiceType = entityType.getChoiceType();
|
||||||
|
|
||||||
if (!choiceType.isEmpty()) {
|
if (!choiceType.isEmpty()) {
|
||||||
EntityDescriptorType.EDTChoiceType edtChoiceType = choiceType.get(0);
|
IDPSSODescriptorType idpDescriptor = null;
|
||||||
List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
|
|
||||||
|
|
||||||
if (!descriptors.isEmpty()) {
|
//Metadata documents can contain multiple Descriptors (See ADFS metadata documents) such as RoleDescriptor, SPSSODescriptor, IDPSSODescriptor.
|
||||||
EntityDescriptorType.EDTDescriptorChoiceType edtDescriptorChoiceType = descriptors.get(0);
|
//So we need to loop through to find the IDPSSODescriptor.
|
||||||
IDPSSODescriptorType idpDescriptor = edtDescriptorChoiceType.getIdpDescriptor();
|
for(EntityDescriptorType.EDTChoiceType edtChoiceType : entityType.getChoiceType()) {
|
||||||
|
List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
|
||||||
|
|
||||||
if (idpDescriptor != null) {
|
if(!descriptors.isEmpty() && descriptors.get(0).getIdpDescriptor() != null) {
|
||||||
SAMLIdentityProviderConfig samlIdentityProviderConfig = new SAMLIdentityProviderConfig();
|
idpDescriptor = descriptors.get(0).getIdpDescriptor();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
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 (defaultCertificate != null) {
|
|
||||||
if (samlIdentityProviderConfig.getSigningCertificate() == null) {
|
|
||||||
samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
|
|
||||||
samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return samlIdentityProviderConfig.getConfig();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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 (defaultCertificate != null) {
|
||||||
|
if (samlIdentityProviderConfig.getSigningCertificate() == null) {
|
||||||
|
samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
|
||||||
|
samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return samlIdentityProviderConfig.getConfig();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (ParsingException pe) {
|
} catch (ParsingException pe) {
|
||||||
throw new RuntimeException("Could not parse IdP SAML Metadata", pe);
|
throw new RuntimeException("Could not parse IdP SAML Metadata", pe);
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<outputDirectory>modules/system/layers/base</outputDirectory>
|
<outputDirectory>modules/system/layers/base</outputDirectory>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
<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>
|
<outputDirectory>standalone/configuration/themes</outputDirectory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/**</include>
|
<include>**/**</include>
|
||||||
|
|
|
@ -367,7 +367,7 @@ public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sign) {
|
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();
|
URI uri = builder.build();
|
||||||
String rawQuery = uri.getRawQuery();
|
String rawQuery = uri.getRawQuery();
|
||||||
Signature signature = signatureAlgorithm.createSignature();
|
Signature signature = signatureAlgorithm.createSignature();
|
||||||
|
|
|
@ -120,11 +120,12 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
|
||||||
protected Document document;
|
protected Document document;
|
||||||
|
|
||||||
public PostBindingBuilder(Document document) throws ProcessingException {
|
public PostBindingBuilder(Document document) throws ProcessingException {
|
||||||
if (encrypt) encryptDocument(document);
|
|
||||||
this.document = document;
|
this.document = document;
|
||||||
if (signAssertions) {
|
if (signAssertions) {
|
||||||
signAssertion(document);
|
signAssertion(document);
|
||||||
}
|
}
|
||||||
|
//Per SAML spec 6.2 Encrypting assertions must happen after the assertions are signed
|
||||||
|
if (encrypt) encryptDocument(document);
|
||||||
if (sign) {
|
if (sign) {
|
||||||
signDocument(document);
|
signDocument(document);
|
||||||
}
|
}
|
||||||
|
@ -151,11 +152,12 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
|
||||||
protected Document document;
|
protected Document document;
|
||||||
|
|
||||||
public RedirectBindingBuilder(Document document) throws ProcessingException {
|
public RedirectBindingBuilder(Document document) throws ProcessingException {
|
||||||
if (encrypt) encryptDocument(document);
|
|
||||||
this.document = document;
|
this.document = document;
|
||||||
if (signAssertions) {
|
if (signAssertions) {
|
||||||
signAssertion(document);
|
signAssertion(document);
|
||||||
}
|
}
|
||||||
|
//Per SAML spec 6.2 Encrypting assertions must happen after the assertions are signed
|
||||||
|
if (encrypt) encryptDocument(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Document getDocument() {
|
public Document getDocument() {
|
||||||
|
@ -340,7 +342,7 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sign) {
|
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();
|
URI uri = builder.build();
|
||||||
String rawQuery = uri.getRawQuery();
|
String rawQuery = uri.getRawQuery();
|
||||||
Signature signature = signatureAlgorithm.createSignature();
|
Signature signature = signatureAlgorithm.createSignature();
|
||||||
|
|
|
@ -448,8 +448,12 @@ public class SamlProtocol implements LoginProtocol {
|
||||||
if (roleListMapper == null) return;
|
if (roleListMapper == null) return;
|
||||||
AssertionType assertion = response.getAssertions().get(0).getAssertion();
|
AssertionType assertion = response.getAssertions().get(0).getAssertion();
|
||||||
AttributeStatementType attributeStatement = new AttributeStatementType();
|
AttributeStatementType attributeStatement = new AttributeStatementType();
|
||||||
assertion.addStatement(attributeStatement);
|
|
||||||
roleListMapper.mapper.mapRoles(attributeStatement, roleListMapper.model, session, userSession, clientSession);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,7 @@ import org.keycloak.services.validation.Validation;
|
||||||
import org.keycloak.social.SocialIdentityProvider;
|
import org.keycloak.social.SocialIdentityProvider;
|
||||||
import org.keycloak.util.ObjectUtil;
|
import org.keycloak.util.ObjectUtil;
|
||||||
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.*;
|
||||||
import javax.ws.rs.OPTIONS;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.QueryParam;
|
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.Response;
|
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);
|
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
|
@GET
|
||||||
@Path("/{provider_id}/login")
|
@Path("/{provider_id}/login")
|
||||||
public Response performLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {
|
public Response performLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {
|
||||||
|
|
Loading…
Reference in a new issue