cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject cxf-fediz git commit: Adding a mock SAML SSO IdP to the systests to be used in the federation scenario with the Fediz IdP
Date Wed, 04 Mar 2015 16:00:07 GMT
Repository: cxf-fediz
Updated Branches:
  refs/heads/master 4e44b9aaf -> 1858cb9e3


Adding a mock SAML SSO IdP to the systests to be used in the federation scenario with the Fediz IdP


Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/1858cb9e
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/1858cb9e
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/1858cb9e

Branch: refs/heads/master
Commit: 1858cb9e357f0829f013df52bb265b2e883d1543
Parents: 4e44b9a
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Wed Mar 4 15:56:15 2015 +0000
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Wed Mar 4 15:56:15 2015 +0000

----------------------------------------------------------------------
 systests/federation/pom.xml                     |   1 +
 systests/federation/samlIdpWebapp/pom.xml       |  73 ++++++++
 .../fediz/samlsso/example/BasicAuthFilter.java  | 122 +++++++++++++
 .../samlsso/example/CommonCallbackHandler.java  |  46 +++++
 .../samlsso/example/SAML2CallbackHandler.java   | 147 ++++++++++++++++
 .../example/SAML2PResponseComponentBuilder.java | 126 ++++++++++++++
 .../cxf/fediz/samlsso/example/SamlSso.java      | 174 +++++++++++++++++++
 .../src/main/resources/log4j.properties         |  17 ++
 .../src/main/resources/logging.properties       |  52 ++++++
 .../src/main/resources/stsKeystoreB.properties  |   6 +
 .../src/main/resources/stsrealm_b.jks           | Bin 0 -> 2061 bytes
 .../src/main/resources/ststrust.jks             | Bin 0 -> 2561 bytes
 .../main/webapp/WEB-INF/applicationContext.xml  |  47 +++++
 .../src/main/webapp/WEB-INF/cxf-service.xml     |  68 ++++++++
 .../src/main/webapp/WEB-INF/web.xml             |  29 ++++
 .../samlIdpWebapp/src/main/webapp/index.html    |  25 +++
 .../src/main/webapp/secure/test.html            |  25 +++
 systests/federation/samlsso/pom.xml             |  10 ++
 .../cxf/fediz/integrationtests/SAMLSSOTest.java |  89 +++++++++-
 .../src/test/resources/entities-realma.xml      |   2 +-
 .../cxf/fediz/integrationtests/WSFedTest.java   |   2 +-
 21 files changed, 1054 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/pom.xml
----------------------------------------------------------------------
diff --git a/systests/federation/pom.xml b/systests/federation/pom.xml
index 870a9b4..0cd60d3 100644
--- a/systests/federation/pom.xml
+++ b/systests/federation/pom.xml
@@ -31,6 +31,7 @@
     <packaging>pom</packaging>
 
     <modules>
+        <module>samlIdpWebapp</module>
         <module>samlsso</module>
         <module>wsfed</module>
     </modules>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/pom.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/pom.xml b/systests/federation/samlIdpWebapp/pom.xml
new file mode 100644
index 0000000..10b6cdf
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.cxf.fediz.systests</groupId>
+        <artifactId>fediz-systests-federation</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <groupId>org.apache.cxf.fediz.systests.federation</groupId>
+    <artifactId>fediz-systests-federation-samlIdpWebapp</artifactId>
+    <name>Apache Fediz Federation Systests SAML SSO Mock Idp Webapp</name>
+    <packaging>war</packaging>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>${servlet.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons.lang.version}</version>
+        </dependency>      
+        <dependency>
+           <groupId>org.apache.cxf</groupId>
+           <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+           <version>${cxf.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.cxf</groupId>
+           <artifactId>cxf-rt-rs-security-sso-saml</artifactId>
+           <version>${cxf.version}</version>
+       </dependency>
+       <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+
+    </dependencies>
+    <build>
+        <!-- Name of the generated WAR file -->
+        <finalName>samlssoidp</finalName>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/BasicAuthFilter.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/BasicAuthFilter.java b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/BasicAuthFilter.java
new file mode 100644
index 0000000..29cf4df
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/BasicAuthFilter.java
@@ -0,0 +1,122 @@
+/**
+ * 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.samlsso.example;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Response;
+
+import org.w3c.dom.Document;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.wss4j.common.principal.WSUsernameTokenPrincipalImpl;
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.WSSConfig;
+import org.apache.wss4j.dom.handler.RequestData;
+import org.apache.wss4j.dom.message.token.UsernameToken;
+import org.apache.wss4j.dom.validate.Credential;
+import org.apache.wss4j.dom.validate.UsernameTokenValidator;
+
+/**
+ * A simple filter to validate a Basic Auth username/password via a CallbackHandler
+ */
+public class BasicAuthFilter implements ContainerRequestFilter {
+    
+    static {
+        WSSConfig.init();
+    }
+
+    private CallbackHandler callbackHandler;
+    
+    public void filter(ContainerRequestContext requestContext) throws IOException {
+        Message message = JAXRSUtils.getCurrentMessage();
+        AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);
+        
+        if (policy == null || policy.getUserName() == null || policy.getPassword() == null) {
+            requestContext.abortWith(
+                Response.status(401).header("WWW-Authenticate", "Basic realm=\"IdP\"").build());
+            return;
+        }
+
+        try {
+            UsernameToken token = convertPolicyToToken(policy);
+            Credential credential = new Credential();
+            credential.setUsernametoken(token);
+            
+            RequestData data = new RequestData();
+            data.setMsgContext(message);
+            data.setCallbackHandler(callbackHandler);
+            UsernameTokenValidator validator = new UsernameTokenValidator();
+            credential = validator.validate(credential, data);
+            
+            // Create a Principal/SecurityContext
+            Principal p = null;
+            if (credential != null && credential.getPrincipal() != null) {
+                p = credential.getPrincipal();
+            } else {
+                p = new WSUsernameTokenPrincipalImpl(policy.getUserName(), false);
+                ((WSUsernameTokenPrincipalImpl)p).setPassword(policy.getPassword());
+            }
+            message.put(SecurityContext.class, createSecurityContext(p));
+        } catch (Exception ex) {
+            requestContext.abortWith(
+                Response.status(401).header("WWW-Authenticate", "Basic realm=\"IdP\"").build());
+        }
+    }
+
+    protected UsernameToken convertPolicyToToken(AuthorizationPolicy policy) 
+        throws Exception {
+
+        Document doc = DOMUtils.createDocument();
+        UsernameToken token = new UsernameToken(false, doc, 
+                                                WSConstants.PASSWORD_TEXT);
+        token.setName(policy.getUserName());
+        token.setPassword(policy.getPassword());
+        return token;
+    }
+    
+    protected SecurityContext createSecurityContext(final Principal p) {
+        return new SecurityContext() {
+
+            public Principal getUserPrincipal() {
+                return p;
+            }
+
+            public boolean isUserInRole(String arg0) {
+                return false;
+            }
+        };
+    }
+
+    public CallbackHandler getCallbackHandler() {
+        return callbackHandler;
+    }
+
+    public void setCallbackHandler(CallbackHandler callbackHandler) {
+        this.callbackHandler = callbackHandler;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/CommonCallbackHandler.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/CommonCallbackHandler.java b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/CommonCallbackHandler.java
new file mode 100644
index 0000000..1576304
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/CommonCallbackHandler.java
@@ -0,0 +1,46 @@
+/**
+ * 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.samlsso.example;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.wss4j.common.ext.WSPasswordCallback;
+
+public class CommonCallbackHandler implements CallbackHandler {
+
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) { // CXF
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                if ("ALICE".equals(pc.getIdentifier())) {
+                    pc.setPassword("ECILA");
+                    break;
+                } else if ("realmb".equals(pc.getIdentifier())) {
+                    pc.setPassword("realmb");
+                    break;
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2CallbackHandler.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2CallbackHandler.java b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2CallbackHandler.java
new file mode 100644
index 0000000..39065b6
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2CallbackHandler.java
@@ -0,0 +1,147 @@
+/**
+ * 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.samlsso.example;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.wss4j.common.saml.SAMLCallback;
+import org.apache.wss4j.common.saml.bean.AttributeBean;
+import org.apache.wss4j.common.saml.bean.AttributeStatementBean;
+import org.apache.wss4j.common.saml.bean.AuthenticationStatementBean;
+import org.apache.wss4j.common.saml.bean.ConditionsBean;
+import org.apache.wss4j.common.saml.bean.SubjectBean;
+import org.apache.wss4j.common.saml.bean.SubjectConfirmationDataBean;
+import org.apache.wss4j.common.saml.builder.SAML2Constants;
+import org.opensaml.common.SAMLVersion;
+
+/**
+ * A Callback Handler implementation for a SAML 2 assertion for use by the SAML SSO IdP. By
+ * default it creates a SAML 2.0 Assertion with an AuthenticationStatement. If a list of roles 
+ * are also supplied, it will insert them as part of an AttributeStatement.
+ */
+public class SAML2CallbackHandler implements CallbackHandler {
+    
+    private String subjectName;
+    private String subjectQualifier;
+    private String confirmationMethod = SAML2Constants.CONF_BEARER;
+    private String issuer;
+    private String subjectNameIDFormat;
+    private ConditionsBean conditions;
+    private SubjectConfirmationDataBean subjectConfirmationData;
+    
+    private void createAndSetStatement(SAMLCallback callback) {
+        AuthenticationStatementBean authBean = new AuthenticationStatementBean();
+        authBean.setAuthenticationMethod("Password");
+        callback.setAuthenticationStatementData(Collections.singletonList(authBean));
+
+        // Add roles for certain users
+        List<Object> roles = new ArrayList<Object>();
+        if ("alice".equals(subjectName)) {
+            roles.add("boss");
+            roles.add("employee");
+            roles.add("User");
+        } else if ("bob".equals(subjectName)) {
+            roles.add("employee");
+        }
+        
+        if (!roles.isEmpty()) {
+            AttributeStatementBean attrBean = new AttributeStatementBean();
+            AttributeBean attributeBean = new AttributeBean();
+            attributeBean.setQualifiedName("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role");
+            attributeBean.setNameFormat(SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED);
+            attributeBean.setAttributeValues(roles);
+                
+            attrBean.setSamlAttributes(Collections.singletonList(attributeBean));
+            callback.setAttributeStatementData(Collections.singletonList(attrBean));
+        }
+    }
+    
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof SAMLCallback) {
+                SAMLCallback callback = (SAMLCallback) callbacks[i];
+                callback.setSamlVersion(SAMLVersion.VERSION_20);
+                callback.setIssuer(issuer);
+                if (conditions != null) {
+                    callback.setConditions(conditions);
+                }
+                
+                SubjectBean subjectBean = 
+                    new SubjectBean(
+                        subjectName, subjectQualifier, confirmationMethod
+                    );
+                if (subjectNameIDFormat != null) {
+                    subjectBean.setSubjectNameIDFormat(subjectNameIDFormat);
+                }
+                subjectBean.setSubjectConfirmationData(subjectConfirmationData);
+
+                callback.setSubject(subjectBean);
+                createAndSetStatement(callback);
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+    
+    public void setSubjectConfirmationData(SubjectConfirmationDataBean subjectConfirmationData) {
+        this.subjectConfirmationData = subjectConfirmationData;
+    }
+    
+    public void setConditions(ConditionsBean conditionsBean) {
+        this.conditions = conditionsBean;
+    }
+    
+    public void setConfirmationMethod(String confMethod) {
+        confirmationMethod = confMethod;
+    }
+    
+    public void setIssuer(String issuer) {
+        this.issuer = issuer;
+    }
+    
+    public void setSubjectNameIDFormat(String subjectNameIDFormat) {
+        this.subjectNameIDFormat = subjectNameIDFormat;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getSubjectQualifier() {
+        return subjectQualifier;
+    }
+
+    public void setSubjectQualifier(String subjectQualifier) {
+        this.subjectQualifier = subjectQualifier;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2PResponseComponentBuilder.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2PResponseComponentBuilder.java b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2PResponseComponentBuilder.java
new file mode 100644
index 0000000..e53f443
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SAML2PResponseComponentBuilder.java
@@ -0,0 +1,126 @@
+/**
+ * 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.samlsso.example;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.opensaml.Configuration;
+import org.opensaml.common.SAMLObjectBuilder;
+import org.opensaml.common.SAMLVersion;
+import org.opensaml.saml2.core.Issuer;
+import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.Status;
+import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.core.StatusMessage;
+import org.opensaml.xml.XMLObjectBuilderFactory;
+
+/**
+* A (basic) set of utility methods to construct SAML 2.0 Protocol Response statements
+*/
+public final class SAML2PResponseComponentBuilder {
+    
+    private static SAMLObjectBuilder<Response> responseBuilder;
+    
+    private static SAMLObjectBuilder<Issuer> issuerBuilder;
+    
+    private static SAMLObjectBuilder<Status> statusBuilder;
+    
+    private static SAMLObjectBuilder<StatusCode> statusCodeBuilder;
+    
+    private static SAMLObjectBuilder<StatusMessage> statusMessageBuilder;
+    
+    private static XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
+    
+    private SAML2PResponseComponentBuilder() {
+        
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static Response createSAMLResponse(
+        String inResponseTo,
+        String issuer,
+        Status status
+    ) {
+        if (responseBuilder == null) {
+            responseBuilder = (SAMLObjectBuilder<Response>)
+                builderFactory.getBuilder(Response.DEFAULT_ELEMENT_NAME);
+        }
+        Response response = responseBuilder.buildObject();
+        
+        response.setID(UUID.randomUUID().toString());
+        response.setIssueInstant(new DateTime());
+        response.setInResponseTo(inResponseTo);
+        response.setIssuer(createIssuer(issuer));
+        response.setStatus(status);
+        response.setVersion(SAMLVersion.VERSION_20);
+        
+        return response;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static Issuer createIssuer(
+        String issuerValue
+    ) {
+        if (issuerBuilder == null) {
+            issuerBuilder = (SAMLObjectBuilder<Issuer>)
+                builderFactory.getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
+        }
+        Issuer issuer = issuerBuilder.buildObject();
+        issuer.setValue(issuerValue);
+        
+        return issuer;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static Status createStatus(
+        String statusCodeValue,
+        String statusMessage
+    ) {
+        if (statusBuilder == null) {
+            statusBuilder = (SAMLObjectBuilder<Status>)
+                builderFactory.getBuilder(Status.DEFAULT_ELEMENT_NAME);
+        }
+        if (statusCodeBuilder == null) {
+            statusCodeBuilder = (SAMLObjectBuilder<StatusCode>)
+                builderFactory.getBuilder(StatusCode.DEFAULT_ELEMENT_NAME);
+        }
+        if (statusMessageBuilder == null) {
+            statusMessageBuilder = (SAMLObjectBuilder<StatusMessage>)
+                builderFactory.getBuilder(StatusMessage.DEFAULT_ELEMENT_NAME);
+        }
+        
+        Status status = statusBuilder.buildObject();
+        
+        StatusCode statusCode = statusCodeBuilder.buildObject();
+        statusCode.setValue(statusCodeValue);
+        status.setStatusCode(statusCode);
+        
+        if (statusMessage != null) {
+            StatusMessage statusMessageObject = statusMessageBuilder.buildObject();
+            statusMessageObject.setMessage(statusMessage);
+            status.setStatusMessage(statusMessageObject);
+        }
+        
+        return status;
+    }
+    
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java
new file mode 100644
index 0000000..d65172f
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java
@@ -0,0 +1,174 @@
+/**
+ * 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.samlsso.example;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Collections;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriBuilder;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+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.joda.time.DateTime;
+import org.opensaml.saml2.core.AuthnRequest;
+import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.Status;
+
+/**
+ * A mock IdP for SAML SSO. The user is already authenticated via HTTP/BA.
+ */
+@Path("/samlsso")
+public class SamlSso {
+    
+    static {
+        OpenSAMLUtil.initSamlEngine();
+    }
+    
+    private final DocumentBuilderFactory docBuilderFactory;
+    private MessageContext messageContext;
+    
+    public SamlSso() {
+        docBuilderFactory = DocumentBuilderFactory.newInstance();
+        docBuilderFactory.setNamespaceAware(true);
+    }
+    
+    @GET
+    public javax.ws.rs.core.Response login(@QueryParam("SAMLRequest") String samlRequest,
+            @QueryParam("RelayState") String relayState) throws Exception {
+        
+        byte[] deflatedToken = Base64Utility.decode(samlRequest);
+        InputStream tokenStream = new DeflateEncoderDecoder().inflateToken(deflatedToken);
+        
+        Document responseDoc = StaxUtils.read(new InputStreamReader(tokenStream, "UTF-8"));
+        AuthnRequest request = 
+            (AuthnRequest)OpenSAMLUtil.fromDom(responseDoc.getDocumentElement());
+        System.out.println(DOM2Writer.nodeToString(responseDoc));
+
+        String racs = request.getAssertionConsumerServiceURL();
+        String requestIssuer = request.getIssuer().getValue();
+        
+        // Create the response
+        Element response = createResponse(request.getID(), racs, requestIssuer);
+        String responseStr = encodeResponse(response);
+        
+        // Perform Redirect to RACS
+        UriBuilder ub = UriBuilder.fromUri(racs);
+        ub.queryParam("SAMLResponse", responseStr);
+        ub.queryParam("RelayState", relayState);
+        
+        // TODO hack just to keep the Fediz IdP happy
+        ub.queryParam("wtrealm", "blah");
+        ub.queryParam("wresult", "blah");
+        
+        return javax.ws.rs.core.Response.seeOther(ub.build()).build();
+    }
+    
+    @Context 
+    public void setMessageContext(MessageContext mc) {
+        this.messageContext = mc;
+    }
+
+    private Element createResponse(String requestID, String racs, String requestIssuer) throws Exception {
+        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
+        Document doc = docBuilder.newDocument();
+        
+        Status status = 
+            SAML2PResponseComponentBuilder.createStatus(
+                "urn:oasis:names:tc:SAML:2.0:status:Success", null
+            );
+        String issuer = messageContext.getUriInfo().getAbsolutePath().toString();
+        Response response = 
+            SAML2PResponseComponentBuilder.createSAMLResponse(requestID, issuer, status);
+        
+        // Create an AuthenticationAssertion
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setIssuer(issuer);
+        String user = messageContext.getSecurityContext().getUserPrincipal().getName();
+        callbackHandler.setSubjectName(user);
+        
+        // Subject Confirmation Data
+        SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean();
+        subjectConfirmationData.setAddress(messageContext.getHttpServletRequest().getRemoteAddr());
+        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);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        Crypto issuerCrypto = CryptoFactory.getInstance("stsKeystoreB.properties");
+        assertion.signAssertion("realmb", "realmb", issuerCrypto, false);
+        
+        response.getAssertions().add(assertion.getSaml2());
+        
+        Element policyElement = OpenSAMLUtil.toDom(response, doc);
+        doc.appendChild(policyElement);
+        
+        return policyElement;
+    }
+    
+    private String encodeResponse(Element response) throws IOException {
+        String responseMessage = DOM2Writer.nodeToString(response);
+        System.out.println("RESP: " + responseMessage);
+
+        DeflateEncoderDecoder encoder = new DeflateEncoderDecoder();
+        byte[] deflatedBytes = encoder.deflateToken(responseMessage.getBytes("UTF-8"));
+
+        return Base64Utility.encode(deflatedBytes);
+    }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/resources/log4j.properties b/systests/federation/samlIdpWebapp/src/main/resources/log4j.properties
new file mode 100644
index 0000000..5fc56e3
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/resources/log4j.properties
@@ -0,0 +1,17 @@
+# Set root category priority to INFO and its only appender to CONSOLE.
+log4j.rootCategory=FATAL, CONSOLE
+#log4j.rootCategory=DEBUG, CONSOLE
+
+# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.Threshold=DEBUG
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n
+
+# LOGFILE is set to be a File appender using a PatternLayout.
+log4j.appender.LOGFILE=org.apache.log4j.FileAppender
+log4j.appender.LOGFILE.File=target/wss4j.log
+log4j.appender.LOGFILE.Append=false
+log4j.appender.LOGFILE.Threshold=DEBUG
+log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/resources/logging.properties
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/resources/logging.properties b/systests/federation/samlIdpWebapp/src/main/resources/logging.properties
new file mode 100644
index 0000000..c185d61
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/resources/logging.properties
@@ -0,0 +1,52 @@
+############################################################
+#  	Default Logging Configuration File
+#
+# You can use a different file by specifying a filename
+# with the java.util.logging.config.file system property.  
+# For example java -Djava.util.logging.config.file=myfile
+############################################################
+
+############################################################
+#  	Global properties
+############################################################
+
+# "handlers" specifies a comma separated list of log Handler 
+# classes.  These handlers will be installed during VM startup.
+# Note that these classes must be on the system classpath.
+# By default we only configure a ConsoleHandler, which will only
+# show messages at the WARNING and above levels.
+handlers= java.util.logging.ConsoleHandler
+#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
+
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers.  For any given facility this global level
+# can be overridden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+.level= INFO
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = %h/java%u.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 1
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
+
+# Limit the message that are printed on the console to WARNING and above.
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+# For example, set the com.xyz.foo logger to only log SEVERE
+# messages:
+#com.xyz.foo.level = SEVERE

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/resources/stsKeystoreB.properties
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/resources/stsKeystoreB.properties b/systests/federation/samlIdpWebapp/src/main/resources/stsKeystoreB.properties
new file mode 100644
index 0000000..16f4a3c
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/resources/stsKeystoreB.properties
@@ -0,0 +1,6 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=jks
+org.apache.ws.security.crypto.merlin.keystore.password=storepass
+org.apache.ws.security.crypto.merlin.keystore.alias=realmb
+org.apache.ws.security.crypto.merlin.keystore.file=stsrealm_b.jks
+

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/resources/stsrealm_b.jks
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/resources/stsrealm_b.jks b/systests/federation/samlIdpWebapp/src/main/resources/stsrealm_b.jks
new file mode 100644
index 0000000..02075e6
Binary files /dev/null and b/systests/federation/samlIdpWebapp/src/main/resources/stsrealm_b.jks differ

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/resources/ststrust.jks
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/resources/ststrust.jks b/systests/federation/samlIdpWebapp/src/main/resources/ststrust.jks
new file mode 100644
index 0000000..911945c
Binary files /dev/null and b/systests/federation/samlIdpWebapp/src/main/resources/ststrust.jks differ

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/applicationContext.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/applicationContext.xml b/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 0000000..eea155c
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans 
+    xmlns="http://www.springframework.org/schema/beans"
+    xmlns:cxf="http://cxf.apache.org/core"
+    xmlns:jaxws="http://cxf.apache.org/jaxws"
+    xmlns:test="http://apache.org/hello_world_soap_http"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:util="http://www.springframework.org/schema/util"
+    xsi:schemaLocation="
+        http://cxf.apache.org/core
+        http://cxf.apache.org/schemas/core.xsd
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+        http://cxf.apache.org/jaxws
+        http://cxf.apache.org/schemas/jaxws.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util-2.0.xsd">
+    
+    <import resource="classpath:META-INF/cxf/cxf.xml"/>   
+    <import resource="cxf-service.xml"/>  
+    
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+    </cxf:bus>
+
+</beans>
+

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/cxf-service.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/cxf-service.xml b/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/cxf-service.xml
new file mode 100644
index 0000000..4e44578
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/cxf-service.xml
@@ -0,0 +1,68 @@
+<!--
+ 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:cxf="http://cxf.apache.org/core"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:sec="http://cxf.apache.org/configuration/security"
+  xmlns:http="http://cxf.apache.org/transports/http/configuration"
+  xmlns:jaxws="http://cxf.apache.org/jaxws"
+  xmlns:jaxrs="http://cxf.apache.org/jaxrs"
+  xsi:schemaLocation="
+            http://cxf.apache.org/core
+            http://cxf.apache.org/schemas/core.xsd
+            http://cxf.apache.org/configuration/security
+            http://cxf.apache.org/schemas/configuration/security.xsd
+            http://cxf.apache.org/jaxws
+            http://cxf.apache.org/schemas/jaxws.xsd
+            http://cxf.apache.org/jaxrs
+            http://cxf.apache.org/schemas/jaxrs.xsd
+            http://cxf.apache.org/transports/http/configuration
+            http://cxf.apache.org/schemas/configuration/http-conf.xsd
+            http://www.springframework.org/schema/beans
+            http://www.springframework.org/schema/beans/spring-beans.xsd">
+   
+   <import resource="classpath:META-INF/cxf/cxf.xml" />
+   
+   <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+   
+   <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+   </cxf:bus>
+   
+   <bean id="serviceBean" class="org.apache.cxf.fediz.samlsso.example.SamlSso" />
+   
+   <bean id="callbackHandler" class="org.apache.cxf.fediz.samlsso.example.CommonCallbackHandler"/>
+   <bean id="basicAuthFilter" class="org.apache.cxf.fediz.samlsso.example.BasicAuthFilter">
+       <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+    <jaxrs:server address="/">
+        <jaxrs:serviceBeans>
+            <ref bean="serviceBean"/>
+        </jaxrs:serviceBeans>
+        <jaxrs:providers>
+            <ref bean="basicAuthFilter"/>
+        </jaxrs:providers>
+   </jaxrs:server>
+   
+
+</beans>
+

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/web.xml b/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..11a1587
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,29 @@
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
+                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+	version="3.0" metadata-complete="true">
+
+	<description>SAML SSO Mock IdP</description>
+	<display-name>SAML SSO Mock IdP</display-name>
+
+    <context-param>
+        <param-name>contextConfigLocation</param-name>
+        <param-value>WEB-INF/applicationContext.xml</param-value>
+    </context-param>
+
+    <listener>
+        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+    </listener>
+
+    <servlet>
+        <servlet-name>SAMLSSOServlet</servlet-name>
+        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+	<servlet-mapping>
+		<servlet-name>SAMLSSOServlet</servlet-name>
+		<url-pattern>/*</url-pattern>
+	</servlet-mapping>
+
+</web-app>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/webapp/index.html
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/webapp/index.html b/systests/federation/samlIdpWebapp/src/main/webapp/index.html
new file mode 100644
index 0000000..a9dbdaa
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/webapp/index.html
@@ -0,0 +1,25 @@
+<!--
+  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.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD><TITLE>WS Federation Tomcat Examples</TITLE>
+<META http-equiv=Content-Type content="text/html">
+</HEAD>
+<BODY>
+<P>
+<H3>Hello World</H3>
+<P></P>
+</BODY></HTML>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlIdpWebapp/src/main/webapp/secure/test.html
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/webapp/secure/test.html b/systests/federation/samlIdpWebapp/src/main/webapp/secure/test.html
new file mode 100644
index 0000000..9cf7366
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/webapp/secure/test.html
@@ -0,0 +1,25 @@
+<!--
+  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.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD><TITLE>WS Federation Tomcat Examples</TITLE>
+<META http-equiv=Content-Type content="text/html">
+</HEAD>
+<BODY>
+<P>
+<H3>Secure Test</H3>
+<P></P>
+</BODY></HTML>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlsso/pom.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/pom.xml b/systests/federation/samlsso/pom.xml
index 3fd7390..2458033 100644
--- a/systests/federation/samlsso/pom.xml
+++ b/systests/federation/samlsso/pom.xml
@@ -127,6 +127,7 @@
                         <configuration>
                             <portNames>
                                 <portName>idp.https.port</portName>
+                                <portName>idp.samlsso.https.port</portName>
                                 <portName>rp.https.port</portName>
                             </portNames>
                         </configuration>
@@ -162,6 +163,14 @@
                                     <outputDirectory>target/tomcat/idp/webapps/fediz-idp-sts</outputDirectory>
                                 </artifactItem>
                                 <artifactItem>
+                                    <groupId>org.apache.cxf.fediz.systests.federation</groupId>
+                                    <artifactId>fediz-systests-federation-samlIdpWebapp</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>war</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>target/tomcat/idpsamlsso/webapps/idpsaml</outputDirectory>
+                                </artifactItem>
+                                <artifactItem>
                                     <groupId>org.apache.cxf.fediz.systests</groupId>
                                     <artifactId>fediz-systests-simpleWebapp</artifactId>
                                     <version>${project.version}</version>
@@ -235,6 +244,7 @@
                             <systemPropertyVariables>
                                 <wt.headless>true</wt.headless>
                                 <idp.https.port>${idp.https.port}</idp.https.port>
+                                <idp.samlsso.https.port>${idp.samlsso.https.port}</idp.samlsso.https.port>
                                 <rp.https.port>${rp.https.port}</rp.https.port>
                             </systemPropertyVariables>
                             <includes>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java b/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
index 17913e1..dd879c6 100644
--- a/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
+++ b/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
@@ -21,24 +21,38 @@ package org.apache.cxf.fediz.integrationtests;
 
 
 import java.io.File;
+import java.io.IOException;
+
+import com.gargoylesoftware.htmlunit.CookieManager;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
 
 import org.apache.catalina.Context;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.connector.Connector;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.cxf.fediz.tomcat.FederationAuthenticator;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 
 /**
+ * This is a test for federation in the IdP. The RP application is configured to use a home realm of "realm b". The
+ * client gets redirected to the IdP for "realm a", which in turn redirects to the IdP for "realm b", which is a 
+ * SAML SSO IdP. The IdP for "realm a" will convert the signin request to a SAML SSO sign in request. The IdP for 
+ * realm b authenticates the user, who is then redirected back to the IdP for "realm a" to get a SAML token from 
+ * the STS + then back to the application.
  */
 public class SAMLSSOTest {
 
     static String idpHttpsPort;
+    static String idpSamlSSOHttpsPort;
     static String rpHttpsPort;
     
     private static Tomcat idpServer;
+    private static Tomcat idpSamlSSOServer;
     private static Tomcat rpServer;
     
     @BeforeClass
@@ -54,10 +68,13 @@ public class SAMLSSOTest {
         
         idpHttpsPort = System.getProperty("idp.https.port");
         Assert.assertNotNull("Property 'idp.https.port' null", idpHttpsPort);
+        idpSamlSSOHttpsPort = System.getProperty("idp.samlsso.https.port");
+        Assert.assertNotNull("Property 'idp.samlsso.https.port' null", idpSamlSSOHttpsPort);
         rpHttpsPort = System.getProperty("rp.https.port");
         Assert.assertNotNull("Property 'rp.https.port' null", rpHttpsPort);
 
         initIdp();
+        initSamlSSOIdp();
         initRp();
     }
     
@@ -97,6 +114,41 @@ public class SAMLSSOTest {
         }
     }
     
+    private static void initSamlSSOIdp() {
+        try {
+            idpSamlSSOServer = new Tomcat();
+            idpSamlSSOServer.setPort(0);
+            String currentDir = new File(".").getCanonicalPath();
+            idpSamlSSOServer.setBaseDir(currentDir + File.separator + "target");
+            
+            idpSamlSSOServer.getHost().setAppBase("tomcat/idpsamlsso/webapps");
+            idpSamlSSOServer.getHost().setAutoDeploy(true);
+            idpSamlSSOServer.getHost().setDeployOnStartup(true);
+            
+            Connector httpsConnector = new Connector();
+            httpsConnector.setPort(Integer.parseInt(idpSamlSSOHttpsPort));
+            httpsConnector.setSecure(true);
+            httpsConnector.setScheme("https");
+            //httpsConnector.setAttribute("keyAlias", keyAlias);
+            httpsConnector.setAttribute("keystorePass", "tompass");
+            httpsConnector.setAttribute("keystoreFile", "test-classes/server.jks");
+            httpsConnector.setAttribute("truststorePass", "tompass");
+            httpsConnector.setAttribute("truststoreFile", "test-classes/server.jks");
+            httpsConnector.setAttribute("clientAuth", "want");
+            // httpsConnector.setAttribute("clientAuth", "false");
+            httpsConnector.setAttribute("sslProtocol", "TLS");
+            httpsConnector.setAttribute("SSLEnabled", true);
+
+            idpSamlSSOServer.getService().addConnector(httpsConnector);
+            
+            idpSamlSSOServer.addWebapp("/idp", "idpsaml");
+            
+            idpSamlSSOServer.start();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
     private static void initRp() {
         try {
             rpServer = new Tomcat();
@@ -181,15 +233,19 @@ public class SAMLSSOTest {
     @org.junit.Ignore
     public void testSAMLSSO() throws Exception {
         String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/secure/fedservlet";
-        // String user = "alice";
-        // String password = "ecila";
-        
         System.out.println("URL: " + url);
+        // Thread.sleep(60 * 2 * 1000);
         
-        Thread.sleep(60 * 2 * 1000);
         /*
+         * TODO Logging in fine to the SAML SSO IdP, but when redirected the context is missing or something
+         * Maybe a bug with htmlunit
+         *
+        String user = "ALICE";  // realm b credentials
+        String password = "ECILA";
         final String bodyTextContent = 
-            HTTPTestUtils.login(url, user, password, getIdpHttpsPort());
+            login(url, user, password, idpSamlSSOHttpsPort, idpHttpsPort);
+        
+        System.out.println("BODY: " + bodyTextContent);
         
         Assert.assertTrue("Principal not " + user,
                           bodyTextContent.contains("userPrincipal=" + user));
@@ -212,4 +268,27 @@ public class SAMLSSOTest {
          */
     }
     
+    protected static String login(String url, String user, String password, 
+                               String idpPort, String rpIdpPort) throws IOException {
+        //
+        // Access the RP + get redirected to the IdP for "realm a". Then get redirected to the IdP for
+        // "realm b".
+        //
+        final WebClient webClient = new WebClient();
+        CookieManager cookieManager = new CookieManager();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(idpPort)),
+            new UsernamePasswordCredentials(user, password));
+
+        //webClient.getOptions().setJavaScriptEnabled(false);
+        final HtmlPage idpPage = webClient.getPage(url);
+        //webClient.getOptions().setJavaScriptEnabled(true);
+        // Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        
+        return idpPage.getBody().getTextContent();
+
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/samlsso/src/test/resources/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/src/test/resources/entities-realma.xml b/systests/federation/samlsso/src/test/resources/entities-realma.xml
index 2f66591..8f8f319 100644
--- a/systests/federation/samlsso/src/test/resources/entities-realma.xml
+++ b/systests/federation/samlsso/src/test/resources/entities-realma.xml
@@ -81,7 +81,7 @@
         class="org.apache.cxf.fediz.service.idp.service.jpa.TrustedIdpEntity">
         <property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-B" />
         <property name="cacheTokens" value="true" />
-        <property name="url" value="http://localhost:12345/idp/samlsso" />
+        <property name="url" value="https://localhost:${idp.samlsso.https.port}/idp/samlsso" />
         <property name="certificate" value="realmb.cert" />
         <property name="trustType" value="PEER_TRUST" />
         <property name="protocol" value="urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser" />

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/1858cb9e/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java
----------------------------------------------------------------------
diff --git a/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java b/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java
index 0e076b4..a4f62d3 100644
--- a/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java
+++ b/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java
@@ -270,7 +270,7 @@ public class WSFedTest {
                           bodyTextContent.contains(claim + "=alice@realma.org"));
     }
     
-    public static String login(String url, String user, String password, 
+    private static String login(String url, String user, String password, 
                                            String idpPort, String rpIdpPort) throws IOException {
         //
         // Access the RP + get redirected to the IdP for "realm a". Then get redirected to the IdP for


Mime
View raw message