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;
+        }
+    }
+
+}