From 637773e2658ec11797a746a713c7f15a2b2f260f Mon Sep 17 00:00:00 2001 From: Luca Leonardo Scorcia Date: Sun, 15 Nov 2020 10:15:51 -0500 Subject: [PATCH] KEYCLOAK-16325 Introduce SAML2NameIDBuilder for easier creation of NameIDType elements --- .../saml/SAML2AuthnRequestBuilder.java | 14 +++-- .../saml/SAML2ErrorResponseBuilder.java | 11 ++-- .../saml/SAML2LoginResponseBuilder.java | 10 +++- .../saml/SAML2LogoutRequestBuilder.java | 17 +++--- .../saml/SAML2LogoutResponseBuilder.java | 12 ++-- .../org/keycloak/saml/SAML2NameIDBuilder.java | 56 +++++++++++++++++++ .../api/saml/v2/request/SAML2Request.java | 8 +-- 7 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 saml-core/src/main/java/org/keycloak/saml/SAML2NameIDBuilder.java diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java index 59b2faa727..cf7da5cc6e 100755 --- a/saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java +++ b/saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java @@ -21,6 +21,7 @@ import org.keycloak.dom.saml.v2.assertion.SubjectType; import org.keycloak.dom.saml.v2.protocol.AuthnRequestType; import org.keycloak.dom.saml.v2.protocol.ExtensionsType; import org.keycloak.dom.saml.v2.protocol.RequestedAuthnContextType; +import org.keycloak.saml.SAML2NameIDBuilder; import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request; import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; @@ -37,7 +38,7 @@ public class SAML2AuthnRequestBuilder implements SamlProtocolExtensionsAwareBuil private final AuthnRequestType authnRequestType; protected String destination; - protected String issuer; + protected NameIDType issuer; protected final List extensions = new LinkedList<>(); public SAML2AuthnRequestBuilder destination(String destination) { @@ -45,11 +46,15 @@ public class SAML2AuthnRequestBuilder implements SamlProtocolExtensionsAwareBuil return this; } - public SAML2AuthnRequestBuilder issuer(String issuer) { + public SAML2AuthnRequestBuilder issuer(NameIDType issuer) { this.issuer = issuer; return this; } + public SAML2AuthnRequestBuilder issuer(String issuer) { + return issuer(SAML2NameIDBuilder.value(issuer).build()); + } + @Override public SAML2AuthnRequestBuilder addExtension(NodeGenerator extension) { this.extensions.add(extension); @@ -132,11 +137,8 @@ public class SAML2AuthnRequestBuilder implements SamlProtocolExtensionsAwareBuil public AuthnRequestType createAuthnRequest() { AuthnRequestType res = this.authnRequestType; - NameIDType nameIDType = new NameIDType(); - nameIDType.setValue(this.issuer); - - res.setIssuer(nameIDType); + res.setIssuer(issuer); res.setDestination(URI.create(this.destination)); if (! this.extensions.isEmpty()) { diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2ErrorResponseBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2ErrorResponseBuilder.java index 5873a7fd75..b42a42025a 100755 --- a/saml-core/src/main/java/org/keycloak/saml/SAML2ErrorResponseBuilder.java +++ b/saml-core/src/main/java/org/keycloak/saml/SAML2ErrorResponseBuilder.java @@ -40,7 +40,7 @@ public class SAML2ErrorResponseBuilder implements SamlProtocolExtensionsAwareBui protected String status; protected String destination; - protected String issuer; + protected NameIDType issuer; protected final List extensions = new LinkedList<>(); public SAML2ErrorResponseBuilder status(String status) { @@ -53,11 +53,15 @@ public class SAML2ErrorResponseBuilder implements SamlProtocolExtensionsAwareBui return this; } - public SAML2ErrorResponseBuilder issuer(String issuer) { + public SAML2ErrorResponseBuilder issuer(NameIDType issuer) { this.issuer = issuer; return this; } + public SAML2ErrorResponseBuilder issuer(String issuer) { + return issuer(SAML2NameIDBuilder.value(issuer).build()); + } + @Override public SAML2ErrorResponseBuilder addExtension(NodeGenerator extension) { this.extensions.add(extension); @@ -70,9 +74,6 @@ public class SAML2ErrorResponseBuilder implements SamlProtocolExtensionsAwareBui StatusResponseType statusResponse = new ResponseType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant()); statusResponse.setStatus(JBossSAMLAuthnResponseFactory.createStatusTypeForResponder(status)); - NameIDType issuer = new NameIDType(); - issuer.setValue(this.issuer); - statusResponse.setIssuer(issuer); statusResponse.setDestination(destination); diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2LoginResponseBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2LoginResponseBuilder.java index 31e6cbf955..406ba45573 100755 --- a/saml-core/src/main/java/org/keycloak/saml/SAML2LoginResponseBuilder.java +++ b/saml-core/src/main/java/org/keycloak/saml/SAML2LoginResponseBuilder.java @@ -21,6 +21,7 @@ import org.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType; import org.keycloak.dom.saml.v2.assertion.AuthnStatementType; import org.keycloak.dom.saml.v2.assertion.ConditionsType; +import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.assertion.OneTimeUseType; import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType; import org.keycloak.dom.saml.v2.protocol.ExtensionsType; @@ -31,6 +32,7 @@ import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.util.DocumentUtil; +import org.keycloak.saml.SAML2NameIDBuilder; import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response; import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator; import org.keycloak.saml.processing.core.saml.v2.holders.IDPInfoHolder; @@ -57,7 +59,7 @@ public class SAML2LoginResponseBuilder implements SamlProtocolExtensionsAwareBui protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); protected String destination; - protected String issuer; + protected NameIDType issuer; protected int subjectExpiration; protected int assertionExpiration; protected int sessionExpiration; @@ -82,11 +84,15 @@ public class SAML2LoginResponseBuilder implements SamlProtocolExtensionsAwareBui return this; } - public SAML2LoginResponseBuilder issuer(String issuer) { + public SAML2LoginResponseBuilder issuer(NameIDType issuer) { this.issuer = issuer; return this; } + public SAML2LoginResponseBuilder issuer(String issuer) { + return issuer(SAML2NameIDBuilder.value(issuer).build()); + } + /** * Length of time in seconds the subject can be confirmed * See SAML core specification 2.4.1.2 NotOnOrAfter diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutRequestBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutRequestBuilder.java index 1a1b5dd875..ff8763a432 100755 --- a/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutRequestBuilder.java +++ b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutRequestBuilder.java @@ -18,7 +18,9 @@ package org.keycloak.saml; import org.keycloak.dom.saml.v2.assertion.NameIDType; +import org.keycloak.dom.saml.v2.protocol.ExtensionsType; import org.keycloak.dom.saml.v2.protocol.LogoutRequestType; +import org.keycloak.saml.SAML2NameIDBuilder; import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ProcessingException; @@ -29,7 +31,6 @@ import org.w3c.dom.Document; import java.net.URI; import java.util.LinkedList; import java.util.List; -import org.keycloak.dom.saml.v2.protocol.ExtensionsType; /** * @author Bill Burke @@ -40,7 +41,7 @@ public class SAML2LogoutRequestBuilder implements SamlProtocolExtensionsAwareBui protected String sessionIndex; protected long assertionExpiration; protected String destination; - protected String issuer; + protected NameIDType issuer; protected final List extensions = new LinkedList<>(); public SAML2LogoutRequestBuilder destination(String destination) { @@ -48,11 +49,15 @@ public class SAML2LogoutRequestBuilder implements SamlProtocolExtensionsAwareBui return this; } - public SAML2LogoutRequestBuilder issuer(String issuer) { + public SAML2LogoutRequestBuilder issuer(NameIDType issuer) { this.issuer = issuer; return this; } + public SAML2LogoutRequestBuilder issuer(String issuer) { + return issuer(SAML2NameIDBuilder.value(issuer).build()); + } + @Override public SAML2LogoutRequestBuilder addExtension(NodeGenerator extension) { this.extensions.add(extension); @@ -108,12 +113,8 @@ public class SAML2LogoutRequestBuilder implements SamlProtocolExtensionsAwareBui LogoutRequestType lort = SAML2Request.createLogoutRequest(issuer); lort.setNameID(nameId); + lort.setIssuer(issuer); - if (issuer != null) { - NameIDType issuerID = new NameIDType(); - issuerID.setValue(issuer); - lort.setIssuer(issuerID); - } if (sessionIndex != null) lort.addSessionIndex(sessionIndex); diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutResponseBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutResponseBuilder.java index fe32bf43b0..1ea82fcf64 100755 --- a/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutResponseBuilder.java +++ b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutResponseBuilder.java @@ -21,6 +21,7 @@ import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.protocol.StatusCodeType; import org.keycloak.dom.saml.v2.protocol.StatusResponseType; import org.keycloak.dom.saml.v2.protocol.StatusType; +import org.keycloak.saml.SAML2NameIDBuilder; import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ParsingException; @@ -42,7 +43,7 @@ public class SAML2LogoutResponseBuilder implements SamlProtocolExtensionsAwareBu protected String logoutRequestID; protected String destination; - protected String issuer; + protected NameIDType issuer; protected final List extensions = new LinkedList<>(); public SAML2LogoutResponseBuilder logoutRequestID(String logoutRequestID) { @@ -55,11 +56,15 @@ public class SAML2LogoutResponseBuilder implements SamlProtocolExtensionsAwareBu return this; } - public SAML2LogoutResponseBuilder issuer(String issuer) { + public SAML2LogoutResponseBuilder issuer(NameIDType issuer) { this.issuer = issuer; return this; } + public SAML2LogoutResponseBuilder issuer(String issuer) { + return issuer(SAML2NameIDBuilder.value(issuer).build()); + } + @Override public SAML2LogoutResponseBuilder addExtension(NodeGenerator extension) { this.extensions.add(extension); @@ -77,9 +82,6 @@ public class SAML2LogoutResponseBuilder implements SamlProtocolExtensionsAwareBu statusResponse.setStatus(statusType); statusResponse.setInResponseTo(logoutRequestID); - NameIDType issuer = new NameIDType(); - issuer.setValue(this.issuer); - statusResponse.setIssuer(issuer); statusResponse.setDestination(destination); diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2NameIDBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2NameIDBuilder.java new file mode 100644 index 0000000000..1fd60423e2 --- /dev/null +++ b/saml-core/src/main/java/org/keycloak/saml/SAML2NameIDBuilder.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.keycloak.saml; + +import org.keycloak.dom.saml.v2.assertion.NameIDType; + +import java.net.URI; + +public class SAML2NameIDBuilder { + private final NameIDType nameIdType; + private String format; + private String spNameQualifier; + + private SAML2NameIDBuilder(String value) { + this.nameIdType = new NameIDType(); + this.nameIdType.setValue(value); + } + + public static SAML2NameIDBuilder value(String value) { + return new SAML2NameIDBuilder(value); + } + + public SAML2NameIDBuilder setFormat(String format) { + this.format = format; + return this; + } + + public SAML2NameIDBuilder setSPNameQualifier(String spNameQualifier) { + this.spNameQualifier = spNameQualifier; + return this; + } + + public NameIDType build() { + if (this.format != null) + this.nameIdType.setFormat(URI.create(this.format)); + + if (this.spNameQualifier != null) + this.nameIdType.setSPNameQualifier(this.spNameQualifier); + + return this.nameIdType; + } +} \ No newline at end of file diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java index 5f37345c62..385a8503e9 100755 --- a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java +++ b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java @@ -257,14 +257,10 @@ public class SAML2Request { * * @throws ConfigurationException */ - public static LogoutRequestType createLogoutRequest(String issuer) throws ConfigurationException { + public static LogoutRequestType createLogoutRequest(NameIDType issuer) throws ConfigurationException { LogoutRequestType lrt = new LogoutRequestType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant()); - // Create an issuer - NameIDType issuerNameID = new NameIDType(); - issuerNameID.setValue(issuer); - - lrt.setIssuer(issuerNameID); + lrt.setIssuer(issuer); return lrt; }