You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2017/01/27 11:22:59 UTC
[16/19] cxf-fediz git commit: FEDIZ-155 - Move .java components out
of idp webapp and into a separate JAR
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseCreator.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseCreator.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseCreator.java
new file mode 100644
index 0000000..742797d
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseCreator.java
@@ -0,0 +1,187 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.beans.samlsso;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.fediz.core.exception.ProcessingException;
+import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
+import org.apache.cxf.fediz.core.util.CertsUtils;
+import org.apache.cxf.fediz.service.idp.IdpConstants;
+import org.apache.cxf.fediz.service.idp.domain.Idp;
+import org.apache.cxf.fediz.service.idp.samlsso.SAML2CallbackHandler;
+import org.apache.cxf.fediz.service.idp.samlsso.SAML2PResponseComponentBuilder;
+import org.apache.cxf.fediz.service.idp.samlsso.SAMLAuthnRequest;
+import org.apache.cxf.fediz.service.idp.util.WebUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.saml.OpenSAMLUtil;
+import org.apache.wss4j.common.saml.SAMLCallback;
+import org.apache.wss4j.common.saml.SAMLUtil;
+import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+import org.apache.wss4j.common.saml.bean.AudienceRestrictionBean;
+import org.apache.wss4j.common.saml.bean.ConditionsBean;
+import org.apache.wss4j.common.saml.bean.SubjectConfirmationDataBean;
+import org.apache.wss4j.common.util.DOM2Writer;
+import org.apache.wss4j.dom.WSConstants;
+import org.joda.time.DateTime;
+import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.webflow.execution.RequestContext;
+
+/**
+ * Insert the SAML Token received from the STS into a SAML Response
+ */
+@Component
+public class SamlResponseCreator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SamlResponseCreator.class);
+ private boolean supportDeflateEncoding;
+
+ public String createSAMLResponse(RequestContext context, Idp idp, Element rpToken,
+ String consumerURL, String requestId, String requestIssuer)
+ throws ProcessingException {
+ List<Element> samlTokens =
+ DOMUtils.findAllElementsByTagNameNS(rpToken, WSConstants.SAML2_NS, "Assertion");
+ if (samlTokens.isEmpty() || samlTokens.size() != 1) {
+ throw new ProcessingException(TYPE.BAD_REQUEST);
+ }
+
+ try {
+ SamlAssertionWrapper wrapper = new SamlAssertionWrapper(samlTokens.get(0));
+ if (wrapper.getSaml2() == null) {
+ throw new ProcessingException(TYPE.BAD_REQUEST);
+ }
+
+ String remoteAddr = WebUtils.getHttpServletRequest(context).getRemoteAddr();
+ Assertion saml2Assertion =
+ createSAML2Assertion(context, idp, wrapper, requestId, requestIssuer,
+ remoteAddr, consumerURL);
+
+ Element response = createResponse(idp, requestId, saml2Assertion);
+ return encodeResponse(response);
+ } catch (Exception ex) {
+ LOG.warn("Error marshalling SAML Token: {}", ex.getMessage());
+ throw new ProcessingException(TYPE.BAD_REQUEST);
+ }
+ }
+
+ private Assertion createSAML2Assertion(RequestContext context, Idp idp, SamlAssertionWrapper receivedToken,
+ String requestID, String requestIssuer,
+ String remoteAddr, String racs) throws Exception {
+ // Create an AuthenticationAssertion
+ SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+ callbackHandler.setIssuer(idp.getRealm());
+ callbackHandler.setSubject(receivedToken.getSaml2().getSubject());
+
+ // Test Subject against received Subject (if applicable)
+ SAMLAuthnRequest authnRequest =
+ (SAMLAuthnRequest)WebUtils.getAttributeFromFlowScope(context, IdpConstants.SAML_AUTHN_REQUEST);
+ if (authnRequest.getSubjectNameId() != null && receivedToken.getSaml2().getSubject().getNameID() != null) {
+ NameID issuedNameId = receivedToken.getSaml2().getSubject().getNameID();
+ if (!authnRequest.getSubjectNameId().equals(issuedNameId.getValue())) {
+ LOG.debug("Received NameID value of {} does not match issued value {}",
+ authnRequest.getSubjectNameId(), issuedNameId.getValue());
+ throw new ProcessingException(ProcessingException.TYPE.INVALID_REQUEST);
+ }
+ }
+
+ // Subject Confirmation Data
+ SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean();
+ subjectConfirmationData.setAddress(remoteAddr);
+ subjectConfirmationData.setInResponseTo(requestID);
+ subjectConfirmationData.setNotAfter(new DateTime().plusMinutes(5));
+ subjectConfirmationData.setRecipient(racs);
+ callbackHandler.setSubjectConfirmationData(subjectConfirmationData);
+
+ // Audience Restriction
+ ConditionsBean conditions = new ConditionsBean();
+ conditions.setTokenPeriodMinutes(5);
+
+ AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+ audienceRestriction.setAudienceURIs(Collections.singletonList(requestIssuer));
+ conditions.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+ callbackHandler.setConditions(conditions);
+
+ // Attributes
+ callbackHandler.setAttributeStatements(receivedToken.getSaml2().getAttributeStatements());
+
+ SAMLCallback samlCallback = new SAMLCallback();
+ SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+ SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+
+ Crypto issuerCrypto = CertsUtils.getCryptoFromCertificate(idp.getCertificate());
+ assertion.signAssertion(issuerCrypto.getDefaultX509Identifier(), idp.getCertificatePassword(),
+ issuerCrypto, false);
+
+ return assertion.getSaml2();
+ }
+
+ protected Element createResponse(Idp idp, String requestID, Assertion assertion) throws Exception {
+ Document doc = DOMUtils.newDocument();
+
+ Status status =
+ SAML2PResponseComponentBuilder.createStatus(
+ "urn:oasis:names:tc:SAML:2.0:status:Success", null
+ );
+ Response response =
+ SAML2PResponseComponentBuilder.createSAMLResponse(requestID, idp.getRealm(), status);
+
+ response.getAssertions().add(assertion);
+
+ Element policyElement = OpenSAMLUtil.toDom(response, doc);
+ doc.appendChild(policyElement);
+
+ return policyElement;
+ }
+
+ protected String encodeResponse(Element response) throws IOException {
+ String responseMessage = DOM2Writer.nodeToString(response);
+ LOG.debug("Created Response: {}", responseMessage);
+
+ if (supportDeflateEncoding) {
+ DeflateEncoderDecoder encoder = new DeflateEncoderDecoder();
+ byte[] deflatedBytes = encoder.deflateToken(responseMessage.getBytes("UTF-8"));
+
+ return Base64Utility.encode(deflatedBytes);
+ }
+
+ return Base64Utility.encode(responseMessage.getBytes());
+ }
+
+ public boolean isSupportDeflateEncoding() {
+ return supportDeflateEncoding;
+ }
+
+ public void setSupportDeflateEncoding(boolean supportDeflateEncoding) {
+ this.supportDeflateEncoding = supportDeflateEncoding;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseErrorCreator.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseErrorCreator.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseErrorCreator.java
new file mode 100644
index 0000000..ce257e0
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/SamlResponseErrorCreator.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.beans.samlsso;
+
+import java.io.IOException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.fediz.core.exception.ProcessingException;
+import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
+import org.apache.cxf.fediz.service.idp.domain.Idp;
+import org.apache.cxf.fediz.service.idp.samlsso.SAML2PResponseComponentBuilder;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
+import org.apache.wss4j.common.saml.OpenSAMLUtil;
+import org.apache.wss4j.common.util.DOM2Writer;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.webflow.execution.RequestContext;
+
+/**
+ * Create a SAML Error Response
+ */
+@Component
+public class SamlResponseErrorCreator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SamlResponseErrorCreator.class);
+ private boolean supportDeflateEncoding;
+
+ public String createSAMLResponse(RequestContext context, boolean requestor,
+ Idp idp, String requestID) throws ProcessingException {
+ Document doc = DOMUtils.newDocument();
+
+ String statusValue = "urn:oasis:names:tc:SAML:2.0:status:Responder";
+ if (requestor) {
+ statusValue = "urn:oasis:names:tc:SAML:2.0:status:Requester";
+ }
+ Status status =
+ SAML2PResponseComponentBuilder.createStatus(statusValue, null);
+ Response response =
+ SAML2PResponseComponentBuilder.createSAMLResponse(requestID, idp.getRealm(), status);
+
+ try {
+ Element policyElement = OpenSAMLUtil.toDom(response, doc);
+ doc.appendChild(policyElement);
+
+ Element responseElement = policyElement;
+ return encodeResponse(responseElement);
+ } catch (Exception e) {
+ LOG.warn("Error marshalling SAML Token: {}", e.getMessage());
+ throw new ProcessingException(TYPE.BAD_REQUEST);
+ }
+ }
+
+ protected String encodeResponse(Element response) throws IOException {
+ String responseMessage = DOM2Writer.nodeToString(response);
+ LOG.debug("Created Response: {}", responseMessage);
+
+ if (supportDeflateEncoding) {
+ DeflateEncoderDecoder encoder = new DeflateEncoderDecoder();
+ byte[] deflatedBytes = encoder.deflateToken(responseMessage.getBytes("UTF-8"));
+
+ return Base64Utility.encode(deflatedBytes);
+ }
+
+ return Base64Utility.encode(responseMessage.getBytes());
+ }
+
+ public boolean isSupportDeflateEncoding() {
+ return supportDeflateEncoding;
+ }
+
+ public void setSupportDeflateEncoding(boolean supportDeflateEncoding) {
+ this.supportDeflateEncoding = supportDeflateEncoding;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/wsfed/WfreshParser.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/wsfed/WfreshParser.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/wsfed/WfreshParser.java
new file mode 100644
index 0000000..148d24b
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/wsfed/WfreshParser.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.beans.wsfed;
+
+import java.util.Date;
+
+import org.apache.cxf.fediz.service.idp.util.WebUtils;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.webflow.execution.RequestContext;
+
+/**
+ * This class is responsible to parse the 'wfresh' parameter
+ */
+@Component
+public class WfreshParser {
+
+ private static final Logger LOG = LoggerFactory.getLogger(WfreshParser.class);
+
+ public boolean authenticationRequired(String wfresh, String whr, RequestContext context)
+ throws Exception {
+
+ SecurityToken idpToken =
+ (SecurityToken) WebUtils.getAttributeFromExternalContext(context, whr);
+ if (idpToken == null) {
+ return true;
+ }
+
+ if (wfresh == null || wfresh.trim().isEmpty()) {
+ return false;
+ }
+
+ long ttl;
+ try {
+ ttl = Long.parseLong(wfresh.trim());
+ } catch (Exception e) {
+ LOG.info("wfresh value '" + wfresh + "' is invalid.");
+ return false;
+ }
+ if (ttl == 0) {
+ return true;
+ }
+
+ long ttlMs = ttl * 60L * 1000L;
+ if (ttlMs > 0) {
+ Date createdDate = idpToken.getCreated();
+ if (createdDate != null) {
+ Date expiryDate = new Date();
+ expiryDate.setTime(createdDate.getTime() + ttlMs);
+ if (expiryDate.before(new Date())) {
+ LOG.info("[IDP_TOKEN="
+ + idpToken.getId()
+ + "] is valid but relying party requested new authentication caused by wfresh="
+ + wfresh + " outdated.");
+ return true;
+ }
+ } else {
+ LOG.info("token creation date not set. Unable to check wfresh is outdated.");
+ }
+ } else {
+ LOG.info("ttl value '" + ttl + "' is negative or is too large.");
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
new file mode 100644
index 0000000..814e342
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
@@ -0,0 +1,242 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import java.io.Serializable;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "application", namespace = "http://org.apache.cxf.fediz/")
+@XmlType(propOrder = {"realm", "role", "serviceDisplayName", "serviceDescription", "protocol",
+ "tokenType", "lifeTime", "encryptionCertificate", "requestedClaims",
+ "policyNamespace", "passiveRequestorEndpoint", "passiveRequestorEndpointConstraint", "id",
+ "validatingCertificate", "enableAppliesTo"})
+public class Application implements Serializable {
+
+ private static final long serialVersionUID = 5644327504861846964L;
+
+
+
+ protected int id;
+
+
+ //Could be imported from Metadata document or manually filled
+
+ //@Column(name = "REALM", nullable = true, length = FIELD_LENGTH)
+ protected String realm; //wtrealm, whr
+
+ //Could be read from Metadata, RoleDescriptor protocolSupportEnumeration=
+ // "http://docs.oasis-open.org/wsfed/federation/200706"
+ // Metadata could provide more than one but one must be chosen
+ protected String protocol;
+
+ // Public key only
+ // Could be read from Metadata, md:KeyDescriptor, use="encryption"
+ protected String encryptionCertificate;
+
+ // Certificate for Signature verification
+ protected String validatingCertificate;
+
+ // Could be read from Metadata, fed:ClaimTypesRequested
+ protected List<RequestClaim> requestedClaims = new ArrayList<>();
+
+ //Could be read from Metadata, ServiceDisplayName
+ //usage for list of application where user is logged in
+ protected String serviceDisplayName;
+
+ //Could be read from Metadata, ServiceDescription
+ //usage for list of application where user is logged in
+ protected String serviceDescription;
+
+ //Could be read from Metadata, RoleDescriptor
+ //fed:ApplicationServiceType, fed:SecurityTokenServiceType
+ protected String role;
+
+ // Not in Metadata, configured in IDP or passed in wreq parameter
+ protected String tokenType;
+
+ // Not in Metadata, configured in IDP or passed in wreq parameter
+ protected int lifeTime;
+
+ // WS-Policy Namespace for AppliesTo element
+ protected String policyNamespace;
+
+ // Request audience restriction in token for this application (default is true)
+ private boolean enableAppliesTo = true;
+
+ private URI href;
+
+ //Could be read from Metadata, PassiveRequestorEndpoint
+ //fed:ApplicationServiceType, fed:SecurityTokenServiceType
+ private String passiveRequestorEndpoint;
+
+ // A regular expression constraint on the passiveRequestorEndpoint
+ private String passiveRequestorEndpointConstraint;
+ private Pattern compiledPassiveRequestorEndpointConstraint;
+
+
+ @XmlAttribute
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @XmlAttribute
+ public URI getHref() {
+ return href;
+ }
+
+ public void setHref(URI href) {
+ this.href = href;
+ }
+
+ public String getRealm() {
+ return realm;
+ }
+
+ public void setRealm(String realm) {
+ this.realm = realm;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public String getEncryptionCertificate() {
+ return encryptionCertificate;
+ }
+
+ public void setEncryptionCertificate(String encryptionCertificate) {
+ this.encryptionCertificate = encryptionCertificate;
+ }
+
+ @XmlElementWrapper(name = "claims")
+ @XmlElementRef(name = "requestedClaims")
+ public List<RequestClaim> getRequestedClaims() {
+ return requestedClaims;
+ }
+
+ public void setRequestedClaims(List<RequestClaim> requestedClaims) {
+ this.requestedClaims = requestedClaims;
+ }
+
+ public String getServiceDisplayName() {
+ return serviceDisplayName;
+ }
+
+ public void setServiceDisplayName(String serviceDisplayName) {
+ this.serviceDisplayName = serviceDisplayName;
+ }
+
+ public String getServiceDescription() {
+ return serviceDescription;
+ }
+
+ public void setServiceDescription(String serviceDescription) {
+ this.serviceDescription = serviceDescription;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ public String getTokenType() {
+ return tokenType;
+ }
+
+ public void setTokenType(String tokenType) {
+ this.tokenType = tokenType;
+ }
+
+ public int getLifeTime() {
+ return lifeTime;
+ }
+
+ public void setLifeTime(int lifeTime) {
+ this.lifeTime = lifeTime;
+ }
+
+ public String getPolicyNamespace() {
+ return policyNamespace;
+ }
+
+ public void setPolicyNamespace(String policyNamespace) {
+ this.policyNamespace = policyNamespace;
+ }
+
+ public String getPassiveRequestorEndpoint() {
+ return passiveRequestorEndpoint;
+ }
+
+ public void setPassiveRequestorEndpoint(String passiveRequestorEndpoint) {
+ this.passiveRequestorEndpoint = passiveRequestorEndpoint;
+ }
+
+ public String getPassiveRequestorEndpointConstraint() {
+ return passiveRequestorEndpointConstraint;
+ }
+
+ public void setPassiveRequestorEndpointConstraint(String passiveRequestorEndpointConstraint) {
+ this.passiveRequestorEndpointConstraint = passiveRequestorEndpointConstraint;
+ if (passiveRequestorEndpointConstraint != null) {
+ compiledPassiveRequestorEndpointConstraint = Pattern.compile(passiveRequestorEndpointConstraint);
+ } else {
+ compiledPassiveRequestorEndpointConstraint = null;
+ }
+ }
+
+ public Pattern getCompiledPassiveRequestorEndpointConstraint() {
+ return compiledPassiveRequestorEndpointConstraint;
+ }
+
+ public String getValidatingCertificate() {
+ return validatingCertificate;
+ }
+
+ public void setValidatingCertificate(String validatingCertificate) {
+ this.validatingCertificate = validatingCertificate;
+ }
+
+ public boolean isEnableAppliesTo() {
+ return enableAppliesTo;
+ }
+
+ public void setEnableAppliesTo(boolean useAudienceRestriction) {
+ this.enableAppliesTo = useAudienceRestriction;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Claim.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Claim.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Claim.java
new file mode 100644
index 0000000..96afed9
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Claim.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import java.io.Serializable;
+import java.net.URI;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "claim", namespace = "http://org.apache.cxf.fediz/")
+public class Claim implements Serializable {
+
+ private static final long serialVersionUID = 2635896159019665467L;
+
+ protected URI claimType;
+ protected String displayName;
+ protected String description;
+ protected int id;
+ private URI href;
+
+ @XmlAttribute
+ public URI getHref() {
+ return href;
+ }
+
+ public void setHref(URI href) {
+ this.href = href;
+ }
+
+ @XmlAttribute
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public void setClaimType(URI claimType) {
+ this.claimType = claimType;
+ }
+
+ public URI getClaimType() {
+ return claimType;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Entitlement.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Entitlement.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Entitlement.java
new file mode 100644
index 0000000..c926386
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Entitlement.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "entitlement", namespace = "http://org.apache.cxf.fediz/")
+@XmlType(propOrder = {"name", "description", "internal", "id" })
+public class Entitlement implements Serializable {
+
+ private static final long serialVersionUID = 2635896159019665467L;
+
+ protected String name;
+ protected String description;
+ protected int id;
+ protected boolean internal;
+
+ @XmlAttribute
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isInternal() {
+ return internal;
+ }
+
+ public void setInternal(boolean internal) {
+ this.internal = internal;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/FederationType.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/FederationType.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/FederationType.java
new file mode 100644
index 0000000..2dcc296
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/FederationType.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import javax.xml.bind.annotation.XmlEnum;
+
+@XmlEnum
+public enum FederationType {
+
+ FEDERATE_IDENTITY("FederateIdentity"),
+ FEDERATE_CLAIMS("FederateClaims");
+
+ private String name;
+
+ FederationType(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
new file mode 100644
index 0000000..d382184
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
@@ -0,0 +1,304 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import java.io.Serializable;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "idp", namespace = "http://org.apache.cxf.fediz/")
+@XmlType(propOrder = {"realm", "uri", "serviceDisplayName", "serviceDescription", "idpUrl", "stsUrl",
+ "certificate", "certificatePassword", "provideIdpList", "useCurrentIdp", "hrds",
+ "rpSingleSignOutConfirmation", "supportedProtocols", "tokenTypesOffered", "claimTypesOffered",
+ "authenticationURIs", "applications", "trustedIdps", "id", "rpSingleSignOutCleanupConfirmation" })
+public class Idp implements Serializable {
+
+ private static final long serialVersionUID = -5570301342547139039L;
+
+
+ protected int id;
+
+ // Unique
+ // fed:TargetScope
+ protected String realm; // wtrealm, whr
+
+ // Unique
+ // https://<host>:<port>/fediz-idp/<IDP uri>/
+ protected String uri;
+
+ // Home Realm Discovery Service
+ // Spring EL
+ protected String hrds;
+
+ // @Column(name = "INACTIVE", nullable = true, length = FIELD_LENGTH)
+ // if HRDS can't determine the home realm, should
+ // the list of trusted IDPs be shown to make a choice
+ protected boolean provideIdpList;
+
+ // If HRDS can't discover a home realm and displaying IDP list is not
+ // enabled
+ // it falls back to current IDP if an authentication domain is configured
+ protected boolean useCurrentIdp;
+
+ // Store certificate in DB or filesystem, provide options?
+ // md:KeyDescriptor, use="signing"
+ protected String certificate;
+
+ // Password to read the private key to sign metadata document
+ protected String certificatePassword;
+
+ // fed:SecurityTokenSerivceEndpoint
+ protected URL stsUrl;
+
+ // fed:PassiveRequestorEndpoint
+ // published hostname, port must be configured
+ protected URL idpUrl;
+
+ // RoleDescriptor protocolSupportEnumeration=
+ // "http://docs.oasis-open.org/wsfed/federation/200706"
+ // "http://docs.oasis-open.org/ws-sx/ws-trust/200512"
+ // Could be more in the future
+ protected List<String> supportedProtocols = new ArrayList<>();
+
+ // list of RPs and RP-IDPs from whom we accept SignInResponse
+ // which includes RP IDPs
+ // key: wtrealm
+ protected List<Application> applications = new ArrayList<>();
+
+ // list of trusted IDP from whom we accept SignInResponse
+ // key: whr
+ protected List<TrustedIdp> trustedIdpList = new ArrayList<>();
+
+ // which URI to redirect for authentication
+ // fediz-idp/<IDP uri>/login/auth/<auth URI>
+ // wauth to auth URI mapping
+ protected Map<String, String> authenticationURIs = new HashMap<>();
+
+ // required to create Federation Metadata document
+ // fed:TokenTypesOffered
+ protected List<String> tokenTypesOffered = new ArrayList<>();
+
+ // fed:ClaimTypesOffered
+ protected List<Claim> claimTypesOffered = new ArrayList<>();
+
+ // ServiceDisplayName
+ protected String serviceDisplayName;
+
+ // ServiceDescription
+ protected String serviceDescription;
+
+ // The user/browser must explicitly confirm to logout from all applications
+ private boolean rpSingleSignOutConfirmation;
+
+ // Is explicit confirmation required when the "cleanup" URL is called
+ private boolean rpSingleSignOutCleanupConfirmation;
+
+ @XmlAttribute
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getRealm() {
+ return realm;
+ }
+
+ public void setRealm(String realm) {
+ this.realm = realm;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public String getHrds() {
+ return hrds;
+ }
+
+ public void setHrds(String hrds) {
+ this.hrds = hrds;
+ }
+
+ public boolean isProvideIdpList() {
+ return provideIdpList;
+ }
+
+ public void setProvideIdpList(boolean provideIdpList) {
+ this.provideIdpList = provideIdpList;
+ }
+
+ public boolean isUseCurrentIdp() {
+ return useCurrentIdp;
+ }
+
+ public void setUseCurrentIdp(boolean useCurrentIdp) {
+ this.useCurrentIdp = useCurrentIdp;
+ }
+
+ public String getCertificate() {
+ return certificate;
+ }
+
+ public void setCertificate(String certificate) {
+ this.certificate = certificate;
+ }
+
+ public String getCertificatePassword() {
+ return certificatePassword;
+ }
+
+ public void setCertificatePassword(String password) {
+ this.certificatePassword = password;
+ }
+
+ public URL getStsUrl() {
+ return stsUrl;
+ }
+
+ public void setStsUrl(URL stsUrl) {
+ this.stsUrl = stsUrl;
+ }
+
+ public URL getIdpUrl() {
+ return idpUrl;
+ }
+
+ public void setIdpUrl(URL idpUrl) {
+ this.idpUrl = idpUrl;
+ }
+
+ @XmlElementWrapper(name = "supportedProtocols")
+ public List<String> getSupportedProtocols() {
+ return supportedProtocols;
+ }
+
+ public void setSupportedProtocols(List<String> supportedProtocols) {
+ this.supportedProtocols = supportedProtocols;
+ }
+
+ public Application findApplication(String realmApplication) {
+ for (Application item : applications) {
+ if (item.getRealm().equals(realmApplication)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ @XmlElementWrapper(name = "applications")
+ @XmlElementRef(name = "application")
+ public List<Application> getApplications() {
+ return applications;
+ }
+
+ public void setApplications(List<Application> applications) {
+ this.applications = applications;
+ }
+
+ public TrustedIdp findTrustedIdp(String realmTrustedIdp) {
+ for (TrustedIdp item : trustedIdpList) {
+ if (item.getRealm().equals(realmTrustedIdp)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ @XmlElementWrapper(name = "trustedIdps")
+ @XmlElementRef(name = "trustedIdp")
+ public List<TrustedIdp> getTrustedIdps() {
+ return trustedIdpList;
+ }
+
+ public Map<String, String> getAuthenticationURIs() {
+ return authenticationURIs;
+ }
+
+ public void setAuthenticationURIs(Map<String, String> authenticationURIs) {
+ this.authenticationURIs = authenticationURIs;
+ }
+
+ @XmlElementWrapper(name = "tokenTypesOffered")
+ public List<String> getTokenTypesOffered() {
+ return tokenTypesOffered;
+ }
+
+ public void setTokenTypesOffered(List<String> tokenTypesOffered) {
+ this.tokenTypesOffered = tokenTypesOffered;
+ }
+
+ @XmlElementWrapper(name = "claimTypesOffered")
+ @XmlElementRef(name = "claimType")
+ public List<Claim> getClaimTypesOffered() {
+ return claimTypesOffered;
+ }
+
+ public void setClaimTypesOffered(List<Claim> claimTypesOffered) {
+ this.claimTypesOffered = claimTypesOffered;
+ }
+
+ public String getServiceDisplayName() {
+ return serviceDisplayName;
+ }
+
+ public void setServiceDisplayName(String serviceDisplayName) {
+ this.serviceDisplayName = serviceDisplayName;
+ }
+
+ public String getServiceDescription() {
+ return serviceDescription;
+ }
+
+ public void setServiceDescription(String serviceDescription) {
+ this.serviceDescription = serviceDescription;
+ }
+
+ public boolean isRpSingleSignOutConfirmation() {
+ return rpSingleSignOutConfirmation;
+ }
+
+ public void setRpSingleSignOutConfirmation(boolean rpSingleSignOutConfirmation) {
+ this.rpSingleSignOutConfirmation = rpSingleSignOutConfirmation;
+ }
+
+ public boolean isRpSingleSignOutCleanupConfirmation() {
+ return rpSingleSignOutCleanupConfirmation;
+ }
+
+ public void setRpSingleSignOutCleanupConfirmation(boolean rpSingleSignOutCleanupConfirmation) {
+ this.rpSingleSignOutCleanupConfirmation = rpSingleSignOutCleanupConfirmation;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/RequestClaim.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/RequestClaim.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/RequestClaim.java
new file mode 100644
index 0000000..008e75a
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/RequestClaim.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "requestClaim", namespace = "http://org.apache.cxf.fediz/")
+public class RequestClaim extends Claim {
+
+ private static final long serialVersionUID = 8097560995225077866L;
+
+ protected boolean optional;
+
+ public RequestClaim() {
+ super();
+ }
+
+ public RequestClaim(Claim c) {
+ super();
+ this.setClaimType(c.getClaimType());
+ this.setDescription(c.getDescription());
+ this.setDisplayName(c.getDisplayName());
+ this.setId(c.getId());
+ }
+
+ public void setOptional(boolean optional) {
+ this.optional = optional;
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Role.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Role.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Role.java
new file mode 100644
index 0000000..f403546
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Role.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "role", namespace = "http://org.apache.cxf.fediz/")
+@XmlType(propOrder = {"name", "description", "entitlements", "id" })
+public class Role implements Serializable {
+
+ private static final long serialVersionUID = 2635896159019665467L;
+
+ protected String name;
+ protected String description;
+ protected int id;
+
+ protected List<Entitlement> entitlements = new ArrayList<>();
+
+ @XmlAttribute
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public List<Entitlement> getEntitlements() {
+ return entitlements;
+ }
+
+ public void setEntitlements(List<Entitlement> entitlements) {
+ this.entitlements = entitlements;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustType.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustType.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustType.java
new file mode 100644
index 0000000..50efb25
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustType.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import javax.xml.bind.annotation.XmlEnum;
+
+@XmlEnum
+public enum TrustType {
+
+ PEER_TRUST("PeerTrust"),
+ INDIRECT_TRUST("IndirectTrust");
+
+ private String name;
+
+ TrustType(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
new file mode 100644
index 0000000..b3262b5
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
@@ -0,0 +1,187 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.domain;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "trustedIdp", namespace = "http://org.apache.cxf.fediz/")
+@XmlType(propOrder = {"realm", "issuer", "url", "name", "description", "protocol", "trustType",
+ "certificate", "federationType", "cacheTokens", "logo", "id", "parameters" })
+//@XmlAttribute on Id must be set on getter, not on attribute, otherwise error
+public class TrustedIdp implements Serializable {
+
+ private static final long serialVersionUID = -6520081722646469178L;
+
+
+ protected int id;
+
+ //@Column(name = "REALM", nullable = true, length = FIELD_LENGTH)
+ protected String realm; //wtrealm, whr
+
+ //@Column(name = "Issuer", nullable = true, length = FIELD_LENGTH)
+ protected String issuer; //SAMLResponse issuer name
+
+ // Should tokens be cached from trusted IDPs
+ // to avoid redirection to the trusted IDP again for next SignIn request
+ protected boolean cacheTokens;
+
+ //Could be read from Metadata, PassiveRequestorEndpoint
+ protected String url;
+
+ //Could be read from Metadata, md:KeyDescriptor, use="signing"
+ //Store certificate in DB or filesystem, provide options?
+ protected String certificate;
+
+ //Direct trust (signing cert imported), Indirect trust (CA certs imported, subject configured)
+ protected TrustType trustType;
+
+ //Could be read from Metadata, RoleDescriptor protocolSupportEnumeration=
+ // "http://docs.oasis-open.org/wsfed/federation/200706"
+ // Metadata could provide more than one but one must be chosen
+ protected String protocol;
+
+ //FederateIdentity, FederateClaims
+ protected FederationType federationType;
+
+ //optional (to provide a list of IDPs)
+ protected String name;
+
+ //optional (to provide a list of IDPs)
+ protected String description;
+
+ //optional (to provide a list of IDPs)
+ protected String logo;
+
+ // Additional (possibly protocol specific parameters)
+ protected Map<String, String> parameters = new HashMap<>();
+
+
+ @XmlAttribute
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(String issuer) {
+ this.issuer = issuer;
+ }
+
+ public String getRealm() {
+ return realm;
+ }
+
+ public void setRealm(String realm) {
+ this.realm = realm;
+ }
+
+ public boolean isCacheTokens() {
+ return cacheTokens;
+ }
+
+ public void setCacheTokens(boolean cacheTokens) {
+ this.cacheTokens = cacheTokens;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getCertificate() {
+ return certificate;
+ }
+
+ public void setCertificate(String certificate) {
+ this.certificate = certificate;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public FederationType getFederationType() {
+ return federationType;
+ }
+
+ public void setFederationType(FederationType federationType) {
+ this.federationType = federationType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getLogo() {
+ return logo;
+ }
+
+ public void setLogo(String logo) {
+ this.logo = logo;
+ }
+
+ public TrustType getTrustType() {
+ return trustType;
+ }
+
+ public void setTrustType(TrustType trustType) {
+ this.trustType = trustType;
+ }
+
+ public Map<String, String> getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(Map<String, String> parameters) {
+ this.parameters = parameters;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosAuthenticationProcessingFilter.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosAuthenticationProcessingFilter.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosAuthenticationProcessingFilter.java
new file mode 100644
index 0000000..8e39e85
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosAuthenticationProcessingFilter.java
@@ -0,0 +1,199 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.apache.cxf.fediz.service.idp.kerberos;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
+import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
+import org.springframework.util.Assert;
+import org.springframework.web.filter.GenericFilterBean;
+/**
+ * Parses the SPNEGO authentication Header, which was generated by the browser
+ * and creates a {@link KerberosServiceRequestToken} out if it. It will then
+ * call the {@link AuthenticationManager}.
+ *
+ * @author Mike Wiesner
+ * @since 1.0
+ * @version $Id$
+ * @see KerberosServiceAuthenticationProvider
+ * @see KerberosEntryPoint
+ */
+public class KerberosAuthenticationProcessingFilter extends GenericFilterBean {
+ private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource =
+ new WebAuthenticationDetailsSource();
+ private AuthenticationManager authenticationManager;
+ private AuthenticationSuccessHandler successHandler;
+ private AuthenticationFailureHandler failureHandler;
+ private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
+ private boolean skipIfAlreadyAuthenticated = true;
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
+ * javax.servlet.ServletResponse, javax.servlet.FilterChain)
+ */
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest) req;
+ HttpServletResponse response = (HttpServletResponse) res;
+ if (skipIfAlreadyAuthenticated) {
+ Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
+ if (existingAuth != null && existingAuth.isAuthenticated()
+ && !(existingAuth instanceof AnonymousAuthenticationToken)) {
+ chain.doFilter(request, response);
+ return;
+ }
+ }
+ String header = request.getHeader("Authorization");
+ if ((header != null) && header.startsWith("Negotiate ")) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Received Negotiate Header for request " + request.getRequestURL() + ": " + header);
+ }
+ byte[] base64Token = header.substring(10).getBytes("UTF-8");
+ byte[] kerberosTicket = Base64.decode(base64Token);
+ KerberosServiceRequestToken authenticationRequest = new KerberosServiceRequestToken(kerberosTicket);
+ authenticationRequest.setDetails(authenticationDetailsSource.buildDetails(request));
+ Authentication authentication;
+ try {
+ authentication = authenticationManager.authenticate(authenticationRequest);
+ } catch (AuthenticationException e) {
+ //That shouldn't happen, as it is most likely a wrong
+ //configuration on the server side
+ logger.warn("Negotiate Header was invalid: " + header, e);
+ SecurityContextHolder.clearContext();
+ if (failureHandler != null) {
+ failureHandler.onAuthenticationFailure(request, response, e);
+ } else {
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ response.flushBuffer();
+ }
+ return;
+ }
+ sessionStrategy.onAuthentication(authentication, request, response);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ if (successHandler != null) {
+ successHandler.onAuthenticationSuccess(request, response, authentication);
+ }
+ }
+ chain.doFilter(request, response);
+ }
+ /**
+ * The authentication manager for validating the ticket.
+ *
+ * @param authenticationManager
+ */
+ public void setAuthenticationManager(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ }
+ /**
+ * This handler is called after a successful authentication. One can add
+ * additional authentication behavior by setting this.<br />
+ * Default is null, which means nothing additional happens
+ *
+ * @param successHandler
+ */
+ public void setSuccessHandler(AuthenticationSuccessHandler successHandler) {
+ this.successHandler = successHandler;
+ }
+ /**
+ * This handler is called after a failure authentication. In most cases you
+ * only get Kerberos/SPNEGO failures with a wrong server or network
+ * configurations and not during runtime. If the client encounters an error,
+ * he will just stop the communication with server and therefore this
+ * handler will not be called in this case.<br />
+ * Default is null, which means that the Filter returns the HTTP 500 code
+ *
+ * @param failureHandler
+ */
+ public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
+ this.failureHandler = failureHandler;
+ }
+ /**
+ * Should Kerberos authentication be skipped if a user is already authenticated
+ * for this request (e.g. in the HTTP session).
+ *
+ * @param skipIfAlreadyAuthenticated default is true
+ */
+ public void setSkipIfAlreadyAuthenticated(boolean skipIfAlreadyAuthenticated) {
+ this.skipIfAlreadyAuthenticated = skipIfAlreadyAuthenticated;
+ }
+ /**
+ * The session handling strategy which will be invoked immediately after an authentication request is
+ * successfully processed by the <tt>AuthenticationManager</tt>. Used, for example, to handle changing of the
+ * session identifier to prevent session fixation attacks.
+ *
+ * @param sessionAuthStrategy the implementation to use. If not set a null implementation is
+ * used.
+ */
+ public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionAuthStrategy) {
+ this.sessionStrategy = sessionAuthStrategy;
+ }
+ public void setAuthenticationDetailsSource(
+ AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
+ Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
+ this.authenticationDetailsSource = authenticationDetailsSource;
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.web.filter.GenericFilterBean#afterPropertiesSet()
+ */
+ @Override
+ public void afterPropertiesSet() throws ServletException {
+ super.afterPropertiesSet();
+ Assert.notNull(this.authenticationManager, "authenticationManager must be specified");
+ }
+}
+
+
+
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosEntryPoint.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosEntryPoint.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosEntryPoint.java
new file mode 100644
index 0000000..457a60e
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosEntryPoint.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * 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.apache.cxf.fediz.service.idp.kerberos;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+/**
+* Sends back a request for a Negotiate Authentication to the browser.
+*
+* @author Mike Wiesner
+* @since 1.0
+* @version $Id$
+* @see KerberosAuthenticationProcessingFilter
+*/
+public class KerberosEntryPoint implements AuthenticationEntryPoint {
+
+ private static final Log LOG = LogFactory.getLog(KerberosEntryPoint.class);
+
+ public void commence(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException ex) throws IOException, ServletException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Sending back Negotiate Header for request: " + request.getRequestURL());
+ }
+ response.addHeader("WWW-Authenticate", "Negotiate");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ response.flushBuffer();
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosServiceRequestToken.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosServiceRequestToken.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosServiceRequestToken.java
new file mode 100644
index 0000000..2aba9cf
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosServiceRequestToken.java
@@ -0,0 +1,150 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * 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.apache.cxf.fediz.service.idp.kerberos;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+
+/**
+ * Holds the Kerberos/SPNEGO token for requesting a kerberized service
+ * and is also the output of <code>KerberosServiceAuthenticationProvider</code>.<br>
+ * Will mostly be created in <code>SpnegoAuthenticationProcessingFilter</code>
+ * and authenticated in <code>KerberosServiceAuthenticationProvider</code>.
+ *
+ * This token cannot be re-authenticated, as you will get a Kerberos Reply error.
+ *
+ * @author Mike Wiesner
+ * @since 1.0
+ * @version $Id$
+ * @see KerberosServiceAuthenticationProvider
+ * @see KerberosAuthenticationProcessingFilter
+ */
+public class KerberosServiceRequestToken extends AbstractAuthenticationToken {
+ private static final long serialVersionUID = 395488921064775014L;
+ private final byte[] token;
+ private final Object principal;
+
+ /** Creates an authenticated token, normally used as an output of an authentication provider.
+ * @param principal the user principal (mostly of instance <code>UserDetails</code>
+ * @param authorities the authorities which are granted to the user
+ * @param token the Kerberos/SPNEGO token
+ * @see UserDetails
+ */
+ public KerberosServiceRequestToken(Object principal,
+ Collection<? extends GrantedAuthority> authorities,
+ byte[] token) {
+ super(authorities);
+ if (token != null) {
+ this.token = Arrays.copyOf(token, token.length);
+ } else {
+ this.token = null;
+ }
+ this.principal = principal;
+ super.setAuthenticated(true);
+ }
+
+ /**
+ * Creates an unauthenticated instance which should then be authenticated by
+ * <code>KerberosServiceAuthenticationProvider/code>
+ *
+ * @param token Kerberos/SPNEGO token
+ * @see KerberosServiceAuthenticationProvider
+ */
+ public KerberosServiceRequestToken(byte[] token) {
+ super(null);
+ if (token != null) {
+ this.token = Arrays.copyOf(token, token.length);
+ } else {
+ this.token = null;
+ }
+ this.principal = null;
+ }
+
+ /**
+ * Calculates hashcode based on the Kerberos token
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(token);
+ return result;
+ }
+
+ /**
+ * equals() is based only on the Kerberos token
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ KerberosServiceRequestToken other = (KerberosServiceRequestToken) obj;
+ if (!Arrays.equals(token, other.token)) { //NOPMD
+ return false;
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.security.core.Authentication#getCredentials()
+ */
+ public Object getCredentials() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.security.core.Authentication#getPrincipal()
+ */
+ public Object getPrincipal() {
+ return this.principal;
+ }
+
+ /** Returns the Kerberos token
+ */
+ public byte[] getToken() {
+ if (token != null) {
+ return Arrays.copyOf(token, token.length);
+ }
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosTokenValidator.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosTokenValidator.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosTokenValidator.java
new file mode 100644
index 0000000..c9b0cd7
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/KerberosTokenValidator.java
@@ -0,0 +1,185 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.kerberos;
+
+import java.security.Principal;
+import java.security.PrivilegedActionException;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.wss4j.common.kerberos.KerberosServiceContext;
+import org.apache.wss4j.common.kerberos.KerberosServiceExceptionAction;
+
+/**
+ * Validate a Kerberos Token
+ */
+public class KerberosTokenValidator {
+
+ private static final org.slf4j.Logger LOG =
+ org.slf4j.LoggerFactory.getLogger(KerberosTokenValidator.class);
+
+ private String serviceName;
+ private CallbackHandler callbackHandler;
+ private String contextName;
+ private boolean usernameServiceNameForm;
+ private boolean spnego;
+
+ /**
+ * Get the JAAS Login context name to use.
+ * @return the JAAS Login context name to use
+ */
+ public String getContextName() {
+ return contextName;
+ }
+
+ /**
+ * Set the JAAS Login context name to use.
+ * @param contextName the JAAS Login context name to use
+ */
+ public void setContextName(String contextName) {
+ this.contextName = contextName;
+ }
+
+ /**
+ * Get the CallbackHandler to use with the LoginContext
+ * @return the CallbackHandler to use with the LoginContext
+ */
+ public CallbackHandler getCallbackHandler() {
+ return callbackHandler;
+ }
+
+ /**
+ * Set the CallbackHandler to use with the LoginContext. It can be null.
+ * @param callbackHandler the CallbackHandler to use with the LoginContext
+ */
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ this.callbackHandler = callbackHandler;
+ }
+
+ /**
+ * The name of the service to use when contacting the KDC. This value can be null, in which
+ * case it defaults to the current principal name.
+ * @param serviceName the name of the service to use when contacting the KDC
+ */
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ /**
+ * Get the name of the service to use when contacting the KDC. This value can be null, in which
+ * case it defaults to the current principal name.
+ * @return the name of the service to use when contacting the KDC
+ */
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public KerberosServiceContext validate(KerberosServiceRequestToken token)
+ throws LoginException, PrivilegedActionException {
+ if (LOG.isDebugEnabled()) {
+ try {
+ String jaasAuth = System.getProperty("java.security.auth.login.config");
+ String krbConf = System.getProperty("java.security.krb5.conf");
+ LOG.debug("KerberosTokenValidator - Using JAAS auth login file: " + jaasAuth);
+ LOG.debug("KerberosTokenValidator - Using KRB conf file: " + krbConf);
+ } catch (SecurityException ex) {
+ LOG.debug(ex.getMessage(), ex);
+ }
+ }
+
+ // Get a TGT from the KDC using JAAS
+ LoginContext loginContext = null;
+ if (callbackHandler != null) {
+ loginContext = new LoginContext(getContextName(), callbackHandler);
+ } else {
+ loginContext = new LoginContext(getContextName());
+ }
+ loginContext.login();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Successfully authenticated to the TGT");
+ }
+
+ // Get the service name to use - fall back on the principal
+ Subject subject = loginContext.getSubject();
+ String service = serviceName;
+ if (service == null) {
+ Set<Principal> principals = subject.getPrincipals();
+ if (principals.isEmpty()) {
+ LOG.debug("No Client principals found after login");
+ return null;
+ }
+ service = principals.iterator().next().getName();
+ }
+
+ // Validate the ticket
+ KerberosServiceExceptionAction action =
+ new KerberosServiceExceptionAction(token.getToken(), service,
+ isUsernameServiceNameForm(), spnego);
+ KerberosServiceContext krbServiceCtx = Subject.doAs(subject, action);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Successfully validated a ticket");
+ }
+
+ return krbServiceCtx;
+ }
+
+ /**
+ * SPN can be configured to be in either <b>"hostbased"</b> or <b>"username"</b> form.<br/>
+ * - <b>"hostbased"</b> - specifies that the service principal name should be interpreted
+ * as a "host-based" name as specified in GSS API Rfc, section "4.1: Host-Based Service
+ * Name Form" - The service name, as it is specified in LDAP/AD, as it is listed in the
+ * KDC.<br/>
+ * - <b>"username"</b> - specifies that the service principal name should be interpreted
+ * as a "username" name as specified in GSS API Rfc, section "4.2: User Name Form"
+ * This is usually the client username in LDAP/AD used for authentication to the KDC.
+ *
+ * <br/><br/>Default is <b>"hostbased"</b>.
+ *
+ * @return the isUsernameServiceNameForm
+ */
+ public boolean isUsernameServiceNameForm() {
+ return usernameServiceNameForm;
+ }
+
+ /**
+ * If true - sets the SPN form to "username"
+ * <br/>If false<b>(default)</b> - the SPN form is "hostbased"
+ *
+ * @see KerberosSecurity#retrieveServiceTicket(String, CallbackHandler, String, boolean)
+ *
+ * @param isUsernameServiceNameForm the isUsernameServiceNameForm to set
+ */
+ public void setUsernameServiceNameForm(boolean isUsernameServiceNameForm) {
+ this.usernameServiceNameForm = isUsernameServiceNameForm;
+ }
+
+ public boolean isSpnego() {
+ return spnego;
+ }
+
+ public void setSpnego(boolean spnego) {
+ this.spnego = spnego;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bf309400/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/PassThroughKerberosClient.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/PassThroughKerberosClient.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/PassThroughKerberosClient.java
new file mode 100644
index 0000000..d75b812
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/kerberos/PassThroughKerberosClient.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.fediz.service.idp.kerberos;
+
+import java.util.Arrays;
+
+import org.apache.cxf.fediz.core.util.DOMUtils;
+import org.apache.cxf.ws.security.kerberos.KerberosClient;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.wss4j.common.util.KeyUtils;
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.engine.WSSConfig;
+import org.apache.wss4j.dom.message.token.KerberosSecurity;
+import org.apache.xml.security.utils.Base64;
+
+/**
+ * Override the default CXF KerberosClient just to create a BinarySecurityToken from a
+ * give Kerberos token. This is used to pass a received Kerberos token through to the
+ * STS, without retrieving a new token.
+ */
+public class PassThroughKerberosClient extends KerberosClient {
+
+ private byte[] token;
+
+ public PassThroughKerberosClient() {
+ super();
+ }
+
+ @Override
+ public SecurityToken requestSecurityToken() throws Exception {
+ KerberosSecurity bst = new KerberosSecurity(DOMUtils.createDocument());
+ bst.setValueType(WSConstants.WSS_GSS_KRB_V5_AP_REQ);
+ bst.setToken(token);
+ bst.addWSUNamespace();
+ bst.setID(WSSConfig.getNewInstance().getIdAllocator().createSecureId("BST-", bst));
+
+ SecurityToken securityToken = new SecurityToken(bst.getID());
+ securityToken.setToken(bst.getElement());
+ securityToken.setWsuId(bst.getID());
+ securityToken.setData(bst.getToken());
+ String sha1 = Base64.encode(KeyUtils.generateDigest(bst.getToken()));
+ securityToken.setSHA1(sha1);
+ securityToken.setTokenType(bst.getValueType());
+
+ return securityToken;
+ }
+
+ public byte[] getToken() {
+ if (token != null) {
+ return Arrays.copyOf(token, token.length);
+ }
+ return null;
+ }
+
+ public void setToken(byte[] token) {
+ if (token != null) {
+ this.token = Arrays.copyOf(token, token.length);
+ } else {
+ this.token = null;
+ }
+ }
+
+}