From 4448a3ed9286d401534bb8f257de6b644c8221b7 Mon Sep 17 00:00:00 2001 From: tom <119664967+tmzcode@users.noreply.github.com> Date: Thu, 7 Aug 2025 14:26:45 +0200 Subject: [PATCH 1/7] Support Keycloak 26.1.x and resolve API changes, add diffgen tool. --- pom.xml | 4 ++-- .../nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java | 4 ++-- .../keycloak/services/resources/IdentityBrokerService.java | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 64e3125..fabe70b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ UTF-8 UTF-8 - 26.0.0 + 26.1.5 4.8.3.1 3.4.1 @@ -383,4 +383,4 @@ - \ No newline at end of file + 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 11edd99..415f171 100644 --- a/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java +++ b/src/main/java/nl/first8/keycloak/protocol/saml/SamlProtocolUtils.java @@ -3,7 +3,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.net.URI; - +import java.nio.charset.StandardCharsets; import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; @@ -151,7 +151,7 @@ public static void verifyRedirectSignature(SAMLDocumentHolder documentHolder, Ke String decodedAlgorithm = RedirectBindingUtil.urlDecode(encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY)); SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm); if (!RedirectBindingSignatureUtil.validateRedirectBindingSignature(signatureAlgorithm, - rawQuery.getBytes("UTF-8"), decodedSignature, locator, keyId)) { + rawQuery.getBytes(StandardCharsets.UTF_8), decodedSignature, locator, keyId)) { throw new VerificationException("Invalid query param signature"); } } catch (Exception e) { 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 6d04761..21998ab 100644 --- a/src/main/java/nl/first8/keycloak/services/resources/IdentityBrokerService.java +++ b/src/main/java/nl/first8/keycloak/services/resources/IdentityBrokerService.java @@ -353,6 +353,8 @@ public Response performLogin(@PathParam("provider_alias") String providerAlias, } return response; } + } catch (WebApplicationException e) { + return e.getResponse(); } catch (IdentityBrokerException e) { return redirectToErrorPage(Response.Status.BAD_GATEWAY, Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerAlias); } catch (Exception e) { @@ -1123,7 +1125,7 @@ private AuthenticationSessionModel parseSessionCode(String code, String clientId private Response checkAccountManagementFailedLinking(AuthenticationSessionModel authSession, String error, Object... parameters) { UserSessionModel userSession = new AuthenticationSessionManager(session).getUserSession(authSession); - if (userSession != null && authSession.getClient() != null && authSession.getClient().getClientId().equals(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID)) { + if (userSession != null && authSession.getClient() != null) { this.event.event(EventType.FEDERATED_IDENTITY_LINK); UserModel user = userSession.getUser(); @@ -1154,7 +1156,7 @@ private Response checkPassiveLoginError(AuthenticationSessionModel authSession, .setHttpHeaders(headers) .setUriInfo(session.getContext().getUri()) .setEventBuilder(event); - return protocol.sendError(authSession, error); + return protocol.sendError(authSession, error, null); } return null; } From 1ba94490c72bdb1456ea4e89f69bd5ec3696a879 Mon Sep 17 00:00:00 2001 From: tom <119664967+tmzcode@users.noreply.github.com> Date: Thu, 7 Aug 2025 14:26:54 +0200 Subject: [PATCH 2/7] Support Keycloak 26.1.x and resolve API changes, add diffgen tool. --- diffgen.sh | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100755 diffgen.sh diff --git a/diffgen.sh b/diffgen.sh new file mode 100755 index 0000000..3cd9d8b --- /dev/null +++ b/diffgen.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +if [ $# -ne 2 ]; then + echo "Usage: $0 OLD_BRANCH NEW_BRANCH" + exit 1 +fi + +OLD_BRANCH="$1" +NEW_BRANCH="$2" + +echo "Comparing Java files between branches:" +echo " OLD_BRANCH: $OLD_BRANCH" +echo " NEW_BRANCH: $NEW_BRANCH" + +OLD_DIR="./diff/old" +NEW_DIR="./diff/new" +PATCH_FILE="./branch-diff.patch" + +FILES=( + 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 + services/src/main/java/org/keycloak/broker/saml/mappers/UsernameTemplateMapper.java + services/src/main/java/org/keycloak/broker/saml/SAMLDataMarshaller.java + services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java + services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java + services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java + services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java + saml-core-api/src/main/java/org/keycloak/dom/saml/v2/assertion/AssertionType.java + saml-core-api/src/main/java/org/keycloak/dom/saml/v2/assertion/AttributeStatementType.java + saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/AttributeConsumingServiceType.java + saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/EntitiesDescriptorType.java + saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/EntityDescriptorType.java + saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/SPSSODescriptorType.java + saml-core-api/src/main/java/org/keycloak/dom/saml/v2/protocol/ResponseType.java + services/src/main/java/org/keycloak/protocol/saml/mappers/SamlMetadataDescriptorUpdater.java + services/src/main/java/org/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java + services/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java + saml-core-api/src/main/java/org/keycloak/saml/common/constants/JBossSAMLConstants.java + saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java + saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java + saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java + saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/AbstractStaxSamlAssertionParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionQNames.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeStatementParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLAttributeConsumingServiceParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLSPSSODescriptorParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/protocol/SAMLArtifactResponseParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/protocol/SAMLResponseParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParser.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java + saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java + saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java + saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java + saml-core/src/main/java/org/keycloak/saml/SAMLRequestParser.java + services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java +) + +# Clean up any previous run +rm -rf "$OLD_DIR" "$NEW_DIR" "$PATCH_FILE" +mkdir -p "$OLD_DIR" "$NEW_DIR" + +echo "Exporting files..." + +for FILE in "${FILES[@]}"; do + mkdir -p "$OLD_DIR/$(dirname "$FILE")" + git show "$OLD_BRANCH:$FILE" > "$OLD_DIR/$FILE" 2>/dev/null || echo "Missing in $OLD_BRANCH: $FILE" + + mkdir -p "$NEW_DIR/$(dirname "$FILE")" + git show "$NEW_BRANCH:$FILE" > "$NEW_DIR/$FILE" 2>/dev/null || echo "Missing in $NEW_BRANCH: $FILE" +done + +echo "File count (.java only):" +echo " $OLD_BRANCH: $(find "$OLD_DIR" -type f -name '*.java' | wc -l)" +echo " $NEW_BRANCH: $(find "$NEW_DIR" -type f -name '*.java' | wc -l)" + +echo "Creating patch..." +diff --color=never -ruN "$OLD_DIR" "$NEW_DIR" > "$PATCH_FILE" + +# Post-process diff for portability or project-specific needs +safe_sed() { + sed "$1" "$2" > "$2.tmp" && mv "$2.tmp" "$2" +} + +safe_sed "s|$OLD_DIR/saml-core/||g" "$PATCH_FILE" +safe_sed "s|$NEW_DIR/saml-core/||g" "$PATCH_FILE" +safe_sed "s|$OLD_DIR/services/||g" "$PATCH_FILE" +safe_sed "s|$NEW_DIR/services/||g" "$PATCH_FILE" +safe_sed 's|org/keycloak/|nl/first8/keycloak/|g' "$PATCH_FILE" + +echo "Patch created at: $PATCH_FILE" From ca26e79a979ba7cbfddfd2c6317c00284f505237 Mon Sep 17 00:00:00 2001 From: tom <119664967+tmzcode@users.noreply.github.com> Date: Thu, 7 Aug 2025 14:38:03 +0200 Subject: [PATCH 3/7] Support Keycloak 26.1.x and resolve API changes, add diffgen tool. --- diffgen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffgen.sh b/diffgen.sh index 3cd9d8b..b6e0528 100755 --- a/diffgen.sh +++ b/diffgen.sh @@ -14,7 +14,7 @@ echo " NEW_BRANCH: $NEW_BRANCH" OLD_DIR="./diff/old" NEW_DIR="./diff/new" -PATCH_FILE="./branch-diff.patch" +PATCH_FILE="./diffgen.patch" FILES=( services/src/main/java/org/keycloak/authentication/authenticators/broker/util/SerializedBrokeredIdentityContext.java From e1a17f84dd03759c63b1e7442dcb07966d804f56 Mon Sep 17 00:00:00 2001 From: tom <119664967+tmzcode@users.noreply.github.com> Date: Fri, 8 Aug 2025 10:38:16 +0200 Subject: [PATCH 4/7] Support Keycloak 26.1.x and resolve API changes, add diffgen tool. --- .gitignore | 1 + diffgen.sh | 105 ------------------------------- patch-tool/README.md | 113 ++++++++++++++++++++++++++++++++++ patch-tool/keycloak-files.txt | 51 +++++++++++++++ patch-tool/patch.sh | 101 ++++++++++++++++++++++++++++++ 5 files changed, 266 insertions(+), 105 deletions(-) delete mode 100755 diffgen.sh create mode 100644 patch-tool/README.md create mode 100644 patch-tool/keycloak-files.txt create mode 100755 patch-tool/patch.sh diff --git a/.gitignore b/.gitignore index df6cd6e..db75fcc 100644 --- a/.gitignore +++ b/.gitignore @@ -172,3 +172,4 @@ buildNumber.properties .classpath # End of https://www.toptal.com/developers/gitignore/api/maven,intellij+all,eclipse +/patch-tool/.work/ diff --git a/diffgen.sh b/diffgen.sh deleted file mode 100755 index b6e0528..0000000 --- a/diffgen.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -if [ $# -ne 2 ]; then - echo "Usage: $0 OLD_BRANCH NEW_BRANCH" - exit 1 -fi - -OLD_BRANCH="$1" -NEW_BRANCH="$2" - -echo "Comparing Java files between branches:" -echo " OLD_BRANCH: $OLD_BRANCH" -echo " NEW_BRANCH: $NEW_BRANCH" - -OLD_DIR="./diff/old" -NEW_DIR="./diff/new" -PATCH_FILE="./diffgen.patch" - -FILES=( - 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 - services/src/main/java/org/keycloak/broker/saml/mappers/UsernameTemplateMapper.java - services/src/main/java/org/keycloak/broker/saml/SAMLDataMarshaller.java - services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java - services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java - services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java - services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java - saml-core-api/src/main/java/org/keycloak/dom/saml/v2/assertion/AssertionType.java - saml-core-api/src/main/java/org/keycloak/dom/saml/v2/assertion/AttributeStatementType.java - saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/AttributeConsumingServiceType.java - saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/EntitiesDescriptorType.java - saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/EntityDescriptorType.java - saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/SPSSODescriptorType.java - saml-core-api/src/main/java/org/keycloak/dom/saml/v2/protocol/ResponseType.java - services/src/main/java/org/keycloak/protocol/saml/mappers/SamlMetadataDescriptorUpdater.java - services/src/main/java/org/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java - services/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java - saml-core-api/src/main/java/org/keycloak/saml/common/constants/JBossSAMLConstants.java - saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java - saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java - saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java - saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/AbstractStaxSamlAssertionParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionQNames.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeStatementParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLAttributeConsumingServiceParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLSPSSODescriptorParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/protocol/SAMLArtifactResponseParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/protocol/SAMLResponseParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParser.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java - saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java - saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java - saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java - saml-core/src/main/java/org/keycloak/saml/SAMLRequestParser.java - services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java -) - -# Clean up any previous run -rm -rf "$OLD_DIR" "$NEW_DIR" "$PATCH_FILE" -mkdir -p "$OLD_DIR" "$NEW_DIR" - -echo "Exporting files..." - -for FILE in "${FILES[@]}"; do - mkdir -p "$OLD_DIR/$(dirname "$FILE")" - git show "$OLD_BRANCH:$FILE" > "$OLD_DIR/$FILE" 2>/dev/null || echo "Missing in $OLD_BRANCH: $FILE" - - mkdir -p "$NEW_DIR/$(dirname "$FILE")" - git show "$NEW_BRANCH:$FILE" > "$NEW_DIR/$FILE" 2>/dev/null || echo "Missing in $NEW_BRANCH: $FILE" -done - -echo "File count (.java only):" -echo " $OLD_BRANCH: $(find "$OLD_DIR" -type f -name '*.java' | wc -l)" -echo " $NEW_BRANCH: $(find "$NEW_DIR" -type f -name '*.java' | wc -l)" - -echo "Creating patch..." -diff --color=never -ruN "$OLD_DIR" "$NEW_DIR" > "$PATCH_FILE" - -# Post-process diff for portability or project-specific needs -safe_sed() { - sed "$1" "$2" > "$2.tmp" && mv "$2.tmp" "$2" -} - -safe_sed "s|$OLD_DIR/saml-core/||g" "$PATCH_FILE" -safe_sed "s|$NEW_DIR/saml-core/||g" "$PATCH_FILE" -safe_sed "s|$OLD_DIR/services/||g" "$PATCH_FILE" -safe_sed "s|$NEW_DIR/services/||g" "$PATCH_FILE" -safe_sed 's|org/keycloak/|nl/first8/keycloak/|g' "$PATCH_FILE" - -echo "Patch created at: $PATCH_FILE" diff --git a/patch-tool/README.md b/patch-tool/README.md new file mode 100644 index 0000000..d6c0c44 --- /dev/null +++ b/patch-tool/README.md @@ -0,0 +1,113 @@ + +# Git Branch Diff & Patch Tool + +This script compares specific files between two branches of a Git repository, generates a patch, and (optionally) applies that patch to a target directory. + +## Features + +- Clones a repository into a temporary **.work** directory +- Extracts only files listed in `keycloak-files.txt` +- Compares two branches and creates a **unified diff patch** +- Cleans up paths and replaces package names in the patch +- Optionally applies the patch to the **parent directory** of the current folder + +## Requirements + +- **Bash** (Unix/Linux/macOS environment) +- **git** installed and configured +- Access to the repository (SSH key if private) +- A `keycloak-files.txt` file in the current directory containing the relative paths of files to compare + +## Usage + +```bash +./patch.sh [--apply] OLD_BRANCH NEW_BRANCH +``` + +### Arguments + +* `OLD_BRANCH` – The base branch (e.g., `main`) +* `NEW_BRANCH` – The comparison branch (e.g., `feature-branch`) +* `--apply` – Optional flag to **apply** the generated patch to the parent directory + +### Examples + +Generate patch without applying: + +```bash +./generate-patch.sh main feature-branch +``` + +Generate and apply patch: + +```bash +./generate-patch.sh --apply main feature-branch +``` + +## How It Works + +```plaintext ++-----------------------------+ +| Start script | ++-----------------------------+ + | + v ++-----------------------------+ +| Validate keycloak-files.txt | ++-----------------------------+ + | + v ++-----------------------------+ +| Clone Git repository | +| into .work/repo | ++-----------------------------+ + | + v ++--------------------------------------+ +| Export listed files from OLD_BRANCH | +| to .work/files/old | ++--------------------------------------+ + | + v ++--------------------------------------+ +| Export listed files from NEW_BRANCH | +| to .work/files/new | ++--------------------------------------+ + | + v ++-----------------------------+ +| Generate patch file | +| .work/patch.patch | ++-----------------------------+ + | + v ++--------------------------------+ +| Post-process patch (clean paths,| +| replace package names) | ++--------------------------------+ + | + v ++-----------------------------------------+ +| If --apply flag set: | +| Apply patch to parent directory | ++-----------------------------------------+ + | + v ++-----------------------------+ +| Script ends with patch ready| ++-----------------------------+ +``` + +## Output + +* Generated patch: `.work/patch.patch` +* Temporary files: `.work/files/old`, `.work/files/new` + +## Notes + +* The `.work` directory is removed and recreated on each run. +* The script exits on any error (`set -e`). +* Missing files in either branch are reported but do not stop execution. +* The patch is applied **only** if the `--apply` option is given. + + diff --git a/patch-tool/keycloak-files.txt b/patch-tool/keycloak-files.txt new file mode 100644 index 0000000..5229975 --- /dev/null +++ b/patch-tool/keycloak-files.txt @@ -0,0 +1,51 @@ +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 +services/src/main/java/org/keycloak/broker/saml/mappers/UsernameTemplateMapper.java +services/src/main/java/org/keycloak/broker/saml/SAMLDataMarshaller.java +services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java +services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java +services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java +services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java +saml-core-api/src/main/java/org/keycloak/dom/saml/v2/assertion/AssertionType.java +saml-core-api/src/main/java/org/keycloak/dom/saml/v2/assertion/AttributeStatementType.java +saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/AttributeConsumingServiceType.java +saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/EntitiesDescriptorType.java +saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/EntityDescriptorType.java +saml-core-api/src/main/java/org/keycloak/dom/saml/v2/metadata/SPSSODescriptorType.java +saml-core-api/src/main/java/org/keycloak/dom/saml/v2/protocol/ResponseType.java +services/src/main/java/org/keycloak/protocol/saml/mappers/SamlMetadataDescriptorUpdater.java +services/src/main/java/org/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java +services/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java +saml-core-api/src/main/java/org/keycloak/saml/common/constants/JBossSAMLConstants.java +saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java +saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java +saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java +saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/AbstractStaxSamlAssertionParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAssertionQNames.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeStatementParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/assertion/SAMLAttributeValueParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLAttributeConsumingServiceParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLSPSSODescriptorParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/protocol/SAMLArtifactResponseParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/protocol/SAMLResponseParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParser.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java +saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java +saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java +saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java +saml-core/src/main/java/org/keycloak/saml/SAMLRequestParser.java +services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java diff --git a/patch-tool/patch.sh b/patch-tool/patch.sh new file mode 100755 index 0000000..8b0f112 --- /dev/null +++ b/patch-tool/patch.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +set -e + +APPLY_PATCH=false + +usage() { + echo "Usage: $0 [--apply] OLD_BRANCH NEW_BRANCH" + echo " --apply Apply patch to parent directory after generation" + exit 1 +} + +# Parse options +while [[ "$1" == --* ]]; do + case "$1" in + --apply) + APPLY_PATCH=true + shift + ;; + *) + usage + ;; + esac +done + +if [ $# -ne 2 ]; then + usage +fi + +OLD_BRANCH="$1" +NEW_BRANCH="$2" + +GIT_REPO_URL="git@github.com:keycloak/keycloak.git" +WORK_DIR="$(pwd)/.work" +REPO_DIR="$WORK_DIR/repo" +OLD_DIR="$WORK_DIR/files/old" +NEW_DIR="$WORK_DIR/files/new" +PATCH_FILE="$WORK_DIR/patch.patch" +FILES_LIST="$(pwd)/keycloak-files.txt" + +echo "=== Git Diff Generator ===" +echo "Repository : $GIT_REPO_URL" +echo "Old branch : $OLD_BRANCH" +echo "New branch : $NEW_BRANCH" +echo "Work dir : $WORK_DIR" +echo "Apply patch: $APPLY_PATCH" + +# Ensure keycloak-files.txt exists +if [ ! -f "$FILES_LIST" ]; then + echo "Error: $FILES_LIST not found in $(pwd)" + exit 1 +fi + +# Read file list into array +FILES=() +while IFS= read -r line; do + [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue + FILES+=("$line") +done < "$FILES_LIST" + +# Prepare work directory +rm -rf "$WORK_DIR" +mkdir -p "$WORK_DIR" "$OLD_DIR" "$NEW_DIR" + +echo "Cloning repository..." +git clone "$GIT_REPO_URL" "$REPO_DIR" + +echo "Exporting files..." +for FILE in "${FILES[@]}"; do + mkdir -p "$OLD_DIR/$(dirname "$FILE")" + git -C "$REPO_DIR" show "$OLD_BRANCH:$FILE" > "$OLD_DIR/$FILE" 2>/dev/null || echo "Missing in $OLD_BRANCH: $FILE" + + mkdir -p "$NEW_DIR/$(dirname "$FILE")" + git -C "$REPO_DIR" show "$NEW_BRANCH:$FILE" > "$NEW_DIR/$FILE" 2>/dev/null || echo "Missing in $NEW_BRANCH: $FILE" +done + +echo "File count (.java only):" +echo " $OLD_BRANCH: $(find "$OLD_DIR" -type f -name '*.java' | wc -l)" +echo " $NEW_BRANCH: $(find "$NEW_DIR" -type f -name '*.java' | wc -l)" + +echo "Creating patch..." +diff --color=never -ruN "$OLD_DIR" "$NEW_DIR" > "$PATCH_FILE" || true + +# Post-process diff +safe_sed() { + sed "$1" "$2" > "$2.tmp" && mv "$2.tmp" "$2" +} + +safe_sed "s|$OLD_DIR/saml-core/||g" "$PATCH_FILE" +safe_sed "s|$NEW_DIR/saml-core/||g" "$PATCH_FILE" +safe_sed "s|$OLD_DIR/services/||g" "$PATCH_FILE" +safe_sed "s|$NEW_DIR/services/||g" "$PATCH_FILE" +safe_sed 's|org/keycloak/|nl/first8/keycloak/|g' "$PATCH_FILE" + +echo "Patch created at: $PATCH_FILE" + +if [ "$APPLY_PATCH" = true ]; then + echo "Applying patch to parent directory: $(dirname "$(pwd)")" + patch -d "$(dirname "$(pwd)")" < "$PATCH_FILE" + echo "Patch applied successfully." +fi From c26b6b5dac481eb4ae46a9fbd71743834359fe77 Mon Sep 17 00:00:00 2001 From: tom <119664967+tmzcode@users.noreply.github.com> Date: Fri, 8 Aug 2025 10:45:21 +0200 Subject: [PATCH 5/7] Support Keycloak 26.1.x and resolve API changes, add diffgen tool. --- patch-tool/README.md | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/patch-tool/README.md b/patch-tool/README.md index d6c0c44..51988f8 100644 --- a/patch-tool/README.md +++ b/patch-tool/README.md @@ -1,33 +1,32 @@ +# Keycloak Git Branch Diff & Patch Tool -# Git Branch Diff & Patch Tool - -This script compares specific files between two branches of a Git repository, generates a patch, and (optionally) applies that patch to a target directory. +This script is designed to work **specifically with the [Keycloak Git repository](https://github.com/keycloak/keycloak)**. It compares selected Java files between two branches of the Keycloak repo, generates a patch, and (optionally) applies that patch to a target directory. ## Features -- Clones a repository into a temporary **.work** directory -- Extracts only files listed in `keycloak-files.txt` +- Clones the Keycloak repository into a temporary **.work** directory +- Extracts only files listed in `keycloak-files.txt` (tailored for Keycloak source paths) - Compares two branches and creates a **unified diff patch** -- Cleans up paths and replaces package names in the patch +- Cleans up file paths and replaces package names in the patch for project-specific needs - Optionally applies the patch to the **parent directory** of the current folder ## Requirements - **Bash** (Unix/Linux/macOS environment) - **git** installed and configured -- Access to the repository (SSH key if private) -- A `keycloak-files.txt` file in the current directory containing the relative paths of files to compare +- Access to the Keycloak repository (SSH key if private) +- A `keycloak-files.txt` file in the current directory containing relative file paths from the Keycloak repo ## Usage ```bash ./patch.sh [--apply] OLD_BRANCH NEW_BRANCH -``` +```` ### Arguments -* `OLD_BRANCH` – The base branch (e.g., `main`) -* `NEW_BRANCH` – The comparison branch (e.g., `feature-branch`) +* `OLD_BRANCH` – The base branch in the Keycloak repo (e.g., `origin/release/26.0`) +* `NEW_BRANCH` – The comparison branch in the Keycloak repo (e.g., `origin/archive/release/26.1`) * `--apply` – Optional flag to **apply** the generated patch to the parent directory ### Examples @@ -35,13 +34,13 @@ This script compares specific files between two branches of a Git repository, ge Generate patch without applying: ```bash -./generate-patch.sh main feature-branch +./patch.sh origin/release/26.0 origin/archive/release/26.1 ``` Generate and apply patch: ```bash -./generate-patch.sh --apply main feature-branch +./patch.sh --apply origin/release/26.0 origin/archive/release/26.1 ``` ## How It Works @@ -58,7 +57,7 @@ Generate and apply patch: | v +-----------------------------+ -| Clone Git repository | +| Clone Keycloak repository | | into .work/repo | +-----------------------------+ | @@ -100,14 +99,13 @@ Generate and apply patch: ## Output -* Generated patch: `.work/patch.patch` -* Temporary files: `.work/files/old`, `.work/files/new` +* Generated patch file: `.work/patch.patch` +* Temporary exported files in `.work/files/old` and `.work/files/new` ## Notes -* The `.work` directory is removed and recreated on each run. -* The script exits on any error (`set -e`). -* Missing files in either branch are reported but do not stop execution. -* The patch is applied **only** if the `--apply` option is given. - +* The `.work` directory is deleted and recreated on each run to ensure a clean workspace. +* The script exits immediately on any error (`set -e`). +* Missing files on either branch will be reported but won’t stop the script. +* Patch is applied **only** if the `--apply` option is specified. From 682f534be0112091f845e1db3a4810dfffe01b9a Mon Sep 17 00:00:00 2001 From: tom <119664967+tmzcode@users.noreply.github.com> Date: Fri, 8 Aug 2025 10:58:52 +0200 Subject: [PATCH 6/7] Support Keycloak 26.1.x and resolve API changes, add diffgen tool. --- patch-tool/patch.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/patch-tool/patch.sh b/patch-tool/patch.sh index 8b0f112..70d402c 100755 --- a/patch-tool/patch.sh +++ b/patch-tool/patch.sh @@ -65,6 +65,14 @@ mkdir -p "$WORK_DIR" "$OLD_DIR" "$NEW_DIR" echo "Cloning repository..." git clone "$GIT_REPO_URL" "$REPO_DIR" +# Validate branches exist +for BRANCH in "$OLD_BRANCH" "$NEW_BRANCH"; do + if ! git -C "$REPO_DIR" ls-remote --exit-code --heads origin "$BRANCH" > /dev/null; then + echo "Error: Branch '$BRANCH' does not exist in remote repository." + exit 1 + fi +done + echo "Exporting files..." for FILE in "${FILES[@]}"; do mkdir -p "$OLD_DIR/$(dirname "$FILE")" From dcb78c7376d492fd383110a2f5e89db7dfcab0c1 Mon Sep 17 00:00:00 2001 From: tom <119664967+tmzcode@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:00:25 +0200 Subject: [PATCH 7/7] Support Keycloak 26.1.x and resolve API changes, add diffgen tool. --- patch-tool/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/patch-tool/README.md b/patch-tool/README.md index 51988f8..50d13ef 100644 --- a/patch-tool/README.md +++ b/patch-tool/README.md @@ -59,6 +59,11 @@ Generate and apply patch: +-----------------------------+ | Clone Keycloak repository | | into .work/repo | ++-----------------------------+ + | + v ++-----------------------------+ +| Validate branches | +-----------------------------+ | v