From e9cc32de79272ed4b22806d9bbce4081ea591a77 Mon Sep 17 00:00:00 2001 From: oadham Date: Mon, 19 Jan 2026 11:41:52 +0100 Subject: [PATCH 1/3] Removed SerializedBrokeredIdentityContext from the patch tool --- patch-tool/keycloak-files.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/patch-tool/keycloak-files.txt b/patch-tool/keycloak-files.txt index 5229975..88e710c 100644 --- a/patch-tool/keycloak-files.txt +++ b/patch-tool/keycloak-files.txt @@ -1,4 +1,3 @@ -services/src/main/java/org/keycloak/authentication/authenticators/broker/util/SerializedBrokeredIdentityContext.java services/src/main/java/org/keycloak/broker/saml/mappers/AdvancedAttributeToRoleMapper.java services/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java services/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java From 8dd344c46fad6e21d8f4ec49ed87d301e5d49fe2 Mon Sep 17 00:00:00 2001 From: oadham Date: Mon, 19 Jan 2026 11:45:27 +0100 Subject: [PATCH 2/3] Pom to newest Keycloak patch of 26.5 (=26.5.1 atm) --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bf1ca6d..1a3c556 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ SAML v2.0 extensions that adds more configuration options to connect to SAML Service Providers. - 26.4 + 26.5 17 @@ -20,7 +20,7 @@ UTF-8 UTF-8 - 26.4.7 + 26.5.1 4.8.3.1 3.4.1 From a67bf9313980e7135403007defe1d7aad2bfb447 Mon Sep 17 00:00:00 2001 From: oadham Date: Mon, 19 Jan 2026 13:01:28 +0100 Subject: [PATCH 3/3] Applied patch 26.4->26.5 (mostly re-ordered imports) --- README.md | 4 +- .../broker/saml/SAMLDataMarshaller.java | 7 +- .../keycloak/broker/saml/SAMLEndpoint.java | 67 ++++++--- .../broker/saml/SAMLIdentityProvider.java | 33 +++-- .../AdvancedAttributeToRoleMapper.java | 11 +- .../saml/mappers/AttributeToRoleMapper.java | 10 +- .../saml/mappers/UserAttributeMapper.java | 19 ++- .../mappers/UserEncryptedAttributeMapper.java | 27 ++-- .../saml/mappers/UsernameTemplateMapper.java | 26 +++- .../saml/JaxrsSAML2BindingBuilder.java | 7 +- .../protocol/saml/SamlProtocolUtils.java | 11 +- .../saml/SAML2AuthnRequestBuilder.java | 10 +- .../keycloak/saml/SAMLRequestParser.java | 9 +- .../common/constants/JBossSAMLConstants.java | 7 +- .../api/saml/v2/request/SAML2Request.java | 4 +- .../api/saml/v2/response/SAML2Response.java | 21 +-- .../api/saml/v2/sig/SAML2Signature.java | 12 ++ .../core/parsers/saml/SAMLParser.java | 16 ++- .../AbstractStaxSamlAssertionParser.java | 3 +- .../saml/assertion/SAMLAssertionParser.java | 8 +- .../saml/assertion/SAMLAssertionQNames.java | 3 +- .../saml/assertion/SAMLAttributeParser.java | 14 +- .../SAMLAttributeStatementParser.java | 7 +- .../assertion/SAMLAttributeValueParser.java | 21 +-- .../SAMLAttributeConsumingServiceParser.java | 7 +- .../SAMLEntitiesDescriptorParser.java | 8 +- .../metadata/SAMLEntityDescriptorParser.java | 6 +- .../metadata/SAMLSPSSODescriptorParser.java | 9 +- .../protocol/SAMLArtifactResponseParser.java | 8 +- .../saml/protocol/SAMLResponseParser.java | 13 +- .../JBossSAMLAuthnResponseFactory.java | 7 +- .../v2/factories/SAMLAssertionFactory.java | 16 +-- .../core/saml/v2/util/AssertionUtil.java | 33 +++-- .../core/saml/v2/util/SAMLMetadataUtil.java | 10 +- .../core/saml/v2/writers/BaseWriter.java | 36 ++--- .../saml/v2/writers/SAMLAssertionWriter.java | 32 ++--- .../saml/v2/writers/SAMLMetadataWriter.java | 12 +- .../saml/v2/writers/SAMLRequestWriter.java | 15 +- .../saml/v2/writers/SAMLResponseWriter.java | 18 ++- .../core/util/XMLSignatureUtil.java | 107 +++++++++----- .../resources/IdentityBrokerService.java | 135 +++++++++++------- 41 files changed, 495 insertions(+), 334 deletions(-) diff --git a/README.md b/README.md index 3dba401..72a73a2 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ If you have trouble creating the patch, consult the Readme in the `/patch-tool` 6. Build the jar from the new branch and test it in our local environment with an eHerkenning-testmiddel. * A Keycloak upgrade might be needed beforehand. - * + * You could consider also testing it with DigiD using the simulator realm. 6. Create a branch, e.g. `27.2.x-once-PR-merged`, from the previous minor, e.g. `27.1` here. @@ -69,6 +69,8 @@ If you have trouble creating the patch, consult the Readme in the `/patch-tool` * Rename branch `{a}.{b+1}.x-once-PR-merged` to just `{a}.{b+1}.x`, e.g. `27.2.x`. * Remove branch `upgrade-to-{a}.{b+1}`. +10. Change the repository's main branch to the most recent version branch, `{a}.{b+1}.x`. + ## Building ```mvn clean package``` diff --git a/src/main/java/nl/first8/keycloak/broker/saml/SAMLDataMarshaller.java b/src/main/java/nl/first8/keycloak/broker/saml/SAMLDataMarshaller.java index c0b1ddd..be6dc51 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/SAMLDataMarshaller.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/SAMLDataMarshaller.java @@ -1,5 +1,9 @@ package nl.first8.keycloak.broker.saml; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import nl.first8.keycloak.dom.saml.v2.protocol.ResponseType; import nl.first8.keycloak.saml.common.constants.GeneralConstants; @@ -14,9 +18,6 @@ import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.StaxUtil; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.util.List; public class SAMLDataMarshaller extends DefaultDataMarshaller { diff --git a/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java b/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java index 752b4fc..e0d6120 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/SAMLEndpoint.java @@ -1,11 +1,41 @@ package nl.first8.keycloak.broker.saml; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.*; +import java.io.IOException; +import java.net.URI; +import java.security.Key; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Predicate; +import javax.xml.crypto.dsig.XMLSignature; +import javax.xml.namespace.QName; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriBuilder; +import jakarta.ws.rs.core.UriInfo; + import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import nl.first8.keycloak.dom.saml.v2.assertion.AttributeStatementType; import nl.first8.keycloak.dom.saml.v2.protocol.ResponseType; -import nl.first8.keycloak.protocol.saml.SamlProtocolUtils; import nl.first8.keycloak.saml.SAMLRequestParser; import nl.first8.keycloak.saml.common.constants.GeneralConstants; import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; @@ -15,7 +45,7 @@ import org.jboss.resteasy.reactive.NoCache; import org.keycloak.broker.provider.BrokeredIdentityContext; import org.keycloak.broker.provider.IdentityBrokerException; -import org.keycloak.broker.provider.IdentityProvider; +import org.keycloak.broker.provider.UserAuthenticationIdentityProvider; import org.keycloak.common.ClientConnection; import org.keycloak.common.VerificationException; import org.keycloak.common.util.Base64; @@ -35,7 +65,14 @@ import org.keycloak.models.*; import org.keycloak.protocol.LoginProtocol; import org.keycloak.protocol.LoginProtocolFactory; -import org.keycloak.protocol.saml.*; +import org.keycloak.protocol.saml.SAMLDecryptionKeysLocator; +import org.keycloak.protocol.saml.SamlMetadataKeyLocator; +import org.keycloak.protocol.saml.SamlMetadataPublicKeyLoader; +import org.keycloak.protocol.saml.SamlPrincipalType; +import org.keycloak.protocol.saml.SamlProtocol; +import org.keycloak.protocol.saml.SamlProtocolUtils; +import org.keycloak.protocol.saml.SamlService; +import org.keycloak.protocol.saml.SamlSessionUtils; import org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor; import org.keycloak.rotation.HardcodedKeyLocator; import org.keycloak.rotation.KeyLocator; @@ -56,22 +93,12 @@ import org.keycloak.services.messages.Messages; import org.keycloak.services.util.CacheControlUtil; import org.keycloak.sessions.AuthenticationSessionModel; +import org.keycloak.util.Booleans; import org.keycloak.utils.StringUtil; + import org.w3c.dom.Element; import org.w3c.dom.NodeList; -import javax.xml.crypto.dsig.XMLSignature; -import javax.xml.namespace.QName; -import java.io.IOException; -import java.net.URI; -import java.security.Key; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.*; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Predicate; - public class SAMLEndpoint { protected static final Logger logger = Logger.getLogger(SAMLEndpoint.class); public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX"; @@ -86,7 +113,7 @@ public class SAMLEndpoint { protected final RealmModel realm; protected EventBuilder event; protected final SAMLIdentityProviderConfig config; - protected final IdentityProvider.AuthenticationCallback callback; + protected final UserAuthenticationIdentityProvider.AuthenticationCallback callback; protected final SAMLIdentityProvider provider; private final DestinationValidator destinationValidator; @@ -100,7 +127,7 @@ public class SAMLEndpoint { public SAMLEndpoint(KeycloakSession session, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, - IdentityProvider.AuthenticationCallback callback, + UserAuthenticationIdentityProvider.AuthenticationCallback callback, DestinationValidator destinationValidator) { this.realm = session.getContext().getRealm(); this.config = config; @@ -526,7 +553,7 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h identity.setEmail(subjectNameID.getValue()); } - if (config.isStoreToken()) { + if (Booleans.isTrue(config.isStoreToken())) { identity.setToken(samlResponse); } diff --git a/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java b/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java index 1557d10..7d40aed 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/SAMLIdentityProvider.java @@ -1,4 +1,24 @@ package nl.first8.keycloak.broker.saml; + +import java.net.URI; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.xml.parsers.ParserConfigurationException; + +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriBuilder; +import jakarta.ws.rs.core.UriInfo; + import nl.first8.keycloak.dom.saml.v2.metadata.AttributeConsumingService; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; @@ -8,12 +28,12 @@ import nl.first8.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType; import nl.first8.keycloak.dom.saml.v2.metadata.EntityDescriptorType; import nl.first8.keycloak.protocol.saml.JaxrsSAML2BindingBuilder; +import org.keycloak.protocol.saml.SAMLEncryptionAlgorithms; import nl.first8.keycloak.saml.SAML2ArtifactResolutionBuilder; import nl.first8.keycloak.saml.SPMetadataDescriptorBuilder; import nl.first8.keycloak.saml.common.constants.GeneralConstants; import nl.first8.keycloak.saml.processing.api.saml.v2.request.SAML2Request; import nl.first8.keycloak.saml.processing.core.saml.v2.writers.SAMLMetadataWriter; -import org.jboss.logging.Logger; import org.keycloak.broker.provider.*; import org.keycloak.common.util.PemUtils; import org.keycloak.crypto.Algorithm; @@ -46,22 +66,19 @@ import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator; import org.keycloak.saml.validators.DestinationValidator; import org.keycloak.sessions.AuthenticationSessionModel; +import org.keycloak.util.Booleans; import org.keycloak.util.JsonSerialization; + +import org.jboss.logging.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLStreamWriter; import java.io.IOException; import java.io.StringWriter; -import java.net.URI; import java.net.URISyntaxException; -import java.security.KeyPair; -import java.security.cert.X509Certificate; -import java.util.*; -import java.util.stream.Collectors; import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC; @@ -115,7 +132,7 @@ public Response performLogin(AuthenticationRequest request) { Integer attributeConsumingServiceIndex = getConfig().getAttributeConsumingServiceIndex(); - String loginHint = getConfig().isLoginHint() ? request.getAuthenticationSession().getClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM) : null; + String loginHint = Booleans.isTrue(getConfig().isLoginHint()) ? request.getAuthenticationSession().getClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM) : null; Boolean allowCreate = null; if (getConfig().getConfig().get(org.keycloak.broker.saml.SAMLIdentityProviderConfig.ALLOW_CREATE) == null || getConfig().isAllowCreate()) allowCreate = Boolean.TRUE; diff --git a/src/main/java/nl/first8/keycloak/broker/saml/mappers/AdvancedAttributeToRoleMapper.java b/src/main/java/nl/first8/keycloak/broker/saml/mappers/AdvancedAttributeToRoleMapper.java index 838a5de..df0b6dd 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/mappers/AdvancedAttributeToRoleMapper.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/mappers/AdvancedAttributeToRoleMapper.java @@ -1,5 +1,13 @@ package nl.first8.keycloak.broker.saml.mappers; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + import nl.first8.keycloak.broker.saml.SAMLEndpoint; import nl.first8.keycloak.broker.saml.SAMLIdentityProviderFactory; import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; @@ -12,9 +20,6 @@ import org.keycloak.models.IdentityProviderSyncMode; import org.keycloak.provider.ProviderConfigProperty; -import java.util.*; -import java.util.stream.Collectors; - import static org.keycloak.utils.RegexUtils.valueMatchesRegex; public class AdvancedAttributeToRoleMapper extends AbstractAttributeToRoleMapper { diff --git a/src/main/java/nl/first8/keycloak/broker/saml/mappers/AttributeToRoleMapper.java b/src/main/java/nl/first8/keycloak/broker/saml/mappers/AttributeToRoleMapper.java index b4b6261..e43f5dd 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/mappers/AttributeToRoleMapper.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/mappers/AttributeToRoleMapper.java @@ -1,5 +1,13 @@ package nl.first8.keycloak.broker.saml.mappers; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + import nl.first8.keycloak.broker.saml.SAMLEndpoint; import nl.first8.keycloak.broker.saml.SAMLIdentityProviderFactory; import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; @@ -19,9 +27,9 @@ import org.keycloak.protocol.saml.mappers.SamlMetadataDescriptorUpdater; import org.keycloak.provider.ProviderConfigProperty; -import java.util.*; import java.util.stream.Collectors; + import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC; /** diff --git a/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserAttributeMapper.java b/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserAttributeMapper.java index 6f1f283..e0e54e3 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserAttributeMapper.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserAttributeMapper.java @@ -1,4 +1,18 @@ package nl.first8.keycloak.broker.saml.mappers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; + import nl.first8.keycloak.broker.saml.SAMLIdentityProviderFactory; import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import nl.first8.keycloak.dom.saml.v2.assertion.AttributeStatementType; @@ -28,11 +42,6 @@ import java.nio.charset.StandardCharsets; import java.security.PrivateKey; -import java.util.*; -import java.util.function.Consumer; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC; diff --git a/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserEncryptedAttributeMapper.java b/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserEncryptedAttributeMapper.java index 41bde10..0be565c 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserEncryptedAttributeMapper.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/mappers/UserEncryptedAttributeMapper.java @@ -1,6 +1,16 @@ package nl.first8.keycloak.broker.saml.mappers; -import org.keycloak.broker.saml.SAMLEndpoint; +import java.security.PrivateKey; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; + import nl.first8.keycloak.broker.saml.SAMLIdentityProviderFactory; import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import nl.first8.keycloak.dom.saml.v2.assertion.AttributeStatementType; @@ -11,27 +21,28 @@ import nl.first8.keycloak.protocol.saml.mappers.SamlMetadataDescriptorUpdater; import nl.first8.keycloak.saml.encryption.DecryptionException; import nl.first8.keycloak.saml.encryption.SamlDecrypter; + import org.jboss.logging.Logger; import org.keycloak.broker.provider.AbstractIdentityProviderMapper; import org.keycloak.broker.provider.BrokeredIdentityContext; +import org.keycloak.broker.saml.SAMLEndpoint; import org.keycloak.common.util.CollectionUtil; import org.keycloak.crypto.Algorithm; import org.keycloak.crypto.KeyUse; import org.keycloak.crypto.KeyWrapper; import org.keycloak.dom.saml.v2.assertion.AttributeType; -import org.keycloak.models.*; +import org.keycloak.models.IdentityProviderMapperModel; +import org.keycloak.models.IdentityProviderSyncMode; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.models.UserModel; import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.util.StringUtil; -import java.security.PrivateKey; -import java.util.*; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Collectors; - import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC; + public class UserEncryptedAttributeMapper extends AbstractIdentityProviderMapper implements SamlMetadataDescriptorUpdater { protected static final Logger logger = Logger.getLogger(UserEncryptedAttributeMapper.class); diff --git a/src/main/java/nl/first8/keycloak/broker/saml/mappers/UsernameTemplateMapper.java b/src/main/java/nl/first8/keycloak/broker/saml/mappers/UsernameTemplateMapper.java index ab46e63..aa15c63 100644 --- a/src/main/java/nl/first8/keycloak/broker/saml/mappers/UsernameTemplateMapper.java +++ b/src/main/java/nl/first8/keycloak/broker/saml/mappers/UsernameTemplateMapper.java @@ -1,5 +1,18 @@ package nl.first8.keycloak.broker.saml.mappers; +import java.security.PrivateKey; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.UnaryOperator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import nl.first8.keycloak.broker.saml.SAMLEndpoint; import nl.first8.keycloak.broker.saml.SAMLIdentityProviderFactory; import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; @@ -7,6 +20,7 @@ import nl.first8.keycloak.dom.saml.v2.assertion.SamlEncryptedId; import nl.first8.keycloak.saml.encryption.DecryptionException; import nl.first8.keycloak.saml.encryption.SamlDecrypter; + import org.jboss.logging.Logger; import org.keycloak.broker.provider.AbstractIdentityProviderMapper; import org.keycloak.broker.provider.BrokeredIdentityContext; @@ -16,16 +30,14 @@ import org.keycloak.dom.saml.v2.assertion.AttributeType; import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.assertion.SubjectType; -import org.keycloak.models.*; +import org.keycloak.models.IdentityProviderMapperModel; +import org.keycloak.models.IdentityProviderSyncMode; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.models.UserModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.provider.ProviderConfigProperty; -import java.security.PrivateKey; -import java.util.*; -import java.util.function.UnaryOperator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - public class UsernameTemplateMapper extends AbstractIdentityProviderMapper { protected static final Logger logger = Logger.getLogger(UsernameTemplateMapper.class); diff --git a/src/main/java/nl/first8/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java b/src/main/java/nl/first8/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java index c9180e1..937bcdc 100644 --- a/src/main/java/nl/first8/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java +++ b/src/main/java/nl/first8/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java @@ -1,5 +1,9 @@ package nl.first8.keycloak.protocol.saml; +import jakarta.ws.rs.core.*; +import java.io.IOException; +import java.net.URI; + import nl.first8.keycloak.broker.saml.SAMLIdentityProviderConfig; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpHeaders; @@ -36,14 +40,11 @@ import jakarta.xml.soap.SOAPEnvelope; import jakarta.xml.soap.SOAPException; import jakarta.xml.soap.SOAPMessage; -import jakarta.ws.rs.core.*; import javax.xml.XMLConstants; import javax.net.ssl.SSLContext; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.InputStream; -import java.net.URI; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateException; diff --git a/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java b/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java index 0fd3a99..81142f4 100644 --- a/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java +++ b/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java @@ -1,7 +1,5 @@ package nl.first8.keycloak.protocol.saml; -import jakarta.ws.rs.core.MultivaluedMap; -import jakarta.ws.rs.core.UriInfo; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.net.URI; @@ -10,8 +8,10 @@ import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import org.apache.xml.security.encryption.XMLCipher; -import org.jboss.logging.Logger; + +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.UriInfo; + import org.keycloak.common.VerificationException; import org.keycloak.common.util.PemUtils; import org.keycloak.crypto.KeyType; @@ -54,6 +54,9 @@ import org.keycloak.saml.processing.core.util.RedirectBindingSignatureUtil; import org.keycloak.saml.processing.web.util.RedirectBindingUtil; import org.keycloak.utils.StringUtil; + +import org.apache.xml.security.encryption.XMLCipher; +import org.jboss.logging.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; public class SamlProtocolUtils { diff --git a/src/main/java/nl/first8/keycloak/saml/SAML2AuthnRequestBuilder.java b/src/main/java/nl/first8/keycloak/saml/SAML2AuthnRequestBuilder.java index cf51b81..55cc115 100644 --- a/src/main/java/nl/first8/keycloak/saml/SAML2AuthnRequestBuilder.java +++ b/src/main/java/nl/first8/keycloak/saml/SAML2AuthnRequestBuilder.java @@ -1,6 +1,11 @@ package nl.first8.keycloak.saml; +import java.net.URI; +import java.util.LinkedList; +import java.util.List; + import nl.first8.keycloak.saml.processing.api.saml.v2.request.SAML2Request; + import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.assertion.SubjectType; import org.keycloak.dom.saml.v2.protocol.AuthnRequestType; @@ -13,11 +18,8 @@ import org.keycloak.saml.SamlProtocolExtensionsAwareBuilder; import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; -import org.w3c.dom.Document; -import java.net.URI; -import java.util.LinkedList; -import java.util.List; +import org.w3c.dom.Document; public class SAML2AuthnRequestBuilder implements SamlProtocolExtensionsAwareBuilder { diff --git a/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java b/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java index e7b22d9..fc0666e 100644 --- a/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java +++ b/src/main/java/nl/first8/keycloak/saml/SAMLRequestParser.java @@ -1,10 +1,13 @@ package nl.first8.keycloak.saml; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + import nl.first8.keycloak.saml.common.constants.GeneralConstants; import nl.first8.keycloak.saml.processing.api.saml.v2.response.SAML2Response; import org.jboss.logging.Logger; - import org.keycloak.common.util.StreamUtil; import org.keycloak.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLoggerFactory; @@ -13,10 +16,6 @@ import org.keycloak.saml.processing.web.util.PostBindingUtil; import org.keycloak.saml.processing.web.util.RedirectBindingUtil; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; - public class SAMLRequestParser { private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); protected static Logger log = Logger.getLogger(SAMLRequestParser.class); diff --git a/src/main/java/nl/first8/keycloak/saml/common/constants/JBossSAMLConstants.java b/src/main/java/nl/first8/keycloak/saml/common/constants/JBossSAMLConstants.java index 1dad044..d248fd3 100644 --- a/src/main/java/nl/first8/keycloak/saml/common/constants/JBossSAMLConstants.java +++ b/src/main/java/nl/first8/keycloak/saml/common/constants/JBossSAMLConstants.java @@ -6,7 +6,12 @@ import java.util.HashMap; import java.util.Map; import javax.xml.namespace.QName; -import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.*; + +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ASSERTION_NSURI; +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ECP_PROFILE; +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.METADATA_NSURI; +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI; +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.XMLDSIG_NSURI; /** * SAML Constants diff --git a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java index ef8ac89..42545ca 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java @@ -1,6 +1,5 @@ package nl.first8.keycloak.saml.processing.api.saml.v2.request; -import javax.xml.datatype.XMLGregorianCalendar; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -9,7 +8,10 @@ import java.io.Writer; import java.net.URI; import java.net.URL; +import javax.xml.datatype.XMLGregorianCalendar; + import nl.first8.keycloak.saml.processing.core.saml.v2.writers.SAMLRequestWriter; + import org.keycloak.dom.saml.v2.SAML2Object; import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.protocol.*; diff --git a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java index f1158d8..8817b2a 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java @@ -1,5 +1,17 @@ package nl.first8.keycloak.saml.processing.api.saml.v2.response; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; +import java.net.URI; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + import nl.first8.keycloak.saml.processing.core.parsers.saml.SAMLParser; import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.dom.saml.v2.SAML2Object; @@ -26,18 +38,11 @@ import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; import org.keycloak.saml.processing.core.saml.v2.writers.SAMLResponseWriter; import org.keycloak.saml.processing.core.util.JAXPValidationUtil; + import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; -import java.io.*; -import java.net.URI; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI; public class SAML2Response { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java index 47e9a86..a2ac63b 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java @@ -1,12 +1,24 @@ package nl.first8.keycloak.saml.processing.api.saml.v2.sig; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.cert.X509Certificate; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.parsers.ParserConfigurationException; + import nl.first8.keycloak.saml.processing.core.util.XMLSignatureUtil; + +import org.keycloak.rotation.KeyLocator; import org.keycloak.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.processing.core.util.SignatureUtilTransferObject; + import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/SAMLParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/SAMLParser.java index e09b0d9..9f64829 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/SAMLParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/SAMLParser.java @@ -1,11 +1,20 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml; +import java.util.HashMap; +import java.util.Map; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + import nl.first8.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionParser; import nl.first8.keycloak.saml.processing.core.parsers.saml.metadata.SAMLEntitiesDescriptorParser; import nl.first8.keycloak.saml.processing.core.parsers.saml.metadata.SAMLEntityDescriptorParser; import nl.first8.keycloak.saml.processing.core.parsers.saml.protocol.SAMLArtifactResponseParser; import nl.first8.keycloak.saml.processing.core.parsers.saml.protocol.SAMLResponseParser; + import org.jboss.logging.Logger; + import org.keycloak.saml.common.ErrorCodes; import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.exceptions.ParsingException; @@ -22,13 +31,6 @@ import org.keycloak.saml.processing.core.parsers.saml.protocol.*; import org.keycloak.saml.processing.core.saml.v1.SAML11Constants; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; -import java.util.HashMap; -import java.util.Map; - public class SAMLParser extends AbstractParser { protected static final Logger logger = Logger.getLogger(SAMLParser.class); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/AbstractStaxSamlAssertionParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/AbstractStaxSamlAssertionParser.java index d38a57c..690339a 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/AbstractStaxSamlAssertionParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/AbstractStaxSamlAssertionParser.java @@ -1,9 +1,10 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.assertion; +import javax.xml.namespace.QName; + import org.keycloak.saml.common.parsers.AbstractStaxParser; import org.keycloak.saml.processing.core.parsers.util.QNameEnumLookup; -import javax.xml.namespace.QName; public abstract class AbstractStaxSamlAssertionParser extends AbstractStaxParser { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionParser.java index 1c810d8..5a0cd27 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionParser.java @@ -1,5 +1,9 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.assertion; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.saml.common.ErrorCodes; import org.keycloak.saml.common.exceptions.ParsingException; @@ -10,10 +14,6 @@ import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; - public class SAMLAssertionParser extends AbstractStaxSamlAssertionParser { private static final String VERSION_2_0 = "2.0"; diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionQNames.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionQNames.java index 84a37dc..9af636b 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionQNames.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionQNames.java @@ -1,9 +1,10 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.assertion; +import javax.xml.namespace.QName; + import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.processing.core.parsers.saml.xmldsig.XmlDSigQNames; import org.keycloak.saml.processing.core.parsers.util.HasQName; -import javax.xml.namespace.QName; import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.XMLENC_NSURI; diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeParser.java index bc2b69c..5d09e13 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeParser.java @@ -1,14 +1,20 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.assertion; -import org.keycloak.dom.saml.v2.assertion.AttributeType; -import org.keycloak.saml.common.exceptions.ParsingException; -import org.keycloak.saml.common.util.StaxParserUtil; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; import javax.xml.stream.events.Attribute; import javax.xml.stream.events.StartElement; -import java.util.*; + +import org.keycloak.dom.saml.v2.assertion.AttributeType; +import org.keycloak.saml.common.exceptions.ParsingException; +import org.keycloak.saml.common.util.StaxParserUtil; public class SAMLAttributeParser extends AbstractStaxSamlAssertionParser { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeStatementParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeStatementParser.java index ee549a2..569d135 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeStatementParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeStatementParser.java @@ -1,13 +1,14 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.assertion; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import nl.first8.keycloak.dom.saml.v2.assertion.AttributeStatementType; import nl.first8.keycloak.dom.saml.v2.assertion.AttributeStatementType.ASTChoiceType; + import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.util.StaxParserUtil; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; - /** * Parse the in the saml assertion * diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java index 52ef7b6..7e93500 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java @@ -1,13 +1,24 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.assertion; +import java.io.StringWriter; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; +import java.util.Objects; +import javax.xml.namespace.QName; import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + import org.keycloak.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; @@ -16,16 +27,6 @@ import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; -import java.io.StringWriter; -import java.util.Objects; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.EndElement; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; public class SAMLAttributeValueParser implements StaxParser { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLAttributeConsumingServiceParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLAttributeConsumingServiceParser.java index 339e678..eacd36b 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLAttributeConsumingServiceParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLAttributeConsumingServiceParser.java @@ -1,6 +1,10 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.metadata; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import nl.first8.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType; + import org.keycloak.dom.saml.v2.metadata.LocalizedNameType; import org.keycloak.dom.saml.v2.metadata.RequestedAttributeType; import org.keycloak.saml.common.exceptions.ParsingException; @@ -9,9 +13,6 @@ import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLRequestedAttributeParser; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; - public class SAMLAttributeConsumingServiceParser extends AbstractStaxSamlMetadataParser { private static final SAMLAttributeConsumingServiceParser INSTANCE = new SAMLAttributeConsumingServiceParser(); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java index 0e8208c..5800fb1 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java @@ -1,16 +1,18 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.metadata; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import nl.first8.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType; + import org.keycloak.dom.saml.v2.metadata.ExtensionsType; import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.processing.core.parsers.saml.metadata.AbstractStaxSamlMetadataParser; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLExtensionsParser; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames; -import org.w3c.dom.Element; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; +import org.w3c.dom.Element; public class SAMLEntitiesDescriptorParser extends AbstractStaxSamlMetadataParser { private static final SAMLEntitiesDescriptorParser INSTANCE = new SAMLEntitiesDescriptorParser(); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java index 0775788..3fdfbac 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java @@ -1,5 +1,8 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.metadata; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import nl.first8.keycloak.dom.saml.v2.metadata.EntityDescriptorType; import nl.first8.keycloak.dom.saml.v2.metadata.SPSSODescriptorType; import org.keycloak.dom.saml.v2.metadata.AttributeAuthorityDescriptorType; @@ -10,9 +13,6 @@ import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.processing.core.parsers.saml.metadata.*; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; - import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.ENTITY_DESCRIPTOR; public class SAMLEntityDescriptorParser extends AbstractStaxSamlMetadataParser { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLSPSSODescriptorParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLSPSSODescriptorParser.java index ef9125d..9aa5eb8 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLSPSSODescriptorParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/metadata/SAMLSPSSODescriptorParser.java @@ -1,16 +1,17 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.metadata; +import java.util.List; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import nl.first8.keycloak.dom.saml.v2.metadata.SPSSODescriptorType; + import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLAssertionConsumerServiceParser; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLSSODescriptorTypeParser; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; -import java.util.List; - import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.SP_SSO_DESCRIPTOR; public class SAMLSPSSODescriptorParser extends SAMLSSODescriptorTypeParser { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLArtifactResponseParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLArtifactResponseParser.java index e195964..67bba01 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLArtifactResponseParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLArtifactResponseParser.java @@ -1,5 +1,9 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.protocol; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import org.keycloak.dom.saml.v2.protocol.ArtifactResponseType; import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.util.StaxParserUtil; @@ -8,10 +12,6 @@ import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; import org.w3c.dom.Element; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; - public class SAMLArtifactResponseParser extends SAMLStatusResponseTypeParser { private static final SAMLArtifactResponseParser INSTANCE = new SAMLArtifactResponseParser(); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLResponseParser.java b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLResponseParser.java index dcd786b..50dfa51 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLResponseParser.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/parsers/saml/protocol/SAMLResponseParser.java @@ -1,5 +1,9 @@ package nl.first8.keycloak.saml.processing.core.parsers.saml.protocol; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + import nl.first8.keycloak.dom.saml.v2.protocol.ResponseType; import nl.first8.keycloak.dom.saml.v2.protocol.ResponseType.RTChoiceType; import nl.first8.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionParser; @@ -10,13 +14,12 @@ import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLStatusParser; import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLStatusResponseTypeParser; import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil; -import org.w3c.dom.Element; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.StartElement; import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLEncryptedAssertionParser; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; -import javax.xml.datatype.XMLGregorianCalendar; + +import org.w3c.dom.Element; + + public class SAMLResponseParser extends SAMLStatusResponseTypeParser { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java index eccc621..8194af4 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java @@ -16,6 +16,9 @@ */ package nl.first8.keycloak.saml.processing.core.saml.v2.factories; +import java.net.URI; +import javax.xml.datatype.XMLGregorianCalendar; + import org.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType; import org.keycloak.dom.saml.v2.assertion.NameIDType; @@ -29,10 +32,8 @@ import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; -import org.w3c.dom.Element; -import javax.xml.datatype.XMLGregorianCalendar; -import java.net.URI; +import org.w3c.dom.Element; /** * Factory for the SAML v2 Authn Response diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java index 602a6ba..d02ad8e 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java @@ -16,20 +16,12 @@ */ package nl.first8.keycloak.saml.processing.core.saml.v2.factories; -import org.keycloak.dom.saml.v2.assertion.AssertionType; -import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType; -import org.keycloak.dom.saml.v2.assertion.ConditionAbstractType; -import org.keycloak.dom.saml.v2.assertion.ConditionsType; -import org.keycloak.dom.saml.v2.assertion.KeyInfoConfirmationDataType; -import org.keycloak.dom.saml.v2.assertion.NameIDType; -import org.keycloak.dom.saml.v2.assertion.StatementAbstractType; -import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationType; -import org.keycloak.dom.saml.v2.assertion.SubjectType; -import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType; - -import javax.xml.datatype.XMLGregorianCalendar; import java.net.URI; import java.util.List; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.keycloak.dom.saml.v2.assertion.*; +import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType; /** * Deal with {@code AssertionType} diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java index f90d395..ac38764 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java @@ -15,6 +15,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.stream.XMLEventReader; + import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import nl.first8.keycloak.dom.saml.v2.protocol.ResponseType; import nl.first8.keycloak.saml.common.constants.GeneralConstants; @@ -22,12 +35,9 @@ import nl.first8.keycloak.saml.processing.core.parsers.saml.SAMLParser; import nl.first8.keycloak.saml.processing.core.saml.v2.writers.SAMLAssertionWriter; import nl.first8.keycloak.saml.processing.core.util.XMLSignatureUtil; + +import org.keycloak.dom.saml.v1.assertion.*; import org.keycloak.dom.saml.v2.assertion.*; -import org.keycloak.dom.saml.v1.assertion.SAML11AssertionType; -import org.keycloak.dom.saml.v1.assertion.SAML11AttributeStatementType; -import org.keycloak.dom.saml.v1.assertion.SAML11AttributeType; -import org.keycloak.dom.saml.v1.assertion.SAML11ConditionsType; -import org.keycloak.dom.saml.v1.assertion.SAML11StatementAbstractType; import org.keycloak.dom.saml.v2.assertion.AttributeStatementType.ASTChoiceType; import org.keycloak.dom.saml.v2.assertion.SubjectType.STSubType; import org.keycloak.rotation.HardcodedKeyLocator; @@ -48,22 +58,11 @@ import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; import org.keycloak.saml.processing.core.util.JAXPValidationUtil; import org.keycloak.saml.processing.core.util.XMLEncryptionUtil; + import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.stream.XMLEventReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Set; - public class AssertionUtil { private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java index 67210af..d48829c 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java @@ -20,13 +20,8 @@ import java.security.cert.X509Certificate; import java.util.List; import java.util.function.Function; -import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType; -import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType; -import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType; -import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType; -import org.keycloak.dom.saml.v2.metadata.KeyTypes; -import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType; -import org.keycloak.dom.saml.v2.metadata.SSODescriptorType; + +import org.keycloak.dom.saml.v2.metadata.*; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ParsingException; @@ -34,6 +29,7 @@ import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.processing.core.parsers.saml.SAMLParser; import org.keycloak.saml.processing.core.util.XMLSignatureUtil; + import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java index d599784..d4e5945 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java @@ -1,38 +1,30 @@ package nl.first8.keycloak.saml.processing.core.saml.v2.writers; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; + import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; -import org.keycloak.dom.saml.v2.assertion.AttributeType; -import org.keycloak.dom.saml.v2.assertion.BaseIDAbstractType; -import org.keycloak.dom.saml.v2.assertion.EncryptedElementType; -import org.keycloak.dom.saml.v2.assertion.KeyInfoConfirmationDataType; -import org.keycloak.dom.saml.v2.assertion.NameIDType; -import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType; -import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationType; -import org.keycloak.dom.saml.v2.assertion.SubjectType; + +import org.keycloak.dom.saml.v2.assertion.*; import org.keycloak.dom.saml.v2.metadata.LocalizedNameType; +import org.keycloak.dom.saml.v2.protocol.ExtensionsType; import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType; +import org.keycloak.saml.SamlProtocolExtensionsAwareBuilder; import org.keycloak.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ASSERTION_NSURI; +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.StaxUtil; import org.keycloak.saml.common.util.StringUtil; import org.keycloak.saml.processing.core.saml.v2.util.StaxWriterUtil; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import java.net.URI; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import org.keycloak.dom.saml.v2.protocol.ExtensionsType; -import org.keycloak.saml.SamlProtocolExtensionsAwareBuilder; - -import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ASSERTION_NSURI; -import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI; - import org.w3c.dom.Element; import org.w3c.dom.Node; diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java index 315ee1b..8b15c03 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java @@ -1,36 +1,22 @@ package nl.first8.keycloak.saml.processing.core.saml.v2.writers; +import java.net.URI; +import java.util.List; +import java.util.Set; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; + import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import nl.first8.keycloak.dom.saml.v2.assertion.AttributeStatementType; import nl.first8.keycloak.dom.saml.v2.assertion.AttributeStatementType.ASTChoiceType; import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; import nl.first8.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionQNames; -import org.keycloak.dom.saml.v2.assertion.AdviceType; -import org.keycloak.dom.saml.v2.assertion.AttributeType; -import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType; -import org.keycloak.dom.saml.v2.assertion.AuthnContextClassRefType; -import org.keycloak.dom.saml.v2.assertion.AuthnContextDeclRefType; -import org.keycloak.dom.saml.v2.assertion.AuthnContextDeclType; -import org.keycloak.dom.saml.v2.assertion.AuthnContextType; -import org.keycloak.dom.saml.v2.assertion.AuthnStatementType; -import org.keycloak.dom.saml.v2.assertion.ConditionAbstractType; -import org.keycloak.dom.saml.v2.assertion.ConditionsType; -import org.keycloak.dom.saml.v2.assertion.EncryptedElementType; -import org.keycloak.dom.saml.v2.assertion.NameIDType; -import org.keycloak.dom.saml.v2.assertion.OneTimeUseType; -import org.keycloak.dom.saml.v2.assertion.StatementAbstractType; -import org.keycloak.dom.saml.v2.assertion.SubjectType; -import org.keycloak.dom.saml.v2.assertion.URIType; + +import org.keycloak.dom.saml.v2.assertion.*; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.StaxUtil; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import java.net.URI; -import java.util.List; -import java.util.Set; - import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ASSERTION_NSURI; /** diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java index c5f91ec..18ef302 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java @@ -1,9 +1,15 @@ package nl.first8.keycloak.saml.processing.core.saml.v2.writers; +import java.net.URI; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; + import nl.first8.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType; import nl.first8.keycloak.dom.saml.v2.metadata.EntityDescriptorType; import nl.first8.keycloak.dom.saml.v2.metadata.RequestedAttributeValueType; import nl.first8.keycloak.dom.saml.v2.metadata.SPSSODescriptorType; + import org.keycloak.dom.saml.v2.assertion.AttributeType; import org.keycloak.dom.saml.v2.metadata.*; import org.keycloak.dom.xmlsec.w3.xmlenc.EncryptionMethodType; @@ -11,12 +17,8 @@ import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.StaxUtil; -import org.w3c.dom.Element; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import java.net.URI; -import java.util.List; +import org.w3c.dom.Element; public class SAMLMetadataWriter extends BaseWriter { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java index 017340a..b9f6bc7 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java @@ -1,22 +1,23 @@ package nl.first8.keycloak.saml.processing.core.saml.v2.writers; +import java.net.URI; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; + import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; + import org.keycloak.dom.saml.v2.assertion.AttributeType; import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.assertion.SubjectType; import org.keycloak.dom.saml.v2.protocol.*; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; +import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.*; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.StaxUtil; import org.keycloak.saml.common.util.StringUtil; -import org.w3c.dom.Element; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import java.net.URI; -import java.util.List; - -import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.*; +import org.w3c.dom.Element; public class SAMLRequestWriter extends BaseWriter { diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java index fc17cd1..935f7f9 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java @@ -1,8 +1,14 @@ package nl.first8.keycloak.saml.processing.core.saml.v2.writers; +import java.net.URI; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; + import nl.first8.keycloak.dom.saml.v2.assertion.AssertionType; import nl.first8.keycloak.dom.saml.v2.protocol.ResponseType; import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; + import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType; import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.protocol.*; @@ -11,15 +17,12 @@ import org.keycloak.saml.common.util.StaxUtil; import org.keycloak.saml.common.util.StringUtil; import org.keycloak.saml.processing.core.saml.v2.writers.BaseWriter; -import org.w3c.dom.Element; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import java.net.URI; -import java.util.List; +import org.w3c.dom.Element; import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI; + public class SAMLResponseWriter extends BaseWriter { private final SAMLAssertionWriter assertionWriter; @@ -33,7 +36,6 @@ public SAMLResponseWriter(XMLStreamWriter writer) { * Write a {@code ResponseType} to stream * * @param response - * @param out * * @throws org.keycloak.saml.common.exceptions.ProcessingException */ @@ -130,7 +132,6 @@ public void write(ArtifactResponseType response) throws ProcessingException { * * @param response * @param qname QName of the starting element - * @param out * * @throws ProcessingException */ @@ -171,7 +172,6 @@ public void write(StatusResponseType response, QName qname) throws ProcessingExc * Write a {@code StatusType} to stream * * @param status - * @param out * * @throws ProcessingException */ @@ -200,7 +200,6 @@ public void write(StatusType status) throws ProcessingException { * Write a {@code StatusCodeType} to stream * * @param statusCodeType - * @param out * * @throws ProcessingException */ @@ -223,7 +222,6 @@ public void write(StatusCodeType statusCodeType) throws ProcessingException { * Write a {@code StatusDetailType} to stream * * @param statusDetailType - * @param out * * @throws ProcessingException */ diff --git a/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java b/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java index f375799..b470cc0 100644 --- a/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java +++ b/src/main/java/nl/first8/keycloak/saml/processing/core/util/XMLSignatureUtil.java @@ -1,39 +1,6 @@ package nl.first8.keycloak.saml.processing.core.util; -import nl.first8.keycloak.saml.common.constants.GeneralConstants; -import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; -import org.keycloak.common.util.Base64; -import org.keycloak.common.util.PemUtils; -import org.keycloak.dom.xmlsec.w3.xmldsig.DSAKeyValueType; -import org.keycloak.dom.xmlsec.w3.xmldsig.KeyValueType; -import org.keycloak.dom.xmlsec.w3.xmldsig.RSAKeyValueType; -import org.keycloak.dom.xmlsec.w3.xmldsig.SignatureType; -import org.keycloak.saml.common.PicketLinkLogger; -import org.keycloak.saml.common.PicketLinkLoggerFactory; -import org.keycloak.saml.common.constants.WSTrustConstants; -import org.keycloak.saml.common.exceptions.ConfigurationException; -import org.keycloak.saml.common.exceptions.ParsingException; -import org.keycloak.saml.common.exceptions.ProcessingException; -import org.keycloak.saml.common.util.*; -import org.keycloak.saml.processing.core.util.SignatureUtilTransferObject; -import org.w3c.dom.*; -import org.xml.sax.SAXException; - import jakarta.xml.bind.JAXBException; -import javax.xml.crypto.*; -import javax.xml.crypto.dsig.*; -import javax.xml.crypto.dsig.dom.DOMSignContext; -import javax.xml.crypto.dsig.dom.DOMValidateContext; -import javax.xml.crypto.dsig.keyinfo.KeyInfo; -import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; -import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; -import javax.xml.crypto.dsig.spec.TransformParameterSpec; -import javax.xml.namespace.QName; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.stream.StreamResult; import java.io.ByteArrayInputStream; import java.io.OutputStream; import java.security.*; @@ -42,15 +9,77 @@ import java.security.interfaces.DSAPublicKey; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; +import java.util.Base64; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; +import javax.xml.crypto.AlgorithmMethod; +import javax.xml.crypto.Data; +import javax.xml.crypto.KeySelector; +import javax.xml.crypto.KeySelectorException; +import javax.xml.crypto.KeySelectorResult; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.NodeSetData; +import javax.xml.crypto.URIReferenceException; +import javax.xml.crypto.XMLCryptoContext; +import javax.xml.crypto.XMLStructure; import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.SignedInfo; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLSignature; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.dom.DOMSignContext; +import javax.xml.crypto.dsig.dom.DOMValidateContext; +import javax.xml.crypto.dsig.keyinfo.KeyInfo; +import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; +import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; + +import nl.first8.keycloak.saml.common.constants.GeneralConstants; +import nl.first8.keycloak.saml.common.constants.JBossSAMLConstants; + +import org.keycloak.common.util.PemUtils; +import org.keycloak.dom.xmlsec.w3.xmldsig.DSAKeyValueType; +import org.keycloak.dom.xmlsec.w3.xmldsig.KeyValueType; +import org.keycloak.dom.xmlsec.w3.xmldsig.RSAKeyValueType; +import org.keycloak.dom.xmlsec.w3.xmldsig.SignatureType; import org.keycloak.rotation.KeyLocator; +import org.keycloak.saml.common.PicketLinkLogger; +import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; +import org.keycloak.saml.common.constants.WSTrustConstants; +import org.keycloak.saml.common.exceptions.ConfigurationException; +import org.keycloak.saml.common.exceptions.ParsingException; +import org.keycloak.saml.common.exceptions.ProcessingException; +import org.keycloak.saml.common.util.DocumentUtil; +import org.keycloak.saml.common.util.SecurityActions; +import org.keycloak.saml.common.util.StringUtil; +import org.keycloak.saml.common.util.SystemPropertiesUtil; +import org.keycloak.saml.common.util.TransformerUtil; +import org.keycloak.saml.processing.core.util.SignatureUtilTransferObject; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.xml.sax.SAXException; public class XMLSignatureUtil { @@ -725,8 +754,8 @@ public static KeyValueType createKeyValue(PublicKey key) { byte[] exponent = pubKey.getPublicExponent().toByteArray(); RSAKeyValueType rsaKeyValue = new RSAKeyValueType(); - rsaKeyValue.setModulus(Base64.encodeBytes(modulus).getBytes(GeneralConstants.SAML_CHARSET)); - rsaKeyValue.setExponent(Base64.encodeBytes(exponent).getBytes(GeneralConstants.SAML_CHARSET)); + rsaKeyValue.setModulus(Base64.getEncoder().encodeToString(modulus).getBytes(GeneralConstants.SAML_CHARSET)); + rsaKeyValue.setExponent(Base64.getEncoder().encodeToString(exponent).getBytes(GeneralConstants.SAML_CHARSET)); return rsaKeyValue; } else if (key instanceof DSAPublicKey) { DSAPublicKey pubKey = (DSAPublicKey) key; @@ -736,10 +765,10 @@ public static KeyValueType createKeyValue(PublicKey key) { byte[] Y = pubKey.getY().toByteArray(); DSAKeyValueType dsaKeyValue = new DSAKeyValueType(); - dsaKeyValue.setP(Base64.encodeBytes(P).getBytes(GeneralConstants.SAML_CHARSET)); - dsaKeyValue.setQ(Base64.encodeBytes(Q).getBytes(GeneralConstants.SAML_CHARSET)); - dsaKeyValue.setG(Base64.encodeBytes(G).getBytes(GeneralConstants.SAML_CHARSET)); - dsaKeyValue.setY(Base64.encodeBytes(Y).getBytes(GeneralConstants.SAML_CHARSET)); + dsaKeyValue.setP(Base64.getEncoder().encodeToString(P).getBytes(GeneralConstants.SAML_CHARSET)); + dsaKeyValue.setQ(Base64.getEncoder().encodeToString(Q).getBytes(GeneralConstants.SAML_CHARSET)); + dsaKeyValue.setG(Base64.getEncoder().encodeToString(G).getBytes(GeneralConstants.SAML_CHARSET)); + dsaKeyValue.setY(Base64.getEncoder().encodeToString(Y).getBytes(GeneralConstants.SAML_CHARSET)); return dsaKeyValue; } throw logger.unsupportedType(key.toString()); diff --git a/src/main/java/nl/first8/keycloak/services/resources/IdentityBrokerService.java b/src/main/java/nl/first8/keycloak/services/resources/IdentityBrokerService.java index 7cee9b5..7137a4c 100644 --- a/src/main/java/nl/first8/keycloak/services/resources/IdentityBrokerService.java +++ b/src/main/java/nl/first8/keycloak/services/resources/IdentityBrokerService.java @@ -1,22 +1,57 @@ package nl.first8.keycloak.services.resources; -import jakarta.ws.rs.*; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.OPTIONS; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status; import jakarta.ws.rs.core.UriBuilder; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.jboss.logging.Logger; import org.jboss.resteasy.reactive.NoCache; -import org.keycloak.authentication.authenticators.broker.IdpConfirmOverrideLinkAuthenticator; -import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext; -import org.keycloak.broker.provider.*; -import org.keycloak.broker.saml.SAMLEndpoint; import org.keycloak.OAuthErrorException; import org.keycloak.authentication.AuthenticationProcessor; +import org.keycloak.authentication.RequiredActionContext; import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator; +import org.keycloak.authentication.authenticators.broker.IdpConfirmOverrideLinkAuthenticator; import org.keycloak.authentication.authenticators.broker.util.PostBrokerLoginConstants; +import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext; import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator; +import org.keycloak.broker.provider.AbstractIdentityProvider; +import org.keycloak.broker.provider.AuthenticationRequest; +import org.keycloak.broker.provider.BrokeredIdentityContext; +import org.keycloak.broker.provider.ExchangeTokenToIdentityProviderToken; +import org.keycloak.broker.provider.IdentityBrokerException; +import org.keycloak.broker.provider.IdentityProvider; +import org.keycloak.broker.provider.IdentityProviderFactory; +import org.keycloak.broker.provider.IdentityProviderMapper; +import org.keycloak.broker.provider.IdentityProviderMapperSyncModeDelegate; +import org.keycloak.broker.provider.IdpLinkAction; +import org.keycloak.broker.provider.UserAuthenticationIdentityProvider; +import org.keycloak.broker.provider.util.IdentityBrokerState; import org.keycloak.broker.provider.util.IdentityBrokerState; +import org.keycloak.broker.saml.SAMLEndpoint; import org.keycloak.broker.social.SocialIdentityProvider; import org.keycloak.common.ClientConnection; import org.keycloak.common.util.Base64Url; @@ -48,7 +83,11 @@ import org.keycloak.services.ServicesLogger; import org.keycloak.services.Urls; import org.keycloak.services.cors.Cors; -import org.keycloak.services.managers.*; +import org.keycloak.services.managers.AppAuthManager; +import org.keycloak.services.managers.AuthenticationManager; +import org.keycloak.services.managers.AuthenticationSessionManager; +import org.keycloak.services.managers.BruteForceProtector; +import org.keycloak.services.managers.ClientSessionCode; import org.keycloak.services.messages.Messages; import org.keycloak.services.resources.LoginActionsService; import org.keycloak.services.resources.SessionCodeChecks; @@ -59,24 +98,10 @@ import org.keycloak.services.validation.Validation; import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.sessions.RootAuthenticationSessionModel; +import org.keycloak.util.Booleans; import org.keycloak.util.JsonSerialization; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class IdentityBrokerService implements IdentityProvider.AuthenticationCallback { +public class IdentityBrokerService implements UserAuthenticationIdentityProvider.AuthenticationCallback { // Authentication session note, which references identity provider that is currently linked private static final String LINKING_IDENTITY_PROVIDER = "LINKING_IDENTITY_PROVIDER"; @@ -192,12 +217,12 @@ public Response clientInitiatedAccountLinking(@PathParam("provider_alias") Strin return Response.status(302).location(builder.build()).build(); } - event.session(cookieResult.getSession()); - event.user(cookieResult.getUser()); - event.detail(Details.USERNAME, cookieResult.getUser().getUsername()); + event.session(cookieResult.session()); + event.user(cookieResult.user()); + event.detail(Details.USERNAME, cookieResult.user().getUsername()); AuthenticatedClientSessionModel clientSession = null; - for (AuthenticatedClientSessionModel cs : cookieResult.getSession().getAuthenticatedClientSessions().values()) { + for (AuthenticatedClientSessionModel cs : cookieResult.session().getAuthenticatedClientSessions().values()) { if (cs.getClient().getClientId().equals(clientId)) { byte[] decoded = Base64Url.decode(hash); MessageDigest md = null; @@ -206,7 +231,7 @@ public Response clientInitiatedAccountLinking(@PathParam("provider_alias") Strin } catch (NoSuchAlgorithmException e) { throw new ErrorPageException(session, Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST); } - String input = nonce + cookieResult.getSession().getId() + clientId + providerAlias; + String input = nonce + cookieResult.session().getId() + clientId + providerAlias; byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8)); if (MessageDigest.isEqual(decoded, check)) { clientSession = cs; @@ -253,7 +278,7 @@ public Response clientInitiatedAccountLinking(@PathParam("provider_alias") Strin // Create AuthenticationSessionModel with same ID like userSession and refresh cookie - UserSessionModel userSession = cookieResult.getSession(); + UserSessionModel userSession = cookieResult.session(); // Auth session with ID corresponding to our userSession may already exists in some rare cases (EG. if some client tried to login in another browser tab with "prompt=login") RootAuthenticationSessionModel rootAuthSession = session.authenticationSessions().getRootAuthenticationSession(realmModel, userSession.getId()); @@ -272,13 +297,13 @@ public Response clientInitiatedAccountLinking(@PathParam("provider_alias") Strin authSession.setProtocol(client.getProtocol()); authSession.setRedirectUri(redirectUri); authSession.setClientNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString()); - authSession.setAuthNote(LINKING_IDENTITY_PROVIDER, cookieResult.getSession().getId() + clientId + providerAlias); + authSession.setAuthNote(LINKING_IDENTITY_PROVIDER, cookieResult.session().getId() + clientId + providerAlias); event.detail(Details.CODE_ID, userSession.getId()); event.success(); try { - IdentityProvider identityProvider = getIdentityProvider(session, providerAlias); + UserAuthenticationIdentityProvider identityProvider = getIdentityProvider(session, providerAlias); Response response = identityProvider.performLogin(createAuthenticationRequest(identityProvider, providerAlias, clientSessionCode)); if (response != null) { @@ -333,16 +358,14 @@ public Response performLogin(@PathParam("provider_alias") String providerAlias, if (identityProviderModel == null) { throw new IdentityBrokerException("Identity Provider [" + providerAlias + "] not found."); } - if (identityProviderModel.isLinkOnly()) { + if (Booleans.isTrue(identityProviderModel.isLinkOnly())) { throw new IdentityBrokerException("Identity Provider [" + providerAlias + "] is not allowed to perform a login."); } if (clientSessionCode.getClientSession() != null && loginHint != null) { clientSessionCode.getClientSession().setClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint); } - IdentityProviderFactory providerFactory = getIdentityProviderFactory(session, identityProviderModel); - - IdentityProvider identityProvider = providerFactory.create(session, identityProviderModel); + UserAuthenticationIdentityProvider identityProvider = getIdentityProvider(session, identityProviderModel.getAlias()); Response response = identityProvider.performLogin(createAuthenticationRequest(identityProvider, providerAlias, clientSessionCode)); @@ -364,7 +387,7 @@ public Response performLogin(@PathParam("provider_alias") String providerAlias, } @Override - public Response retryLogin(IdentityProvider identityProvider, AuthenticationSessionModel authSession) { + public Response retryLogin(UserAuthenticationIdentityProvider identityProvider, AuthenticationSessionModel authSession) { ClientSessionCode clientSessionCode = new ClientSessionCode<>(session, realmModel, authSession); clientSessionCode.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name()); Response response = identityProvider.performLogin(createAuthenticationRequest(identityProvider, identityProvider.getConfig().getAlias(), clientSessionCode)); @@ -385,7 +408,7 @@ public Response retryLogin(IdentityProvider identityProvider, AuthenticationS @Path("{provider_alias}/endpoint") public Object getEndpoint(@PathParam("provider_alias") String providerAlias) { try { - IdentityProvider identityProvider = getIdentityProvider(session, providerAlias); + UserAuthenticationIdentityProvider identityProvider = getIdentityProvider(session, providerAlias); return identityProvider.callback(realmModel, this, event); } catch (IdentityBrokerException e) { throw new NotFoundException(e.getMessage()); @@ -422,10 +445,10 @@ private Response getToken(String providerAlias, boolean forceRetrieval) { .authenticate(); if (authResult != null) { - AccessToken token = authResult.getToken(); - ClientModel clientModel = authResult.getClient(); + AccessToken token = authResult.token(); + ClientModel clientModel = authResult.client(); event.client(clientModel); - event.user(authResult.getUser()); + event.user(authResult.user()); session.getContext().setClient(clientModel); @@ -439,18 +462,18 @@ private Response getToken(String providerAlias, boolean forceRetrieval) { } - IdentityProvider identityProvider = getIdentityProvider(session, providerAlias); + UserAuthenticationIdentityProvider identityProvider = getIdentityProvider(session, providerAlias); IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(providerAlias); - if (identityProviderConfig.isStoreToken()) { - FederatedIdentityModel identity = this.session.users().getFederatedIdentity(this.realmModel, authResult.getUser(), providerAlias); + if (Booleans.isTrue(identityProviderConfig.isStoreToken())) { + FederatedIdentityModel identity = this.session.users().getFederatedIdentity(this.realmModel, authResult.user(), providerAlias); if (identity == null) { - return corsResponse(badRequest("User [" + authResult.getUser().getId() + "] is not associated with identity provider [" + providerAlias + "]."), clientModel); + return corsResponse(badRequest("User [" + authResult.user().getId() + "] is not associated with identity provider [" + providerAlias + "]."), clientModel); } if (identity.getToken() == null) { - return corsResponse(notFound("No token stored for user [" + authResult.getUser().getId() + "] with associated identity provider [" + providerAlias + "]."), clientModel); + return corsResponse(notFound("No token stored for user [" + authResult.user().getId() + "] with associated identity provider [" + providerAlias + "]."), clientModel); } String oldToken = identity.getToken(); @@ -466,7 +489,7 @@ private Response getToken(String providerAlias, boolean forceRetrieval) { if (!Objects.equals(oldToken, identity.getToken())) { // The API of the IdentityProvider doesn't allow use to pass down the realm and the user, so we check if the token has changed, // and then update the store. - session.users().updateFederatedIdentity(session.getContext().getRealm(), authResult.getUser(), identity); + session.users().updateFederatedIdentity(session.getContext().getRealm(), authResult.user(), identity); } } } @@ -491,7 +514,7 @@ public Response authenticated(BrokeredIdentityContext context) { AuthenticationSessionModel authenticationSession = context.getAuthenticationSession(); String providerAlias = identityProviderConfig.getAlias(); - if (!identityProviderConfig.isStoreToken()) { + if (Booleans.isFalse(identityProviderConfig.isStoreToken())) { if (isDebugEnabled()) { logger.debugf("Token will not be stored for identity provider [%s].", providerAlias); } @@ -670,7 +693,7 @@ private Response afterFirstBrokerLogin(AuthenticationSessionModel authSession) { event.user(federatedUser); event.detail(Details.USERNAME, federatedUser.getUsername()); - if (context.getIdpConfig().isAddReadTokenRoleOnCreate()) { + if (Booleans.isTrue(context.getIdpConfig().isAddReadTokenRoleOnCreate())) { ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID); if (brokerClient == null) { throw new IdentityBrokerException("Client 'broker' not available. Maybe realm has not migrated to support the broker token exchange service"); @@ -694,7 +717,8 @@ private Response afterFirstBrokerLogin(AuthenticationSessionModel authSession) { logger.debugf("Registered new user '%s' after first login with identity provider '%s'. Identity provider username is '%s' . ", federatedUser.getUsername(), providerAlias, context.getUsername()); - context.getIdp().importNewUser(session, realmModel, federatedUser, context); + UserAuthenticationIdentityProvider idp = context.getIdp(); + idp.importNewUser(session, realmModel, federatedUser, context); KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); realmModel.getIdentityProviderMappersByAliasStream(providerAlias).forEach(mapper -> { IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory @@ -950,7 +974,7 @@ private Response performAccountLinking(AuthenticationSessionModel authSession, U if (federatedUser != null) { - if (context.getIdpConfig().isStoreToken()) { + if (Booleans.isTrue(context.getIdpConfig().isStoreToken())) { FederatedIdentityModel oldModel = this.session.users().getFederatedIdentity(this.realmModel, federatedUser, context.getIdpConfig().getAlias()); if (!ObjectUtil.isEqualOrBothNull(context.getToken(), oldModel.getToken())) { this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, newModel); @@ -1065,7 +1089,7 @@ private void migrateFederatedIdentityId(BrokeredIdentityContext context, UserMod } private void updateToken(BrokeredIdentityContext context, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) { - if (context.getIdpConfig().isStoreToken() && !ObjectUtil.isEqualOrBothNull(context.getToken(), federatedIdentityModel.getToken())) { + if (Booleans.isTrue(context.getIdpConfig().isStoreToken()) && !ObjectUtil.isEqualOrBothNull(context.getToken(), federatedIdentityModel.getToken())) { // like in OIDCIdentityProvider.exchangeStoredToken() // we shouldn't override the refresh token if it is null in the context and not null in the DB // as for google IDP it will be lost forever @@ -1180,7 +1204,7 @@ private Response checkPassiveLoginError(AuthenticationSessionModel authSession, return null; } - private AuthenticationRequest createAuthenticationRequest(IdentityProvider identityProvider, String providerAlias, ClientSessionCode clientSessionCode) { + private AuthenticationRequest createAuthenticationRequest(UserAuthenticationIdentityProvider identityProvider, String providerAlias, ClientSessionCode clientSessionCode) { AuthenticationSessionModel authSession = null; IdentityBrokerState encodedState = null; @@ -1281,19 +1305,20 @@ private Response notFound(String message) { throw ErrorResponse.error(message, Response.Status.NOT_FOUND); } - public static IdentityProvider getIdentityProvider(KeycloakSession session, String alias) { + public static UserAuthenticationIdentityProvider getIdentityProvider(KeycloakSession session, String alias) { IdentityProviderModel identityProviderModel = session.identityProviders().getByAlias(alias); - IdentityProvider identityProvider = getIdentityProvider(session, identityProviderModel); + UserAuthenticationIdentityProvider identityProvider = getIdentityProvider(session, identityProviderModel, UserAuthenticationIdentityProvider.class); if (identityProvider == null) { throw new IdentityBrokerException("Identity Provider [" + alias + "] not found."); } return identityProvider; } - public static IdentityProvider getIdentityProvider(KeycloakSession session, IdentityProviderModel identityProviderModel) { + public static > T getIdentityProvider(KeycloakSession session, IdentityProviderModel identityProviderModel, Class type) { if (identityProviderModel != null) { IdentityProviderFactory providerFactory = getIdentityProviderFactory(session, identityProviderModel); - return providerFactory != null ? providerFactory.create(session, identityProviderModel) : null; + IdentityProvider idp = providerFactory.create(session, identityProviderModel); + return type.isInstance(idp) ? type.cast(idp) : null; } return null; }