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 2014/07/23 18:24:05 UTC

[1/4] Adding unit tests for SAML SSO

Repository: cxf-fediz
Updated Branches:
  refs/heads/master 909e640e0 -> 617fd4e95


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java
new file mode 100644
index 0000000..09e626a
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseTest.java
@@ -0,0 +1,1378 @@
+/**
+ * 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.core.samlsso;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import org.apache.cxf.fediz.common.STSUtil;
+import org.apache.cxf.fediz.common.SecurityTestUtil;
+import org.apache.cxf.fediz.core.AbstractSAMLCallbackHandler;
+import org.apache.cxf.fediz.core.Claim;
+import org.apache.cxf.fediz.core.ClaimTypes;
+import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.KeystoreCallbackHandler;
+import org.apache.cxf.fediz.core.SAML2CallbackHandler;
+import org.apache.cxf.fediz.core.config.FedizConfigurator;
+import org.apache.cxf.fediz.core.config.FedizContext;
+import org.apache.cxf.fediz.core.config.SAMLProtocol;
+import org.apache.cxf.fediz.core.exception.ProcessingException;
+import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
+import org.apache.cxf.fediz.core.processor.FedizProcessor;
+import org.apache.cxf.fediz.core.processor.FedizRequest;
+import org.apache.cxf.fediz.core.processor.FedizResponse;
+import org.apache.cxf.fediz.core.processor.SAMLProcessorImpl;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.WSPasswordCallback;
+import org.apache.wss4j.common.ext.WSSecurityException;
+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.saml.builder.SAML2Constants;
+import org.apache.wss4j.common.util.DOM2Writer;
+import org.apache.xml.security.utils.Base64;
+import org.easymock.EasyMock;
+import org.joda.time.DateTime;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.Status;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Some tests for processing SAMLResponses using the SAMLProcessorImpl
+ */
+public class SAMLResponseTest {
+    static final String TEST_USER = "alice";
+    static final String TEST_REQUEST_URL = "https://localhost/fedizhelloworld/";
+    static final String TEST_REQUEST_URI = "/fedizhelloworld";
+    static final String TEST_IDP_ISSUER = "http://url_to_the_issuer";
+    static final String TEST_CLIENT_ADDRESS = "https://127.0.0.1";
+    
+    private static final String CONFIG_FILE = "fediz_test_config_saml.xml";
+    
+    private static Crypto crypto;
+    private static CallbackHandler cbPasswordHandler;
+    private static FedizConfigurator configurator;
+    private static DocumentBuilderFactory docBuilderFactory;
+    
+    static {
+        docBuilderFactory = DocumentBuilderFactory.newInstance();
+        docBuilderFactory.setNamespaceAware(true);
+    }
+    
+    
+    @BeforeClass
+    public static void init() {
+        try {
+            crypto = CryptoFactory.getInstance("signature.properties");
+            cbPasswordHandler = new KeystoreCallbackHandler();
+            getFederationConfigurator();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        Assert.assertNotNull(configurator);
+
+    }
+    
+    @AfterClass
+    public static void cleanup() {
+        SecurityTestUtil.cleanup();
+    }
+    
+
+    private static FedizConfigurator getFederationConfigurator() {
+        if (configurator != null) {
+            return configurator;
+        }
+        try {
+            configurator = new FedizConfigurator();
+            final URL resource = Thread.currentThread().getContextClassLoader()
+                    .getResource(CONFIG_FILE);
+            File f = new File(resource.toURI());
+            configurator.loadConfig(f);
+            return configurator;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    /**
+     * Successfully validate a SAMLResponse
+     */
+    @org.junit.Test
+    public void validateSAMLResponse() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        
+        RequestState requestState = new RequestState(TEST_REQUEST_URL,
+                                                     TEST_IDP_ISSUER,
+                                                     requestId,
+                                                     TEST_REQUEST_URL,
+                                                     (String)config.getProtocol().getIssuer(),
+                                                     null,
+                                                     System.currentTimeMillis());
+        
+        String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        ((SAMLProtocol)config.getProtocol()).getStateManager().setRequestState(relayState, requestState);
+        
+        // Create SAML Response
+        String responseStr = createSamlResponseStr(requestId);
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL));
+        EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS);
+        EasyMock.replay(req);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setResponseToken(responseStr);
+        wfReq.setState(relayState);
+        wfReq.setRequest(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_IDP_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_REQUEST_URL, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), FederationConstants.DEFAULT_ROLE_URI.toString());
+    }
+    
+    /**
+     * Validate SAMLResponse with a Response without an internal token parameter
+     */
+    @org.junit.Test
+    public void validateResponseWithoutToken() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        
+        RequestState requestState = new RequestState(TEST_REQUEST_URL,
+                                                     TEST_IDP_ISSUER,
+                                                     requestId,
+                                                     TEST_REQUEST_URL,
+                                                     (String)config.getProtocol().getIssuer(),
+                                                     null,
+                                                     System.currentTimeMillis());
+        
+        String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        ((SAMLProtocol)config.getProtocol()).getStateManager().setRequestState(relayState, requestState);
+        
+        Document doc = STSUtil.toSOAPPart(SAMLSSOTestUtils.SAMPLE_EMPTY_SAML_RESPONSE);
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL));
+        EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS);
+        EasyMock.replay(req);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setResponseToken(DOM2Writer.nodeToString(doc));
+        wfReq.setState(relayState);
+        wfReq.setRequest(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on missing security token in response");
+        } catch (ProcessingException ex) {
+            if (!TYPE.INVALID_REQUEST.equals(ex.getType())) {
+                fail("Expected ProcessingException with BAD_REQUEST type");
+            }
+        }
+    }
+    
+    @org.junit.Test
+    public void testMissingRelayState() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        
+        RequestState requestState = new RequestState(TEST_REQUEST_URL,
+                                                     TEST_IDP_ISSUER,
+                                                     requestId,
+                                                     TEST_REQUEST_URL,
+                                                     (String)config.getProtocol().getIssuer(),
+                                                     null,
+                                                     System.currentTimeMillis());
+        
+        String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        ((SAMLProtocol)config.getProtocol()).getStateManager().setRequestState(relayState, requestState);
+        
+        // Create SAML Response
+        String responseStr = createSamlResponseStr(requestId);
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL));
+        EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS);
+        EasyMock.replay(req);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setResponseToken(responseStr);
+        wfReq.setRequest(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on missing relay state in response");
+        } catch (ProcessingException ex) {
+            if (!TYPE.INVALID_REQUEST.equals(ex.getType())) {
+                fail("Expected ProcessingException with BAD_REQUEST type");
+            }
+        }
+    }
+    
+    @org.junit.Test
+    public void testNonMatchingRelayState() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        
+        RequestState requestState = new RequestState(TEST_REQUEST_URL,
+                                                     TEST_IDP_ISSUER,
+                                                     requestId,
+                                                     TEST_REQUEST_URL,
+                                                     (String)config.getProtocol().getIssuer(),
+                                                     null,
+                                                     System.currentTimeMillis());
+        
+        String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+        ((SAMLProtocol)config.getProtocol()).getStateManager().setRequestState(relayState, requestState);
+        
+        // Create SAML Response
+        String responseStr = createSamlResponseStr(requestId);
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL));
+        EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS);
+        EasyMock.replay(req);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setResponseToken(responseStr);
+        wfReq.setState("XYZ=");
+        wfReq.setRequest(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on non matching relay state in response");
+        } catch (ProcessingException ex) {
+            if (!TYPE.INVALID_REQUEST.equals(ex.getType())) {
+                fail("Expected ProcessingException with BAD_REQUEST type");
+            }
+        }
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+    @org.junit.Test
+    public void validateSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+        
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     * Not RequestedSecurityTokenCollection in this test, default in all others
+    @org.junit.Test
+    public void validateSAML2TokenRSTR() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_MSG);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 2 token which doesn't include the role SAML attribute
+    @org.junit.Test
+    public void validateSAML2TokenWithoutRoles() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setRoles(null);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("No roles must be found", null, wfRes.getRoles());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 2 token where role information is provided
+     * within another SAML attribute
+    @org.junit.Test
+    public void validateSAML2TokenDifferentRoleURI() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 2 token where role information is provided
+     * within another SAML attribute
+    @org.junit.Test
+    public void validateSAML1TokenDifferentRoleURI() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 2 token which includes role attribute
+     * but RoleURI is not configured
+    @org.junit.Test
+    public void validateSAML2TokenRoleURINotConfigured() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        ((FederationProtocol)config.getProtocol()).setRoleURI(null);
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", null, wfRes.getRoles());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 1.1 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+    @org.junit.Test
+    public void validateSAML1Token() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 1.1 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     * Token embedded in RSTR 2005/02 - WS Federation 1.0
+    @org.junit.Test
+    public void validateSAML1TokenWSFed10() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_2005_02_MSG);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multiple saml attributes with the same name
+    @org.junit.Test
+    public void validateSAML2TokenRoleMultiAttributes() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setMultiValueType(MultiValue.MULTI_ATTR);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a single saml attribute with encoded value
+    @org.junit.Test
+    public void validateSAML2TokenRoleEncodedValue() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setMultiValueType(MultiValue.ENC_VALUE);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        FederationProtocol fp = (FederationProtocol)config.getProtocol();
+        fp.setRoleDelimiter(",");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * The configured subject of the trusted issuer doesn't match with
+     * the issuer of the SAML token
+    @org.junit.Test
+    public void validateUnsignedSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", false);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");       
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            Assert.fail("Processing must fail because of missing signature");
+        } catch (ProcessingException ex) {
+            if (!TYPE.TOKEN_NO_SIGNATURE.equals(ex.getType())) {
+                fail("Expected ProcessingException with TOKEN_NO_SIGNATURE type");
+            }
+        }
+    }
+    
+    /**
+     * Validate SAML 2 token twice which causes an exception
+     * due to replay attack
+    @org.junit.Test
+    public void testReplayAttack() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        
+        wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on a replay attack");
+        } catch (ProcessingException ex) {
+            if (!TYPE.TOKEN_REPLAY.equals(ex.getType())) {
+                fail("Expected ProcessingException with TOKEN_REPLAY type");
+            }
+        }
+    }
+    
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * The configured subject of the trusted issuer doesn't match with
+     * the issuer of the SAML token
+    @org.junit.Test
+    public void validateSAML2TokenSeveralCertStore() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+    }
+
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * The configured subject of the trusted issuer doesn't match with
+     * the issuer of the SAML token
+    @org.junit.Test
+    public void validateSAML2TokenSeveralCertStoreTrustedIssuer() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT3");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+    }
+    
+    /**
+     * Validate SAML 2 token which is expired
+    @org.junit.Test
+    public void validateSAML2TokenExpired() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        DateTime currentTime = new DateTime();
+        currentTime = currentTime.minusSeconds(60);
+        cp.setNotAfter(currentTime);
+        currentTime = new DateTime();
+        currentTime = currentTime.minusSeconds(300);
+        cp.setNotBefore(currentTime);
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on expired SAML token");
+        } catch (ProcessingException ex) {
+            if (!TYPE.TOKEN_EXPIRED.equals(ex.getType())) {
+                fail("Expected ProcessingException with TOKEN_EXPIRED type");
+            }
+        }
+    }
+    
+    /**
+     * Validate SAML 2 token which is not yet valid (in 30 seconds)
+     * but within the maximum clock skew range (60 seconds)
+    @org.junit.Test
+    public void validateSAML2TokenClockSkewRange() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        DateTime currentTime = new DateTime();
+        currentTime = currentTime.plusSeconds(300);
+        cp.setNotAfter(currentTime);
+        currentTime = new DateTime();
+        currentTime = currentTime.plusSeconds(30);
+        cp.setNotBefore(currentTime);
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        config.setMaximumClockSkew(BigInteger.valueOf(60));
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+    }
+
+    /**
+     * "Validate" SAML 2 token with a custom token validator
+     * If a validator is configured it precedes the SAMLTokenValidator as part of Fediz
+    @org.junit.Test
+    public void validateSAML2TokenCustomValidator() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTTOK");
+        FederationProtocol fp = (FederationProtocol)config.getProtocol();
+        List<TokenValidator> validators = fp.getTokenValidators();
+        Assert.assertEquals("Two validators must be found", 2, validators.size());
+        Assert.assertEquals("First validator must be custom validator",
+                            CustomValidator.class.getName(), validators.get(0).getClass().getName());
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+    }
+
+    /**
+     * "Validate" SAML 2 token with a custom token validator
+     * If a validator is configured it precedes the SAMLTokenValidator as part of Fediz
+    @org.junit.Test
+    public void validateSAML2TokenMaxClockSkewNotDefined() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("NOCLOCKSKEW");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate an encrypted SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+    @org.junit.Test
+    public void validateEncryptedSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = encryptAndSignToken(assertion);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = 
+            getFederationConfigurator().getFedizContext("ROOT_DECRYPTION");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate a HolderOfKey SAML 2 token
+    @org.junit.Test
+    public void validateHOKSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        Crypto clientCrypto = CryptoFactory.getInstance("client-crypto.properties");
+        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+        cryptoType.setAlias("myclientkey");
+        X509Certificate[] certs = clientCrypto.getX509Certificates(cryptoType);
+        callbackHandler.setCerts(certs);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        assertion.signAssertion("mystskey", password, crypto, false);
+
+        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
+        Element token = assertion.toDOM(doc);
+
+        Element e = SAMLProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                        FederationConstants.WS_TRUST_13_NS);
+        if (e == null) {
+            e = SAMLProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                    FederationConstants.WS_TRUST_2005_02_NS);
+        }
+        e.appendChild(token);
+                               
+        String rstr = DOM2Writer.nodeToString(doc);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = 
+            getFederationConfigurator().getFedizContext("ROOT_DECRYPTION");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on missing client certs");
+        } catch (ProcessingException ex) {
+            // expected
+        }
+        
+        // Now set client certs
+        wfReq.setCerts(certs);      
+        wfProc.processRequest(wfReq, config);
+    }
+    
+    @org.junit.Test
+    public void validateSAML2TokenWithConfigCreatedWithAPI() throws Exception {
+        
+        ContextConfig config = new ContextConfig();
+        
+        config.setName("whatever");
+
+        // Configure certificate store
+        CertificateStores certStores = new CertificateStores();
+        TrustManagersType tm0 = new TrustManagersType();       
+        KeyStoreType ks0 = new KeyStoreType();
+        ks0.setType("JKS");
+        ks0.setPassword("storepass");
+        ks0.setFile("ststrust.jks");
+        tm0.setKeyStore(ks0);
+        certStores.getTrustManager().add(tm0);
+        config.setCertificateStores(certStores);
+        
+        // Configure trusted IDP
+        TrustedIssuers trustedIssuers = new TrustedIssuers();
+        TrustedIssuerType ti0 = new TrustedIssuerType();
+        ti0.setCertificateValidation(ValidationType.CHAIN_TRUST);
+        ti0.setName("FedizSTSIssuer");
+        ti0.setSubject(".*CN=www.sts.com.*");
+        trustedIssuers.getIssuer().add(ti0);
+        config.setTrustedIssuers(trustedIssuers);
+
+        FederationProtocolType protocol = new FederationProtocolType();
+        config.setProtocol(protocol);
+
+        AudienceUris audienceUris = new AudienceUris();
+        audienceUris.getAudienceItem().add("https://localhost/fedizhelloworld");
+        config.setAudienceUris(audienceUris);
+
+        protocol.setRoleURI("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role");
+
+        FedizContext fedContext = new FedizContext(config);
+        fedContext.init();
+        
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_MSG);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+                
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, fedContext);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        
+        fedContext.close();
+
+    }
+    */
+    
+    private String createSamlResponseStr(String requestId) throws Exception {
+        // Create SAML Assertion
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setAlsoAddAuthnStatement(true);
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_IDP_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_REQUEST_URL);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        // Subject Confirmation Data
+        SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean();
+        subjectConfirmationData.setAddress(TEST_CLIENT_ADDRESS);
+        subjectConfirmationData.setInResponseTo(requestId);
+        subjectConfirmationData.setNotAfter(new DateTime().plusMinutes(5));
+        subjectConfirmationData.setRecipient(TEST_REQUEST_URL);
+        callbackHandler.setSubjectConfirmationData(subjectConfirmationData);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        Element response = createSamlResponse(assertion, "mystskey", true, requestId);
+        return encodeResponse(response);
+    }
+    
+    private Element createSamlResponse(SamlAssertionWrapper assertion, String alias, 
+                                      boolean sign, String requestID)
+        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        if (sign) {
+            assertion.signAssertion(alias, password, crypto, false);
+        }
+        
+        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
+        Document doc = docBuilder.newDocument();
+
+        Status status =
+            SAML2PResponseComponentBuilder.createStatus(
+                "urn:oasis:names:tc:SAML:2.0:status:Success", null
+            );
+        Response response =
+            SAML2PResponseComponentBuilder.createSAMLResponse(requestID, 
+                                                              assertion.getIssuerString(), 
+                                                              status);
+
+        response.getAssertions().add(assertion.getSaml2());
+
+        Element policyElement = OpenSAMLUtil.toDom(response, doc);
+        doc.appendChild(policyElement);
+
+        return policyElement;
+    }
+    
+
+    
+    
+    /**
+     * Returns the first element that matches <code>name</code> and
+     * <code>namespace</code>. <p/> This is a replacement for a XPath lookup
+     * <code>//name</code> with the given namespace. It's somewhat faster than
+     * XPath, and we do not deal with prefixes, just with the real namespace URI
+     * 
+     * @param startNode Where to start the search
+     * @param name Local name of the element
+     * @param namespace Namespace URI of the element
+     * @return The found element or <code>null</code>
+     */
+    public static Element findElement(Node startNode, String name, String namespace) {
+        //
+        // Replace the formerly recursive implementation with a depth-first-loop
+        // lookup
+        //
+        if (startNode == null) {
+            return null;
+        }
+        Node startParent = startNode.getParentNode();
+        Node processedNode = null;
+
+        while (startNode != null) {
+            // start node processing at this point
+            if (startNode.getNodeType() == Node.ELEMENT_NODE
+                && startNode.getLocalName().equals(name)) {
+                String ns = startNode.getNamespaceURI();
+                if (ns != null && ns.equals(namespace)) {
+                    return (Element)startNode;
+                }
+
+                if ((namespace == null || namespace.length() == 0)
+                    && (ns == null || ns.length() == 0)) {
+                    return (Element)startNode;
+                }
+            }
+            processedNode = startNode;
+            startNode = startNode.getFirstChild();
+
+            // no child, this node is done.
+            if (startNode == null) {
+                // close node processing, get sibling
+                startNode = processedNode.getNextSibling();
+            }
+            // no more siblings, get parent, all children
+            // of parent are processed.
+            while (startNode == null) {
+                processedNode = processedNode.getParentNode();
+                if (processedNode == startParent) {
+                    return null;
+                }
+                // close parent node processing (processed node now)
+                startNode = processedNode.getNextSibling();
+            }
+        }
+        return null;
+    }
+
+    private void assertClaims(List<Claim> claims, String roleClaimType) {
+        for (Claim c : claims) {
+            Assert.assertTrue("Invalid ClaimType URI: " + c.getClaimType(), 
+                              c.getClaimType().equals(roleClaimType)
+                              || c.getClaimType().equals(ClaimTypes.COUNTRY)
+                              || c.getClaimType().equals(AbstractSAMLCallbackHandler.CLAIM_TYPE_LANGUAGE)
+                              );
+        }
+    }
+    
+    private String encodeResponse(Element response) throws IOException {
+        String responseMessage = DOM2Writer.nodeToString(response);
+
+        byte[] deflatedBytes = CompressionUtils.deflate(responseMessage.getBytes("UTF-8"));
+
+        return Base64.encode(deflatedBytes);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOTestUtils.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOTestUtils.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOTestUtils.java
new file mode 100644
index 0000000..842dcd8
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOTestUtils.java
@@ -0,0 +1,41 @@
+/**
+ * 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.core.samlsso;
+
+
+public final class SAMLSSOTestUtils {
+    
+ 
+    public static final String SAMPLE_EMPTY_SAML_RESPONSE = 
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        + "<saml2p:Response ID=\"c4b78949-d52e-4ae0-ad44-04ef58fe1ca8\" "
+        + "InResponseTo=\"612223b6-fb12-4c40-9a31-9bd94e09a579\" "
+        + "IssueInstant=\"2014-07-22T15:32:52.933Z\" Version=\"2.0\" "
+        + "xmlns:saml2p=\"urn:oasis:names:tc:SAML:2.0:protocol\">"
+        + "<saml2:Issuer xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\">"
+        + "http://localhost:12345/idp/samlsso</saml2:Issuer><saml2p:Status>"
+        + "<saml2p:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/>"
+        + "</saml2p:Status></saml2p:Response>";
+    
+    private SAMLSSOTestUtils() {
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/resources/fediz_test_config.xml
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/resources/fediz_test_config.xml b/plugins/core/src/test/resources/fediz_test_config.xml
index d2f83d2..48622a7 100644
--- a/plugins/core/src/test/resources/fediz_test_config.xml
+++ b/plugins/core/src/test/resources/fediz_test_config.xml
@@ -133,7 +133,7 @@
 				<claimType type="a particular claim type" optional="true" />
 			</claimTypesRequested>
 			<tokenValidators>
-				<validator>org.apache.cxf.fediz.core.CustomValidator</validator>
+				<validator>org.apache.cxf.fediz.core.federation.CustomValidator</validator>
 				<validator>org.apache.cxf.fediz.core.NonexistentCustomValidator</validator>
 			</tokenValidators>
 		</protocol>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/resources/fediz_test_config_saml.xml
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/resources/fediz_test_config_saml.xml b/plugins/core/src/test/resources/fediz_test_config_saml.xml
new file mode 100644
index 0000000..8c971d6
--- /dev/null
+++ b/plugins/core/src/test/resources/fediz_test_config_saml.xml
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<FedizConfig>
+	<contextConfig name="ROOT">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="samlProtocolType" version="1.2">
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+	</contextConfig>
+	
+	<contextConfig name="ROOT2">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="stsrealm_a.jks" password="storepass"
+					type="JKS" />
+			</trustManager>	
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="samlProtocolType" version="1.2">
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+	</contextConfig>
+	
+	<contextConfig name="ROOT3">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="stsrealm_a.jks" password="storepass"
+					type="JKS" />
+			</trustManager>	
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="samlProtocolType" version="1.2">
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+	</contextConfig>
+	<contextConfig name="CUSTTOK">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />				
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="samlProtocolType" version="1.2">
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+			<tokenValidators>
+				<validator>org.apache.cxf.fediz.core.CustomValidator</validator>
+				<validator>org.apache.cxf.fediz.core.NonexistentCustomValidator</validator>
+			</tokenValidators>
+		</protocol>
+	</contextConfig>
+	<contextConfig name="NOCLOCKSKEW">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />				
+		</trustedIssuers>
+
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="samlProtocolType" version="1.2">
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+	</contextConfig>
+	<contextConfig name="CUSTOMROLEURI">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="samlProtocolType" version="1.2">
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.mycompany.com/claims/role</roleURI>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+	</contextConfig>
+	
+	<contextConfig name="SIGNED_ROOT">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<signingKey keyPassword="stskpass" keyAlias="mystskey">
+             <keyStore file="stsstore.jks" password="stsspass" type="JKS" />
+        </signingKey>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="samlProtocolType" version="1.2">
+			<signRequest>true</signRequest>
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+	</contextConfig>	
+</FedizConfig>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ed23110..e1cb718 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
         <commons.logging.version>1.1.3</commons.logging.version>
         <cxf.version>3.0.1</cxf.version>
         <cxf.build-utils.version>2.6.0</cxf.build-utils.version>
+        <easymock.version>3.1</easymock.version>
         <ehcache.version>2.8.3</ehcache.version>
         <httpclient.version>4.3.3</httpclient.version>
         <hsqldb.version>1.8.0.10</hsqldb.version>


[3/4] Adding unit tests for SAML SSO

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/SAMLTokenValidatorOldTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/SAMLTokenValidatorOldTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/SAMLTokenValidatorOldTest.java
deleted file mode 100644
index 8785895..0000000
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/SAMLTokenValidatorOldTest.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/**
- * 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.core;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.List;
-
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.apache.cxf.fediz.common.STSUtil;
-import org.apache.cxf.fediz.common.SecurityTestUtil;
-import org.apache.cxf.fediz.core.config.FedizConfigurator;
-import org.apache.cxf.fediz.core.config.FedizContext;
-import org.apache.cxf.fediz.core.processor.FederationProcessorImpl;
-import org.apache.cxf.fediz.core.processor.FedizProcessor;
-import org.apache.cxf.fediz.core.processor.FedizRequest;
-import org.apache.cxf.fediz.core.processor.FedizResponse;
-import org.apache.wss4j.common.crypto.Crypto;
-import org.apache.wss4j.common.crypto.CryptoFactory;
-import org.apache.wss4j.common.ext.WSPasswordCallback;
-import org.apache.wss4j.common.ext.WSSecurityException;
-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.builder.SAML1Constants;
-import org.apache.wss4j.common.saml.builder.SAML2Constants;
-import org.apache.wss4j.common.util.DOM2Writer;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-
-
-// This testcases tests the encoding implemented before CXF-4484
-public class SAMLTokenValidatorOldTest {
-    static final String TEST_USER = "alice";
-    static final String TEST_RSTR_ISSUER = "FedizSTSIssuer";
-    static final String TEST_AUDIENCE = "https://localhost/fedizhelloworld";
-    
-    private static final String CONFIG_FILE = "fediz_test_config.xml";
-    
-    private static Crypto crypto;
-    private static CallbackHandler cbPasswordHandler;
-    private static FedizConfigurator configurator;
-    
-    
-    @BeforeClass
-    public static void init() {
-        try {
-            crypto = CryptoFactory.getInstance("signature.properties");
-            cbPasswordHandler = new KeystoreCallbackHandler();
-            getFederationConfigurator();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        Assert.assertNotNull(configurator);
-
-    }
-    
-    @AfterClass
-    public static void cleanup() {
-        SecurityTestUtil.cleanup();
-    }
-    
-
-    private static FedizConfigurator getFederationConfigurator() {
-        if (configurator != null) {
-            return configurator;
-        }
-        try {
-            configurator = new FedizConfigurator();
-            final URL resource = Thread.currentThread().getContextClassLoader()
-                    .getResource(CONFIG_FILE);
-            File f = new File(resource.toURI());
-            configurator.loadConfig(f);
-            return configurator;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-    
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * Roles are encoded as a multi-value saml attribute
-     */
-    @org.junit.Test
-    public void validateSAML2Token() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
-        callbackHandler.setCountryClaimName("country");
-        callbackHandler.setRoleAttributeName("role");
-        
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-        
-    }
-    
-    /**
-     * Validate SAML 2 token where role information is provided
-     * within another SAML attribute
-     */
-    @org.junit.Test
-    public void validateSAML2TokenDifferentRoleURI() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
-        callbackHandler.setCountryClaimName("country");
-        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
-        
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    /**
-     * Validate SAML 2 token where role information is provided
-     * within another SAML attribute
-     */
-    @org.junit.Test
-    public void validateSAML1TokenDifferentRoleURI() throws Exception {
-        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
-        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setUseNameFormatAsNamespace(true);
-        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
-        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    /**
-     * Validate SAML 1.1 token which includes the role attribute with 2 values
-     * Roles are encoded as a multi-value saml attribute
-     */
-    @org.junit.Test
-    public void validateSAML1Token() throws Exception {
-        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
-        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setUseNameFormatAsNamespace(true);
-        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
-        callbackHandler.setRoleAttributeName("role");
-        
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    
-    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign)
-        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
-        return createSamlToken(assertion, alias, sign, STSUtil.SAMPLE_RSTR_COLL_MSG);
-    }
-    
-    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign, String rstr)
-        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
-        WSPasswordCallback[] cb = {
-            new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE)
-        };
-        cbPasswordHandler.handle(cb);
-        String password = cb[0].getPassword();
-
-        if (sign) {
-            assertion.signAssertion(alias, password, crypto, false);
-        }
-        Document doc = STSUtil.toSOAPPart(rstr);
-        Element token = assertion.toDOM(doc);
-
-        Element e = SAMLTokenValidatorOldTest.findElement(doc, "RequestedSecurityToken",
-                                                        FederationConstants.WS_TRUST_13_NS);
-        if (e == null) {
-            e = SAMLTokenValidatorOldTest.findElement(doc, "RequestedSecurityToken",
-                                                    FederationConstants.WS_TRUST_2005_02_NS);
-        }
-        e.appendChild(token);
-        return DOM2Writer.nodeToString(doc);
-    }
-    
-
-    
-    
-    /**
-     * Returns the first element that matches <code>name</code> and
-     * <code>namespace</code>. <p/> This is a replacement for a XPath lookup
-     * <code>//name</code> with the given namespace. It's somewhat faster than
-     * XPath, and we do not deal with prefixes, just with the real namespace URI
-     * 
-     * @param startNode Where to start the search
-     * @param name Local name of the element
-     * @param namespace Namespace URI of the element
-     * @return The found element or <code>null</code>
-     */
-    public static Element findElement(Node startNode, String name, String namespace) {
-        //
-        // Replace the formerly recursive implementation with a depth-first-loop
-        // lookup
-        //
-        if (startNode == null) {
-            return null;
-        }
-        Node startParent = startNode.getParentNode();
-        Node processedNode = null;
-
-        while (startNode != null) {
-            // start node processing at this point
-            if (startNode.getNodeType() == Node.ELEMENT_NODE
-                && startNode.getLocalName().equals(name)) {
-                String ns = startNode.getNamespaceURI();
-                if (ns != null && ns.equals(namespace)) {
-                    return (Element)startNode;
-                }
-
-                if ((namespace == null || namespace.length() == 0)
-                    && (ns == null || ns.length() == 0)) {
-                    return (Element)startNode;
-                }
-            }
-            processedNode = startNode;
-            startNode = startNode.getFirstChild();
-
-            // no child, this node is done.
-            if (startNode == null) {
-                // close node processing, get sibling
-                startNode = processedNode.getNextSibling();
-            }
-            // no more siblings, get parent, all children
-            // of parent are processed.
-            while (startNode == null) {
-                processedNode = processedNode.getParentNode();
-                if (processedNode == startParent) {
-                    return null;
-                }
-                // close parent node processing (processed node now)
-                startNode = processedNode.getNextSibling();
-            }
-        }
-        return null;
-    }
-    
-    private void assertClaims(List<Claim> claims, String roleClaimType) {
-        for (Claim c : claims) {
-            Assert.assertTrue("Invalid ClaimType URI: " + c.getClaimType(), 
-                              c.getClaimType().equals(roleClaimType)
-                              || c.getClaimType().equals(ClaimTypes.COUNTRY)
-                              || c.getClaimType().equals(AbstractSAMLCallbackHandler.CLAIM_TYPE_LANGUAGE)
-                              );
-        }
-    }
-
-
-    
-
-}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/CustomValidator.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/CustomValidator.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/CustomValidator.java
new file mode 100644
index 0000000..9f988bb
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/CustomValidator.java
@@ -0,0 +1,54 @@
+/**
+ * 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.core.federation;
+
+import org.w3c.dom.Element;
+import org.apache.cxf.fediz.core.TokenValidator;
+import org.apache.cxf.fediz.core.TokenValidatorRequest;
+import org.apache.cxf.fediz.core.TokenValidatorResponse;
+import org.apache.cxf.fediz.core.config.FedizContext;
+
+
+public class CustomValidator implements TokenValidator {
+
+    @Override
+    public boolean canHandleTokenType(String tokenType) {
+        return true;
+    }
+
+    @Override
+    public boolean canHandleToken(Element token) {
+        return true;
+    }
+
+    @Override
+    public TokenValidatorResponse validateAndProcessToken(
+        TokenValidatorRequest request, 
+        FedizContext config
+    ) {
+        return new TokenValidatorResponse(null,
+                                          FederationProcessorTest.TEST_USER,
+                                          FederationProcessorTest.TEST_RSTR_ISSUER,
+                                          null,
+                                          null,
+                                          FederationProcessorTest.TEST_AUDIENCE);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationMetaDataTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationMetaDataTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationMetaDataTest.java
new file mode 100644
index 0000000..211df13
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationMetaDataTest.java
@@ -0,0 +1,117 @@
+/**
+ * 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.core.federation;
+
+import java.io.File;
+import java.net.URL;
+
+import javax.xml.transform.TransformerException;
+
+import org.w3c.dom.Document;
+import org.apache.cxf.fediz.common.SecurityTestUtil;
+import org.apache.cxf.fediz.core.config.FedizConfigurator;
+import org.apache.cxf.fediz.core.config.FedizContext;
+import org.apache.cxf.fediz.core.exception.ProcessingException;
+import org.apache.cxf.fediz.core.processor.FederationProcessorImpl;
+import org.apache.cxf.fediz.core.processor.FedizProcessor;
+import org.apache.cxf.fediz.core.util.DOMUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+
+import static org.junit.Assert.fail;
+
+public class FederationMetaDataTest {
+    private static final String CONFIG_FILE = "fediz_meta_test_config.xml";
+    
+    @AfterClass
+    public static void cleanup() {
+        SecurityTestUtil.cleanup();
+    }
+    
+
+    private FedizContext loadConfig(String context) {
+        try {
+            FedizConfigurator configurator = new FedizConfigurator();
+            final URL resource = Thread.currentThread().getContextClassLoader()
+                    .getResource(CONFIG_FILE);
+            File f = new File(resource.toURI());
+            configurator.loadConfig(f);
+            return configurator.getFedizContext(context);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+
+    @org.junit.Test
+    public void validateMetaDataWithAlias() throws ProcessingException {
+
+        FedizContext config = loadConfig("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        Document doc = wfProc.getMetaData(config);
+        Assert.assertNotNull(doc);
+        
+        try {
+            DOMUtils.writeXml(doc, System.out);
+        } catch (TransformerException e) {
+            fail("Exception not expected: " + e.getMessage()); 
+        }
+        
+    }
+
+    @org.junit.Test
+    public void validateMetaDataNoAlias() throws ProcessingException {
+
+        try {
+            FedizContext config = loadConfig("ROOT_NO_KEY");
+
+            FedizProcessor wfProc = new FederationProcessorImpl();
+            Document doc;
+           
+            doc = wfProc.getMetaData(config);
+            Assert.assertNull(doc);          
+        } catch (ProcessingException ex) {
+            //Expected as signing store contains more than one certificate
+        }
+
+        
+    }
+    
+    @org.junit.Test
+    public void validateMetaDataNoSigningKey() throws ProcessingException {
+
+        FedizContext config = loadConfig("ROOT_NO_SIGNINGKEY");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        Document doc = wfProc.getMetaData(config);
+        Assert.assertNotNull(doc);
+        
+        try {
+            DOMUtils.writeXml(doc, System.out);
+        } catch (TransformerException e) {
+            fail("Exception not expected: " + e.getMessage()); 
+        }
+        
+    }
+   
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationProcessorTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationProcessorTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationProcessorTest.java
new file mode 100644
index 0000000..fd564b2
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationProcessorTest.java
@@ -0,0 +1,1350 @@
+/**
+ * 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.core.federation;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URL;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.List;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.apache.cxf.fediz.common.STSUtil;
+import org.apache.cxf.fediz.common.SecurityTestUtil;
+import org.apache.cxf.fediz.core.AbstractSAMLCallbackHandler;
+import org.apache.cxf.fediz.core.AbstractSAMLCallbackHandler.MultiValue;
+import org.apache.cxf.fediz.core.Claim;
+import org.apache.cxf.fediz.core.ClaimTypes;
+import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.KeystoreCallbackHandler;
+import org.apache.cxf.fediz.core.SAML1CallbackHandler;
+import org.apache.cxf.fediz.core.SAML2CallbackHandler;
+import org.apache.cxf.fediz.core.TokenValidator;
+import org.apache.cxf.fediz.core.config.FederationProtocol;
+import org.apache.cxf.fediz.core.config.FedizConfigurator;
+import org.apache.cxf.fediz.core.config.FedizContext;
+import org.apache.cxf.fediz.core.config.jaxb.AudienceUris;
+import org.apache.cxf.fediz.core.config.jaxb.CertificateStores;
+import org.apache.cxf.fediz.core.config.jaxb.ContextConfig;
+import org.apache.cxf.fediz.core.config.jaxb.FederationProtocolType;
+import org.apache.cxf.fediz.core.config.jaxb.KeyStoreType;
+import org.apache.cxf.fediz.core.config.jaxb.TrustManagersType;
+import org.apache.cxf.fediz.core.config.jaxb.TrustedIssuerType;
+import org.apache.cxf.fediz.core.config.jaxb.TrustedIssuers;
+import org.apache.cxf.fediz.core.config.jaxb.ValidationType;
+import org.apache.cxf.fediz.core.exception.ProcessingException;
+import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
+import org.apache.cxf.fediz.core.processor.FederationProcessorImpl;
+import org.apache.cxf.fediz.core.processor.FedizProcessor;
+import org.apache.cxf.fediz.core.processor.FedizRequest;
+import org.apache.cxf.fediz.core.processor.FedizResponse;
+import org.apache.wss4j.common.WSEncryptionPart;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.crypto.CryptoType;
+import org.apache.wss4j.common.ext.WSPasswordCallback;
+import org.apache.wss4j.common.ext.WSSecurityException;
+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.builder.SAML1Constants;
+import org.apache.wss4j.common.saml.builder.SAML2Constants;
+import org.apache.wss4j.common.util.DOM2Writer;
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.message.WSSecEncrypt;
+import org.joda.time.DateTime;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Some tests for the WS-Federation "FederationProcessor".
+ */
+public class FederationProcessorTest {
+    static final String TEST_USER = "alice";
+    static final String TEST_RSTR_ISSUER = "FedizSTSIssuer";
+    static final String TEST_AUDIENCE = "https://localhost/fedizhelloworld";
+    
+    private static final String CONFIG_FILE = "fediz_test_config.xml";
+    
+    private static Crypto crypto;
+    private static CallbackHandler cbPasswordHandler;
+    private static FedizConfigurator configurator;
+    
+    
+    @BeforeClass
+    public static void init() {
+        try {
+            crypto = CryptoFactory.getInstance("signature.properties");
+            cbPasswordHandler = new KeystoreCallbackHandler();
+            getFederationConfigurator();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        Assert.assertNotNull(configurator);
+
+    }
+    
+    @AfterClass
+    public static void cleanup() {
+        SecurityTestUtil.cleanup();
+    }
+    
+
+    private static FedizConfigurator getFederationConfigurator() {
+        if (configurator != null) {
+            return configurator;
+        }
+        try {
+            configurator = new FedizConfigurator();
+            final URL resource = Thread.currentThread().getContextClassLoader()
+                    .getResource(CONFIG_FILE);
+            File f = new File(resource.toURI());
+            configurator.loadConfig(f);
+            return configurator;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    
+    /**
+     * Validate RSTR without RequestedSecurityToken element
+     */
+    @org.junit.Test
+    public void validateRSTRWithoutToken() throws Exception {
+        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(DOM2Writer.nodeToString(doc));
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on missing security token in RSTR");
+        } catch (ProcessingException ex) {
+            if (!TYPE.BAD_REQUEST.equals(ex.getType())) {
+                fail("Expected ProcessingException with BAD_REQUEST type");
+            }
+        }
+    }
+    
+    /**
+     * Validate FederationRequest with unknown action
+     */
+    @org.junit.Test
+    public void validateRequestUnknownAction() throws Exception {
+        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction("gugus");
+        wfReq.setResponseToken(DOM2Writer.nodeToString(doc));
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected due to invalid action");
+        } catch (ProcessingException ex) {
+            if (!TYPE.INVALID_REQUEST.equals(ex.getType())) {
+                fail("Expected ProcessingException with INVALID_REQUEST type");
+            }
+        }
+    }
+    
+    /**
+     *Validate FederationRequest with invalid RSTR/wresult
+     */
+    @org.junit.Test
+    public void validateSignInInvalidWResult() throws Exception {
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken("gugus");
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected due to invalid wresult");
+        } catch (ProcessingException ex) {
+            if (!TYPE.INVALID_REQUEST.equals(ex.getType())) {
+                fail("Expected ProcessingException with INVALID_REQUEST type");
+            }
+        }
+    }
+    
+    @org.junit.Test
+    public void validateTokenAndCreateMetadata() throws Exception {
+        validateSAML2Token();
+        FederationMetaDataTest other = new FederationMetaDataTest();
+        other.validateMetaDataWithAlias();
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     */
+    @org.junit.Test
+    public void validateSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+        
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     * Not RequestedSecurityTokenCollection in this test, default in all others
+     */
+    @org.junit.Test
+    public void validateSAML2TokenRSTR() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_MSG);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 2 token which doesn't include the role SAML attribute
+     */
+    @org.junit.Test
+    public void validateSAML2TokenWithoutRoles() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setRoles(null);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("No roles must be found", null, wfRes.getRoles());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 2 token where role information is provided
+     * within another SAML attribute
+     */
+    @org.junit.Test
+    public void validateSAML2TokenDifferentRoleURI() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 2 token where role information is provided
+     * within another SAML attribute
+     */
+    @org.junit.Test
+    public void validateSAML1TokenDifferentRoleURI() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 2 token which includes role attribute
+     * but RoleURI is not configured
+     */
+    @org.junit.Test
+    public void validateSAML2TokenRoleURINotConfigured() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        ((FederationProtocol)config.getProtocol()).setRoleURI(null);
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", null, wfRes.getRoles());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 1.1 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     */
+    @org.junit.Test
+    public void validateSAML1Token() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 1.1 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     * Token embedded in RSTR 2005/02 - WS Federation 1.0
+     */
+    @org.junit.Test
+    public void validateSAML1TokenWSFed10() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_2005_02_MSG);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multiple saml attributes with the same name
+     */
+    @org.junit.Test
+    public void validateSAML2TokenRoleMultiAttributes() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setMultiValueType(MultiValue.MULTI_ATTR);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a single saml attribute with encoded value
+     */
+    @org.junit.Test
+    public void validateSAML2TokenRoleEncodedValue() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setMultiValueType(MultiValue.ENC_VALUE);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        FederationProtocol fp = (FederationProtocol)config.getProtocol();
+        fp.setRoleDelimiter(",");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * The configured subject of the trusted issuer doesn't match with
+     * the issuer of the SAML token
+     * 
+     * Ignored because PeerTrust ignores subject attribute
+     */
+    @org.junit.Test
+    @org.junit.Ignore
+    public void validateSAML2TokenUntrustedIssuer() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        config.getTrustedIssuers().get(0).setSubject("wrong-issuer-name");        
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            Assert.fail("Processing must fail because of untrusted issuer configured");
+        } catch (ProcessingException ex) {
+            if (!TYPE.ISSUER_NOT_TRUSTED.equals(ex.getType())) {
+                fail("Expected ProcessingException with ISSUER_NOT_TRUSTED type");
+            }
+        }
+    }
+
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * The configured subject of the trusted issuer doesn't match with
+     * the issuer of the SAML token
+     */
+    @org.junit.Test
+    public void validateUnsignedSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", false);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");       
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            Assert.fail("Processing must fail because of missing signature");
+        } catch (ProcessingException ex) {
+            if (!TYPE.TOKEN_NO_SIGNATURE.equals(ex.getType())) {
+                fail("Expected ProcessingException with TOKEN_NO_SIGNATURE type");
+            }
+        }
+    }
+    
+    /**
+     * Validate SAML 2 token twice which causes an exception
+     * due to replay attack
+     */
+    @org.junit.Test
+    public void testReplayAttack() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        
+        wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on a replay attack");
+        } catch (ProcessingException ex) {
+            if (!TYPE.TOKEN_REPLAY.equals(ex.getType())) {
+                fail("Expected ProcessingException with TOKEN_REPLAY type");
+            }
+        }
+    }
+    
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * The configured subject of the trusted issuer doesn't match with
+     * the issuer of the SAML token
+     */
+    @org.junit.Test
+    public void validateSAML2TokenSeveralCertStore() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+    }
+
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * The configured subject of the trusted issuer doesn't match with
+     * the issuer of the SAML token
+     */
+    @org.junit.Test
+    public void validateSAML2TokenSeveralCertStoreTrustedIssuer() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        // Load and update the config to enforce an error
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT3");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+    }
+    
+    /**
+     * Validate SAML 2 token which is expired
+     */
+    @org.junit.Test
+    public void validateSAML2TokenExpired() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        DateTime currentTime = new DateTime();
+        currentTime = currentTime.minusSeconds(60);
+        cp.setNotAfter(currentTime);
+        currentTime = new DateTime();
+        currentTime = currentTime.minusSeconds(300);
+        cp.setNotBefore(currentTime);
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on expired SAML token");
+        } catch (ProcessingException ex) {
+            if (!TYPE.TOKEN_EXPIRED.equals(ex.getType())) {
+                fail("Expected ProcessingException with TOKEN_EXPIRED type");
+            }
+        }
+    }
+    
+    /**
+     * Validate SAML 2 token which is not yet valid (in 30 seconds)
+     * but within the maximum clock skew range (60 seconds)
+     */
+    @org.junit.Test
+    public void validateSAML2TokenClockSkewRange() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        DateTime currentTime = new DateTime();
+        currentTime = currentTime.plusSeconds(300);
+        cp.setNotAfter(currentTime);
+        currentTime = new DateTime();
+        currentTime = currentTime.plusSeconds(30);
+        cp.setNotBefore(currentTime);
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        config.setMaximumClockSkew(BigInteger.valueOf(60));
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+    }
+
+    /**
+     * "Validate" SAML 2 token with a custom token validator
+     * If a validator is configured it precedes the SAMLTokenValidator as part of Fediz
+     */
+    @org.junit.Test
+    public void validateSAML2TokenCustomValidator() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTTOK");
+        FederationProtocol fp = (FederationProtocol)config.getProtocol();
+        List<TokenValidator> validators = fp.getTokenValidators();
+        Assert.assertEquals("Two validators must be found", 2, validators.size());
+        Assert.assertEquals("First validator must be custom validator",
+                            CustomValidator.class.getName(), validators.get(0).getClass().getName());
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+    }
+
+    /**
+     * "Validate" SAML 2 token with a custom token validator
+     * If a validator is configured it precedes the SAMLTokenValidator as part of Fediz
+     */
+    @org.junit.Test
+    public void validateSAML2TokenMaxClockSkewNotDefined() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("NOCLOCKSKEW");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+    }
+    
+    /**
+     * Validate an encrypted SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     */
+    @org.junit.Test
+    public void validateEncryptedSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = encryptAndSignToken(assertion);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = 
+            getFederationConfigurator().getFedizContext("ROOT_DECRYPTION");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate a HolderOfKey SAML 2 token
+     */
+    @org.junit.Test
+    public void validateHOKSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        Crypto clientCrypto = CryptoFactory.getInstance("client-crypto.properties");
+        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+        cryptoType.setAlias("myclientkey");
+        X509Certificate[] certs = clientCrypto.getX509Certificates(cryptoType);
+        callbackHandler.setCerts(certs);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        assertion.signAssertion("mystskey", password, crypto, false);
+
+        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
+        Element token = assertion.toDOM(doc);
+
+        Element e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                        FederationConstants.WS_TRUST_13_NS);
+        if (e == null) {
+            e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                    FederationConstants.WS_TRUST_2005_02_NS);
+        }
+        e.appendChild(token);
+                               
+        String rstr = DOM2Writer.nodeToString(doc);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = 
+            getFederationConfigurator().getFedizContext("ROOT_DECRYPTION");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        try {
+            wfProc.processRequest(wfReq, config);
+            fail("Failure expected on missing client certs");
+        } catch (ProcessingException ex) {
+            // expected
+        }
+        
+        // Now set client certs
+        wfReq.setCerts(certs);      
+        wfProc.processRequest(wfReq, config);
+    }
+    
+    @org.junit.Test
+    public void validateSAML2TokenWithConfigCreatedWithAPI() throws Exception {
+        
+        ContextConfig config = new ContextConfig();
+        
+        config.setName("whatever");
+
+        // Configure certificate store
+        CertificateStores certStores = new CertificateStores();
+        TrustManagersType tm0 = new TrustManagersType();       
+        KeyStoreType ks0 = new KeyStoreType();
+        ks0.setType("JKS");
+        ks0.setPassword("storepass");
+        ks0.setFile("ststrust.jks");
+        tm0.setKeyStore(ks0);
+        certStores.getTrustManager().add(tm0);
+        config.setCertificateStores(certStores);
+        
+        // Configure trusted IDP
+        TrustedIssuers trustedIssuers = new TrustedIssuers();
+        TrustedIssuerType ti0 = new TrustedIssuerType();
+        ti0.setCertificateValidation(ValidationType.CHAIN_TRUST);
+        ti0.setName("FedizSTSIssuer");
+        ti0.setSubject(".*CN=www.sts.com.*");
+        trustedIssuers.getIssuer().add(ti0);
+        config.setTrustedIssuers(trustedIssuers);
+
+        FederationProtocolType protocol = new FederationProtocolType();
+        config.setProtocol(protocol);
+
+        AudienceUris audienceUris = new AudienceUris();
+        audienceUris.getAudienceItem().add("https://localhost/fedizhelloworld");
+        config.setAudienceUris(audienceUris);
+
+        protocol.setRoleURI("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role");
+
+        FedizContext fedContext = new FedizContext(config);
+        
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_MSG);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+                
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, fedContext);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        
+        fedContext.close();
+
+    }
+    
+    
+    private String encryptAndSignToken(
+        SamlAssertionWrapper assertion
+    ) throws Exception {
+        
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        assertion.signAssertion("mystskey", password, crypto, false);
+        
+        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
+        Element token = assertion.toDOM(doc);
+
+        Element e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                        FederationConstants.WS_TRUST_13_NS);
+        if (e == null) {
+            e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                    FederationConstants.WS_TRUST_2005_02_NS);
+        }
+        e.appendChild(token);
+        
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("mystskey");
+        
+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        builder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+        builder.setKeyEncAlgo(WSConstants.KEYTRANSPORT_RSA15);
+        builder.setEmbedEncryptedKey(true);
+        
+        WSEncryptionPart encryptionPart = new WSEncryptionPart(assertion.getId(), "Element");
+        encryptionPart.setElement(token);
+        
+        Crypto encrCrypto = CryptoFactory.getInstance("signature.properties");
+        builder.prepare(token.getOwnerDocument(), encrCrypto);
+        builder.encryptForRef(null, Collections.singletonList(encryptionPart));
+        
+        // return doc.getDocumentElement();
+        return DOM2Writer.nodeToString(doc);
+    }
+    
+    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign)
+        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
+        return createSamlToken(assertion, alias, sign, STSUtil.SAMPLE_RSTR_COLL_MSG);
+    }
+    
+    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign, String rstr)
+        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        if (sign) {
+            assertion.signAssertion(alias, password, crypto, false);
+        }
+        Document doc = STSUtil.toSOAPPart(rstr);
+        Element token = assertion.toDOM(doc);
+
+        Element e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                        FederationConstants.WS_TRUST_13_NS);
+        if (e == null) {
+            e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
+                                                    FederationConstants.WS_TRUST_2005_02_NS);
+        }
+        e.appendChild(token);
+        return DOM2Writer.nodeToString(doc);
+    }
+    
+
+    
+    
+    /**
+     * Returns the first element that matches <code>name</code> and
+     * <code>namespace</code>. <p/> This is a replacement for a XPath lookup
+     * <code>//name</code> with the given namespace. It's somewhat faster than
+     * XPath, and we do not deal with prefixes, just with the real namespace URI
+     * 
+     * @param startNode Where to start the search
+     * @param name Local name of the element
+     * @param namespace Namespace URI of the element
+     * @return The found element or <code>null</code>
+     */
+    public static Element findElement(Node startNode, String name, String namespace) {
+        //
+        // Replace the formerly recursive implementation with a depth-first-loop
+        // lookup
+        //
+        if (startNode == null) {
+            return null;
+        }
+        Node startParent = startNode.getParentNode();
+        Node processedNode = null;
+
+        while (startNode != null) {
+            // start node processing at this point
+            if (startNode.getNodeType() == Node.ELEMENT_NODE
+                && startNode.getLocalName().equals(name)) {
+                String ns = startNode.getNamespaceURI();
+                if (ns != null && ns.equals(namespace)) {
+                    return (Element)startNode;
+                }
+
+                if ((namespace == null || namespace.length() == 0)
+                    && (ns == null || ns.length() == 0)) {
+                    return (Element)startNode;
+                }
+            }
+            processedNode = startNode;
+            startNode = startNode.getFirstChild();
+
+            // no child, this node is done.
+            if (startNode == null) {
+                // close node processing, get sibling
+                startNode = processedNode.getNextSibling();
+            }
+            // no more siblings, get parent, all children
+            // of parent are processed.
+            while (startNode == null) {
+                processedNode = processedNode.getParentNode();
+                if (processedNode == startParent) {
+                    return null;
+                }
+                // close parent node processing (processed node now)
+                startNode = processedNode.getNextSibling();
+            }
+        }
+        return null;
+    }
+
+    private void assertClaims(List<Claim> claims, String roleClaimType) {
+        for (Claim c : claims) {
+            Assert.assertTrue("Invalid ClaimType URI: " + c.getClaimType(), 
+                              c.getClaimType().equals(roleClaimType)
+                              || c.getClaimType().equals(ClaimTypes.COUNTRY)
+                              || c.getClaimType().equals(AbstractSAMLCallbackHandler.CLAIM_TYPE_LANGUAGE)
+                              );
+        }
+    }
+    
+
+}


[2/4] Adding unit tests for SAML SSO

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/SAMLTokenValidatorOldTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/SAMLTokenValidatorOldTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/SAMLTokenValidatorOldTest.java
new file mode 100644
index 0000000..fb21c21
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/SAMLTokenValidatorOldTest.java
@@ -0,0 +1,399 @@
+/**
+ * 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.core.federation;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.apache.cxf.fediz.common.STSUtil;
+import org.apache.cxf.fediz.common.SecurityTestUtil;
+import org.apache.cxf.fediz.core.AbstractSAMLCallbackHandler;
+import org.apache.cxf.fediz.core.Claim;
+import org.apache.cxf.fediz.core.ClaimTypes;
+import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.KeystoreCallbackHandler;
+import org.apache.cxf.fediz.core.SAML1CallbackHandler;
+import org.apache.cxf.fediz.core.SAML2CallbackHandler;
+import org.apache.cxf.fediz.core.config.FedizConfigurator;
+import org.apache.cxf.fediz.core.config.FedizContext;
+import org.apache.cxf.fediz.core.processor.FederationProcessorImpl;
+import org.apache.cxf.fediz.core.processor.FedizProcessor;
+import org.apache.cxf.fediz.core.processor.FedizRequest;
+import org.apache.cxf.fediz.core.processor.FedizResponse;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.WSPasswordCallback;
+import org.apache.wss4j.common.ext.WSSecurityException;
+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.builder.SAML1Constants;
+import org.apache.wss4j.common.saml.builder.SAML2Constants;
+import org.apache.wss4j.common.util.DOM2Writer;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+
+// This testcases tests the encoding implemented before CXF-4484
+public class SAMLTokenValidatorOldTest {
+    static final String TEST_USER = "alice";
+    static final String TEST_RSTR_ISSUER = "FedizSTSIssuer";
+    static final String TEST_AUDIENCE = "https://localhost/fedizhelloworld";
+    
+    private static final String CONFIG_FILE = "fediz_test_config.xml";
+    
+    private static Crypto crypto;
+    private static CallbackHandler cbPasswordHandler;
+    private static FedizConfigurator configurator;
+    
+    
+    @BeforeClass
+    public static void init() {
+        try {
+            crypto = CryptoFactory.getInstance("signature.properties");
+            cbPasswordHandler = new KeystoreCallbackHandler();
+            getFederationConfigurator();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        Assert.assertNotNull(configurator);
+
+    }
+    
+    @AfterClass
+    public static void cleanup() {
+        SecurityTestUtil.cleanup();
+    }
+    
+
+    private static FedizConfigurator getFederationConfigurator() {
+        if (configurator != null) {
+            return configurator;
+        }
+        try {
+            configurator = new FedizConfigurator();
+            final URL resource = Thread.currentThread().getContextClassLoader()
+                    .getResource(CONFIG_FILE);
+            File f = new File(resource.toURI());
+            configurator.loadConfig(f);
+            return configurator;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    /**
+     * Validate SAML 2 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     */
+    @org.junit.Test
+    public void validateSAML2Token() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
+        callbackHandler.setCountryClaimName("country");
+        callbackHandler.setRoleAttributeName("role");
+        
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+        
+    }
+    
+    /**
+     * Validate SAML 2 token where role information is provided
+     * within another SAML attribute
+     */
+    @org.junit.Test
+    public void validateSAML2TokenDifferentRoleURI() throws Exception {
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
+        callbackHandler.setCountryClaimName("country");
+        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
+        
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 2 token where role information is provided
+     * within another SAML attribute
+     */
+    @org.junit.Test
+    public void validateSAML1TokenDifferentRoleURI() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setUseNameFormatAsNamespace(true);
+        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
+        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    /**
+     * Validate SAML 1.1 token which includes the role attribute with 2 values
+     * Roles are encoded as a multi-value saml attribute
+     */
+    @org.junit.Test
+    public void validateSAML1Token() throws Exception {
+        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
+        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
+        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
+        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
+        callbackHandler.setSubjectName(TEST_USER);
+        callbackHandler.setUseNameFormatAsNamespace(true);
+        callbackHandler.setAttributeNameFormat(ClaimTypes.URI_BASE.toString());
+        callbackHandler.setRoleAttributeName("role");
+        
+        ConditionsBean cp = new ConditionsBean();
+        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
+        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
+        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
+        callbackHandler.setConditions(cp);
+
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        String rstr = createSamlToken(assertion, "mystskey", true);
+        
+        FedizRequest wfReq = new FedizRequest();
+        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
+        wfReq.setResponseToken(rstr);
+        
+        configurator = null;
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        FedizProcessor wfProc = new FederationProcessorImpl();
+        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
+        
+        Assert.assertEquals("Principal name wrong", TEST_USER,
+                            wfRes.getUsername());
+        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
+        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
+                            .size());
+        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
+        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
+    }
+    
+    
+    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign)
+        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
+        return createSamlToken(assertion, alias, sign, STSUtil.SAMPLE_RSTR_COLL_MSG);
+    }
+    
+    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign, String rstr)
+        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
+        WSPasswordCallback[] cb = {
+            new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE)
+        };
+        cbPasswordHandler.handle(cb);
+        String password = cb[0].getPassword();
+
+        if (sign) {
+            assertion.signAssertion(alias, password, crypto, false);
+        }
+        Document doc = STSUtil.toSOAPPart(rstr);
+        Element token = assertion.toDOM(doc);
+
+        Element e = SAMLTokenValidatorOldTest.findElement(doc, "RequestedSecurityToken",
+                                                        FederationConstants.WS_TRUST_13_NS);
+        if (e == null) {
+            e = SAMLTokenValidatorOldTest.findElement(doc, "RequestedSecurityToken",
+                                                    FederationConstants.WS_TRUST_2005_02_NS);
+        }
+        e.appendChild(token);
+        return DOM2Writer.nodeToString(doc);
+    }
+    
+
+    
+    
+    /**
+     * Returns the first element that matches <code>name</code> and
+     * <code>namespace</code>. <p/> This is a replacement for a XPath lookup
+     * <code>//name</code> with the given namespace. It's somewhat faster than
+     * XPath, and we do not deal with prefixes, just with the real namespace URI
+     * 
+     * @param startNode Where to start the search
+     * @param name Local name of the element
+     * @param namespace Namespace URI of the element
+     * @return The found element or <code>null</code>
+     */
+    public static Element findElement(Node startNode, String name, String namespace) {
+        //
+        // Replace the formerly recursive implementation with a depth-first-loop
+        // lookup
+        //
+        if (startNode == null) {
+            return null;
+        }
+        Node startParent = startNode.getParentNode();
+        Node processedNode = null;
+
+        while (startNode != null) {
+            // start node processing at this point
+            if (startNode.getNodeType() == Node.ELEMENT_NODE
+                && startNode.getLocalName().equals(name)) {
+                String ns = startNode.getNamespaceURI();
+                if (ns != null && ns.equals(namespace)) {
+                    return (Element)startNode;
+                }
+
+                if ((namespace == null || namespace.length() == 0)
+                    && (ns == null || ns.length() == 0)) {
+                    return (Element)startNode;
+                }
+            }
+            processedNode = startNode;
+            startNode = startNode.getFirstChild();
+
+            // no child, this node is done.
+            if (startNode == null) {
+                // close node processing, get sibling
+                startNode = processedNode.getNextSibling();
+            }
+            // no more siblings, get parent, all children
+            // of parent are processed.
+            while (startNode == null) {
+                processedNode = processedNode.getParentNode();
+                if (processedNode == startParent) {
+                    return null;
+                }
+                // close parent node processing (processed node now)
+                startNode = processedNode.getNextSibling();
+            }
+        }
+        return null;
+    }
+    
+    private void assertClaims(List<Claim> claims, String roleClaimType) {
+        for (Claim c : claims) {
+            Assert.assertTrue("Invalid ClaimType URI: " + c.getClaimType(), 
+                              c.getClaimType().equals(roleClaimType)
+                              || c.getClaimType().equals(ClaimTypes.COUNTRY)
+                              || c.getClaimType().equals(AbstractSAMLCallbackHandler.CLAIM_TYPE_LANGUAGE)
+                              );
+        }
+    }
+
+
+    
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAML2PResponseComponentBuilder.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAML2PResponseComponentBuilder.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAML2PResponseComponentBuilder.java
new file mode 100644
index 0000000..ffaade7
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/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.core.samlsso;
+
+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/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
new file mode 100644
index 0000000..cfbc8d2
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
@@ -0,0 +1,205 @@
+/**
+ * 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.core.samlsso;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+
+import org.apache.cxf.fediz.common.SecurityTestUtil;
+import org.apache.cxf.fediz.core.config.FedizConfigurator;
+import org.apache.cxf.fediz.core.config.FedizContext;
+import org.apache.cxf.fediz.core.config.SAMLProtocol;
+import org.apache.cxf.fediz.core.processor.FedizProcessor;
+import org.apache.cxf.fediz.core.processor.RedirectionResponse;
+import org.apache.cxf.fediz.core.processor.SAMLProcessorImpl;
+import org.apache.cxf.fediz.core.util.DOMUtils;
+import org.apache.wss4j.common.saml.OpenSAMLUtil;
+import org.apache.xml.security.utils.Base64;
+import org.easymock.EasyMock;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.opensaml.saml2.core.AuthnRequest;
+
+/**
+ * Some tests for creating SAMLRequests using the SAMLProcessorImpl
+ */
+public class SAMLRequestTest {
+    static final String TEST_USER = "alice";
+    static final String TEST_REQUEST_URL = "https://localhost/fedizhelloworld/";
+    static final String TEST_REQUEST_URI = "/fedizhelloworld";
+    static final String TEST_IDP_ISSUER = "http://url_to_the_issuer";
+    static final String TEST_CLIENT_ADDRESS = "https://127.0.0.1";
+    
+    private static final String CONFIG_FILE = "fediz_test_config_saml.xml";
+    
+    private static FedizConfigurator configurator;
+    private static DocumentBuilderFactory docBuilderFactory;
+    
+    static {
+        docBuilderFactory = DocumentBuilderFactory.newInstance();
+        docBuilderFactory.setNamespaceAware(true);
+    }
+    
+    
+    @BeforeClass
+    public static void init() {
+        getFederationConfigurator();
+        Assert.assertNotNull(configurator);
+    }
+    
+    @AfterClass
+    public static void cleanup() {
+        SecurityTestUtil.cleanup();
+    }
+    
+
+    private static FedizConfigurator getFederationConfigurator() {
+        if (configurator != null) {
+            return configurator;
+        }
+        try {
+            configurator = new FedizConfigurator();
+            final URL resource = Thread.currentThread().getContextClassLoader()
+                    .getResource(CONFIG_FILE);
+            File f = new File(resource.toURI());
+            configurator.loadConfig(f);
+            return configurator;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    @org.junit.Test
+    public void createSAMLRequest() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)).times(1, 2);
+        EasyMock.expect(req.getContextPath()).andReturn(TEST_REQUEST_URI);
+        EasyMock.expect(req.getRequestURI()).andReturn(TEST_REQUEST_URI).times(1, 2);
+        EasyMock.replay(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        RedirectionResponse response = wfProc.createSignInRequest(req, config);
+        
+        String redirectionURL = response.getRedirectionURL();
+        Assert.assertTrue(redirectionURL.startsWith(TEST_IDP_ISSUER));
+        Assert.assertTrue(redirectionURL.contains("SAMLRequest="));
+        Assert.assertTrue(redirectionURL.contains("RelayState="));
+        
+        Map<String, String> headers = response.getHeaders();
+        Assert.assertNotNull(headers);
+        Assert.assertFalse(headers.isEmpty());
+        Assert.assertTrue(headers.containsKey("Set-Cookie"));
+        Assert.assertTrue("no-cache, no-store".equals(headers.get("Cache-Control")));
+        Assert.assertTrue("no-cache".equals(headers.get("Pragma")));
+    }
+    
+    @org.junit.Test
+    public void testRelayState() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)).times(1, 2);
+        EasyMock.expect(req.getContextPath()).andReturn(TEST_REQUEST_URI);
+        EasyMock.expect(req.getRequestURI()).andReturn(TEST_REQUEST_URI).times(1, 2);
+        EasyMock.replay(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        RedirectionResponse response = wfProc.createSignInRequest(req, config);
+        
+        String redirectionURL = response.getRedirectionURL();
+        String relayState = 
+            redirectionURL.substring(redirectionURL.indexOf("RelayState=") + "RelayState=".length());
+        
+        // Now retrieve the RequestState corresponding to the RelayState
+        RequestState requestState = 
+            ((SAMLProtocol)config.getProtocol()).getStateManager().removeRequestState(relayState);
+        Assert.assertNotNull(requestState);
+        
+        Assert.assertEquals(TEST_IDP_ISSUER, requestState.getIdpServiceAddress());
+        Assert.assertEquals(TEST_REQUEST_URL, requestState.getIssuerId());
+        Assert.assertEquals(TEST_REQUEST_URL, requestState.getTargetAddress());
+    }
+    
+    @org.junit.Test
+    public void testSAMLRequest() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)).times(1, 2);
+        EasyMock.expect(req.getContextPath()).andReturn(TEST_REQUEST_URI);
+        EasyMock.expect(req.getRequestURI()).andReturn(TEST_REQUEST_URI).times(1, 2);
+        EasyMock.replay(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        RedirectionResponse response = wfProc.createSignInRequest(req, config);
+        
+        String redirectionURL = response.getRedirectionURL();
+        String samlRequest = 
+            redirectionURL.substring(redirectionURL.indexOf("SAMLRequest=") + "SAMLRequest=".length(),
+                                     redirectionURL.indexOf("RelayState=") - 1);
+        
+        byte[] deflatedToken = Base64.decode(URLDecoder.decode(samlRequest, "UTF-8"));
+        InputStream tokenStream = CompressionUtils.inflate(deflatedToken);
+
+        Document requestDoc = DOMUtils.readXml(new InputStreamReader(tokenStream, "UTF-8"));
+        AuthnRequest request =
+            (AuthnRequest)OpenSAMLUtil.fromDom(requestDoc.getDocumentElement());
+
+        Assert.assertEquals(TEST_REQUEST_URL, request.getIssuer().getValue());
+        Assert.assertEquals(TEST_REQUEST_URL, request.getAssertionConsumerServiceURL());
+    }
+    
+    @org.junit.Test
+    public void testSignedSAMLRequest() throws Exception {
+        // Mock up a Request
+        FedizContext config = getFederationConfigurator().getFedizContext("SIGNED_ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)).times(1, 2);
+        EasyMock.expect(req.getContextPath()).andReturn(TEST_REQUEST_URI);
+        EasyMock.expect(req.getRequestURI()).andReturn(TEST_REQUEST_URI).times(1, 2);
+        EasyMock.replay(req);
+        
+        FedizProcessor wfProc = new SAMLProcessorImpl();
+        RedirectionResponse response = wfProc.createSignInRequest(req, config);
+        
+        String redirectionURL = response.getRedirectionURL();
+        String signature = 
+            redirectionURL.substring(redirectionURL.indexOf("Signature=") + "Signature=".length());
+        Assert.assertTrue(signature != null && signature.length() > 0);
+    }
+    
+}
\ No newline at end of file


[4/4] git commit: Adding unit tests for SAML SSO

Posted by co...@apache.org.
Adding unit tests for SAML SSO


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

Branch: refs/heads/master
Commit: 617fd4e95f61194a76eb734b1132f82b27d06102
Parents: 909e640
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Jul 23 17:23:43 2014 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Jul 23 17:23:43 2014 +0100

----------------------------------------------------------------------
 plugins/core/pom.xml                            |    6 +
 .../fediz/core/AbstractSAMLCallbackHandler.java |   19 +-
 .../apache/cxf/fediz/core/CustomValidator.java  |   51 -
 .../cxf/fediz/core/FederationMetaDataTest.java  |  117 --
 .../cxf/fediz/core/FederationProcessorTest.java | 1340 -----------------
 .../fediz/core/SAMLTokenValidatorOldTest.java   |  392 -----
 .../fediz/core/federation/CustomValidator.java  |   54 +
 .../core/federation/FederationMetaDataTest.java |  117 ++
 .../federation/FederationProcessorTest.java     | 1350 +++++++++++++++++
 .../federation/SAMLTokenValidatorOldTest.java   |  399 +++++
 .../samlsso/SAML2PResponseComponentBuilder.java |  126 ++
 .../cxf/fediz/core/samlsso/SAMLRequestTest.java |  205 +++
 .../fediz/core/samlsso/SAMLResponseTest.java    | 1378 ++++++++++++++++++
 .../fediz/core/samlsso/SAMLSSOTestUtils.java    |   41 +
 .../src/test/resources/fediz_test_config.xml    |    2 +-
 .../test/resources/fediz_test_config_saml.xml   |  196 +++
 pom.xml                                         |    1 +
 17 files changed, 3889 insertions(+), 1905 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/core/pom.xml b/plugins/core/pom.xml
index 0c85b21..fc53ba5 100644
--- a/plugins/core/pom.xml
+++ b/plugins/core/pom.xml
@@ -67,6 +67,12 @@
             <version>${servlet.version}</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <version>${easymock.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/AbstractSAMLCallbackHandler.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/AbstractSAMLCallbackHandler.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/AbstractSAMLCallbackHandler.java
index 3ff69f0..78629b0 100644
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/AbstractSAMLCallbackHandler.java
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/AbstractSAMLCallbackHandler.java
@@ -73,6 +73,7 @@ public abstract class AbstractSAMLCallbackHandler implements CallbackHandler {
     protected String confirmationMethod;
     protected X509Certificate[] certs;
     protected Statement statement = Statement.AUTHN;
+    protected boolean alsoAddAuthnStatement;
     protected CERT_IDENTIFIER certIdentifier = CERT_IDENTIFIER.X509_CERT;
     protected byte[] ephemeralKey;
     protected String issuer;
@@ -203,7 +204,7 @@ public abstract class AbstractSAMLCallbackHandler implements CallbackHandler {
      */
     //CHECKSTYLE:OFF
     protected void createAndSetStatement(SubjectBean subjectBean, SAMLCallback callback) {
-        if (statement == Statement.AUTHN) {
+        if (alsoAddAuthnStatement || statement == Statement.AUTHN) {
             AuthenticationStatementBean authBean = new AuthenticationStatementBean();
             if (subjectBean != null) {
                 authBean.setSubject(subjectBean);
@@ -216,7 +217,9 @@ public abstract class AbstractSAMLCallbackHandler implements CallbackHandler {
             }
             authBean.setAuthenticationMethod("Password");
             callback.setAuthenticationStatementData(Collections.singletonList(authBean));
-        } else if (statement == Statement.ATTR) {
+        }
+        
+        if (statement == Statement.ATTR) {
             AttributeStatementBean attrStateBean = new AttributeStatementBean();
             if (subjectBean != null) {
                 attrStateBean.setSubject(subjectBean);
@@ -357,7 +360,7 @@ public abstract class AbstractSAMLCallbackHandler implements CallbackHandler {
             attrStateBean.setSamlAttributes(attributeList);
             callback.setAttributeStatementData(Collections.singletonList(attrStateBean));
                        
-        } else {
+        } else if (statement == Statement.AUTHZ) {
             AuthDecisionStatementBean authzBean = new AuthDecisionStatementBean();
             if (subjectBean != null) {
                 authzBean.setSubject(subjectBean);
@@ -374,7 +377,7 @@ public abstract class AbstractSAMLCallbackHandler implements CallbackHandler {
     
     protected KeyInfoBean createKeyInfo() throws Exception {
         KeyInfoBean keyInfo = new KeyInfoBean();
-        if (statement == Statement.AUTHN) {
+        if (alsoAddAuthnStatement || statement == Statement.AUTHN) {
             keyInfo.setCertificate(certs[0]);
             keyInfo.setCertIdentifer(certIdentifier);
         } else if (statement == Statement.ATTR) {
@@ -417,4 +420,12 @@ public abstract class AbstractSAMLCallbackHandler implements CallbackHandler {
         int i = claimType.lastIndexOf("/");
         return claimType.substring(i + 1);
     }
+    
+    public boolean isAlsoAddAuthnStatement() {
+        return alsoAddAuthnStatement;
+    }
+
+    public void setAlsoAddAuthnStatement(boolean alsoAddAuthnStatement) {
+        this.alsoAddAuthnStatement = alsoAddAuthnStatement;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/CustomValidator.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/CustomValidator.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/CustomValidator.java
deleted file mode 100644
index f67edae..0000000
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/CustomValidator.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * 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.core;
-
-import org.w3c.dom.Element;
-import org.apache.cxf.fediz.core.config.FedizContext;
-
-
-public class CustomValidator implements TokenValidator {
-
-    @Override
-    public boolean canHandleTokenType(String tokenType) {
-        return true;
-    }
-
-    @Override
-    public boolean canHandleToken(Element token) {
-        return true;
-    }
-
-    @Override
-    public TokenValidatorResponse validateAndProcessToken(
-        TokenValidatorRequest request, 
-        FedizContext config
-    ) {
-        return new TokenValidatorResponse(null,
-                                          FederationProcessorTest.TEST_USER,
-                                          FederationProcessorTest.TEST_RSTR_ISSUER,
-                                          null,
-                                          null,
-                                          FederationProcessorTest.TEST_AUDIENCE);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationMetaDataTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationMetaDataTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationMetaDataTest.java
deleted file mode 100644
index 150eb08..0000000
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationMetaDataTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * 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.core;
-
-import java.io.File;
-import java.net.URL;
-
-import javax.xml.transform.TransformerException;
-
-import org.w3c.dom.Document;
-import org.apache.cxf.fediz.common.SecurityTestUtil;
-import org.apache.cxf.fediz.core.config.FedizConfigurator;
-import org.apache.cxf.fediz.core.config.FedizContext;
-import org.apache.cxf.fediz.core.exception.ProcessingException;
-import org.apache.cxf.fediz.core.processor.FederationProcessorImpl;
-import org.apache.cxf.fediz.core.processor.FedizProcessor;
-import org.apache.cxf.fediz.core.util.DOMUtils;
-import org.junit.AfterClass;
-import org.junit.Assert;
-
-import static org.junit.Assert.fail;
-
-public class FederationMetaDataTest {
-    private static final String CONFIG_FILE = "fediz_meta_test_config.xml";
-    
-    @AfterClass
-    public static void cleanup() {
-        SecurityTestUtil.cleanup();
-    }
-    
-
-    private FedizContext loadConfig(String context) {
-        try {
-            FedizConfigurator configurator = new FedizConfigurator();
-            final URL resource = Thread.currentThread().getContextClassLoader()
-                    .getResource(CONFIG_FILE);
-            File f = new File(resource.toURI());
-            configurator.loadConfig(f);
-            return configurator.getFedizContext(context);
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-    
-
-    @org.junit.Test
-    public void validateMetaDataWithAlias() throws ProcessingException {
-
-        FedizContext config = loadConfig("ROOT");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        Document doc = wfProc.getMetaData(config);
-        Assert.assertNotNull(doc);
-        
-        try {
-            DOMUtils.writeXml(doc, System.out);
-        } catch (TransformerException e) {
-            fail("Exception not expected: " + e.getMessage()); 
-        }
-        
-    }
-
-    @org.junit.Test
-    public void validateMetaDataNoAlias() throws ProcessingException {
-
-        try {
-            FedizContext config = loadConfig("ROOT_NO_KEY");
-
-            FedizProcessor wfProc = new FederationProcessorImpl();
-            Document doc;
-           
-            doc = wfProc.getMetaData(config);
-            Assert.assertNull(doc);          
-        } catch (ProcessingException ex) {
-            //Expected as signing store contains more than one certificate
-        }
-
-        
-    }
-    
-    @org.junit.Test
-    public void validateMetaDataNoSigningKey() throws ProcessingException {
-
-        FedizContext config = loadConfig("ROOT_NO_SIGNINGKEY");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        Document doc = wfProc.getMetaData(config);
-        Assert.assertNotNull(doc);
-        
-        try {
-            DOMUtils.writeXml(doc, System.out);
-        } catch (TransformerException e) {
-            fail("Exception not expected: " + e.getMessage()); 
-        }
-        
-    }
-   
-
-}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/617fd4e9/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java
deleted file mode 100644
index cc533a9..0000000
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/FederationProcessorTest.java
+++ /dev/null
@@ -1,1340 +0,0 @@
-/**
- * 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.core;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URL;
-import java.security.cert.X509Certificate;
-import java.util.Collections;
-import java.util.List;
-
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.apache.cxf.fediz.common.STSUtil;
-import org.apache.cxf.fediz.common.SecurityTestUtil;
-import org.apache.cxf.fediz.core.AbstractSAMLCallbackHandler.MultiValue;
-import org.apache.cxf.fediz.core.config.FederationProtocol;
-import org.apache.cxf.fediz.core.config.FedizConfigurator;
-import org.apache.cxf.fediz.core.config.FedizContext;
-import org.apache.cxf.fediz.core.config.jaxb.AudienceUris;
-import org.apache.cxf.fediz.core.config.jaxb.CertificateStores;
-import org.apache.cxf.fediz.core.config.jaxb.ContextConfig;
-import org.apache.cxf.fediz.core.config.jaxb.FederationProtocolType;
-import org.apache.cxf.fediz.core.config.jaxb.KeyStoreType;
-import org.apache.cxf.fediz.core.config.jaxb.TrustManagersType;
-import org.apache.cxf.fediz.core.config.jaxb.TrustedIssuerType;
-import org.apache.cxf.fediz.core.config.jaxb.TrustedIssuers;
-import org.apache.cxf.fediz.core.config.jaxb.ValidationType;
-import org.apache.cxf.fediz.core.exception.ProcessingException;
-import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
-import org.apache.cxf.fediz.core.processor.FederationProcessorImpl;
-import org.apache.cxf.fediz.core.processor.FedizProcessor;
-import org.apache.cxf.fediz.core.processor.FedizRequest;
-import org.apache.cxf.fediz.core.processor.FedizResponse;
-import org.apache.wss4j.common.WSEncryptionPart;
-import org.apache.wss4j.common.crypto.Crypto;
-import org.apache.wss4j.common.crypto.CryptoFactory;
-import org.apache.wss4j.common.crypto.CryptoType;
-import org.apache.wss4j.common.ext.WSPasswordCallback;
-import org.apache.wss4j.common.ext.WSSecurityException;
-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.builder.SAML1Constants;
-import org.apache.wss4j.common.saml.builder.SAML2Constants;
-import org.apache.wss4j.common.util.DOM2Writer;
-import org.apache.wss4j.dom.WSConstants;
-import org.apache.wss4j.dom.message.WSSecEncrypt;
-import org.joda.time.DateTime;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-
-import static org.junit.Assert.fail;
-
-public class FederationProcessorTest {
-    static final String TEST_USER = "alice";
-    static final String TEST_RSTR_ISSUER = "FedizSTSIssuer";
-    static final String TEST_AUDIENCE = "https://localhost/fedizhelloworld";
-    
-    private static final String CONFIG_FILE = "fediz_test_config.xml";
-    
-    private static Crypto crypto;
-    private static CallbackHandler cbPasswordHandler;
-    private static FedizConfigurator configurator;
-    
-    
-    @BeforeClass
-    public static void init() {
-        try {
-            crypto = CryptoFactory.getInstance("signature.properties");
-            cbPasswordHandler = new KeystoreCallbackHandler();
-            getFederationConfigurator();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        Assert.assertNotNull(configurator);
-
-    }
-    
-    @AfterClass
-    public static void cleanup() {
-        SecurityTestUtil.cleanup();
-    }
-    
-
-    private static FedizConfigurator getFederationConfigurator() {
-        if (configurator != null) {
-            return configurator;
-        }
-        try {
-            configurator = new FedizConfigurator();
-            final URL resource = Thread.currentThread().getContextClassLoader()
-                    .getResource(CONFIG_FILE);
-            File f = new File(resource.toURI());
-            configurator.loadConfig(f);
-            return configurator;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    
-    /**
-     * Validate RSTR without RequestedSecurityToken element
-     */
-    @org.junit.Test
-    public void validateRSTRWithoutToken() throws Exception {
-        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(DOM2Writer.nodeToString(doc));
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            fail("Failure expected on missing security token in RSTR");
-        } catch (ProcessingException ex) {
-            if (!TYPE.BAD_REQUEST.equals(ex.getType())) {
-                fail("Expected ProcessingException with BAD_REQUEST type");
-            }
-        }
-    }
-    
-    /**
-     * Validate FederationRequest with unknown action
-     */
-    @org.junit.Test
-    public void validateRequestUnknownAction() throws Exception {
-        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction("gugus");
-        wfReq.setResponseToken(DOM2Writer.nodeToString(doc));
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            fail("Failure expected due to invalid action");
-        } catch (ProcessingException ex) {
-            if (!TYPE.INVALID_REQUEST.equals(ex.getType())) {
-                fail("Expected ProcessingException with INVALID_REQUEST type");
-            }
-        }
-    }
-    
-    /**
-     *Validate FederationRequest with invalid RSTR/wresult
-     */
-    @org.junit.Test
-    public void validateSignInInvalidWResult() throws Exception {
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken("gugus");
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            fail("Failure expected due to invalid wresult");
-        } catch (ProcessingException ex) {
-            if (!TYPE.INVALID_REQUEST.equals(ex.getType())) {
-                fail("Expected ProcessingException with INVALID_REQUEST type");
-            }
-        }
-    }
-    
-    @org.junit.Test
-    public void validateTokenAndCreateMetadata() throws Exception {
-        validateSAML2Token();
-        FederationMetaDataTest other = new FederationMetaDataTest();
-        other.validateMetaDataWithAlias();
-    }
-    
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * Roles are encoded as a multi-value saml attribute
-     */
-    @org.junit.Test
-    public void validateSAML2Token() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-        
-    }
-    
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * Roles are encoded as a multi-value saml attribute
-     * Not RequestedSecurityTokenCollection in this test, default in all others
-     */
-    @org.junit.Test
-    public void validateSAML2TokenRSTR() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_MSG);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-    }
-    
-    /**
-     * Validate SAML 2 token which doesn't include the role SAML attribute
-     */
-    @org.junit.Test
-    public void validateSAML2TokenWithoutRoles() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setRoles(null);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("No roles must be found", null, wfRes.getRoles());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-    }
-    
-    /**
-     * Validate SAML 2 token where role information is provided
-     * within another SAML attribute
-     */
-    @org.junit.Test
-    public void validateSAML2TokenDifferentRoleURI() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    /**
-     * Validate SAML 2 token where role information is provided
-     * within another SAML attribute
-     */
-    @org.junit.Test
-    public void validateSAML1TokenDifferentRoleURI() throws Exception {
-        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
-        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setRoleAttributeName("http://schemas.mycompany.com/claims/role");
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("CUSTOMROLEURI");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles().size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    /**
-     * Validate SAML 2 token which includes role attribute
-     * but RoleURI is not configured
-     */
-    @org.junit.Test
-    public void validateSAML2TokenRoleURINotConfigured() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        ((FederationProtocol)config.getProtocol()).setRoleURI(null);
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", null, wfRes.getRoles());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-    }
-    
-    /**
-     * Validate SAML 1.1 token which includes the role attribute with 2 values
-     * Roles are encoded as a multi-value saml attribute
-     */
-    @org.junit.Test
-    public void validateSAML1Token() throws Exception {
-        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
-        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    /**
-     * Validate SAML 1.1 token which includes the role attribute with 2 values
-     * Roles are encoded as a multi-value saml attribute
-     * Token embedded in RSTR 2005/02 - WS Federation 1.0
-     */
-    @org.junit.Test
-    public void validateSAML1TokenWSFed10() throws Exception {
-        SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
-        callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_2005_02_MSG);
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-    }
-    
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * Roles are encoded as a multiple saml attributes with the same name
-     */
-    @org.junit.Test
-    public void validateSAML2TokenRoleMultiAttributes() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setMultiValueType(MultiValue.MULTI_ATTR);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * Roles are encoded as a single saml attribute with encoded value
-     */
-    @org.junit.Test
-    public void validateSAML2TokenRoleEncodedValue() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        callbackHandler.setMultiValueType(MultiValue.ENC_VALUE);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        FederationProtocol fp = (FederationProtocol)config.getProtocol();
-        fp.setRoleDelimiter(",");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * The configured subject of the trusted issuer doesn't match with
-     * the issuer of the SAML token
-     * 
-     * Ignored because PeerTrust ignores subject attribute
-     */
-    @org.junit.Test
-    @org.junit.Ignore
-    public void validateSAML2TokenUntrustedIssuer() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        // Load and update the config to enforce an error
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        config.getTrustedIssuers().get(0).setSubject("wrong-issuer-name");        
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            Assert.fail("Processing must fail because of untrusted issuer configured");
-        } catch (ProcessingException ex) {
-            if (!TYPE.ISSUER_NOT_TRUSTED.equals(ex.getType())) {
-                fail("Expected ProcessingException with ISSUER_NOT_TRUSTED type");
-            }
-        }
-    }
-
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * The configured subject of the trusted issuer doesn't match with
-     * the issuer of the SAML token
-     */
-    @org.junit.Test
-    public void validateUnsignedSAML2Token() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", false);
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        // Load and update the config to enforce an error
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");       
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            Assert.fail("Processing must fail because of missing signature");
-        } catch (ProcessingException ex) {
-            if (!TYPE.TOKEN_NO_SIGNATURE.equals(ex.getType())) {
-                fail("Expected ProcessingException with TOKEN_NO_SIGNATURE type");
-            }
-        }
-    }
-    
-    /**
-     * Validate SAML 2 token twice which causes an exception
-     * due to replay attack
-     */
-    @org.junit.Test
-    public void testReplayAttack() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        
-        wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            fail("Failure expected on a replay attack");
-        } catch (ProcessingException ex) {
-            if (!TYPE.TOKEN_REPLAY.equals(ex.getType())) {
-                fail("Expected ProcessingException with TOKEN_REPLAY type");
-            }
-        }
-    }
-    
-    
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * The configured subject of the trusted issuer doesn't match with
-     * the issuer of the SAML token
-     */
-    @org.junit.Test
-    public void validateSAML2TokenSeveralCertStore() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        // Load and update the config to enforce an error
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-    }
-
-    /**
-     * Validate SAML 2 token which includes the role attribute with 2 values
-     * The configured subject of the trusted issuer doesn't match with
-     * the issuer of the SAML token
-     */
-    @org.junit.Test
-    public void validateSAML2TokenSeveralCertStoreTrustedIssuer() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        // Load and update the config to enforce an error
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT3");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-    }
-    
-    /**
-     * Validate SAML 2 token which is expired
-     */
-    @org.junit.Test
-    public void validateSAML2TokenExpired() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        DateTime currentTime = new DateTime();
-        currentTime = currentTime.minusSeconds(60);
-        cp.setNotAfter(currentTime);
-        currentTime = new DateTime();
-        currentTime = currentTime.minusSeconds(300);
-        cp.setNotBefore(currentTime);
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            fail("Failure expected on expired SAML token");
-        } catch (ProcessingException ex) {
-            if (!TYPE.TOKEN_EXPIRED.equals(ex.getType())) {
-                fail("Expected ProcessingException with TOKEN_EXPIRED type");
-            }
-        }
-    }
-    
-    /**
-     * Validate SAML 2 token which is not yet valid (in 30 seconds)
-     * but within the maximum clock skew range (60 seconds)
-     */
-    @org.junit.Test
-    public void validateSAML2TokenClockSkewRange() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        DateTime currentTime = new DateTime();
-        currentTime = currentTime.plusSeconds(300);
-        cp.setNotAfter(currentTime);
-        currentTime = new DateTime();
-        currentTime = currentTime.plusSeconds(30);
-        cp.setNotBefore(currentTime);
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
-        config.setMaximumClockSkew(BigInteger.valueOf(60));
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-    }
-
-    /**
-     * "Validate" SAML 2 token with a custom token validator
-     * If a validator is configured it precedes the SAMLTokenValidator as part of Fediz
-     */
-    @org.junit.Test
-    public void validateSAML2TokenCustomValidator() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("CUSTTOK");
-        FederationProtocol fp = (FederationProtocol)config.getProtocol();
-        List<TokenValidator> validators = fp.getTokenValidators();
-        Assert.assertEquals("Two validators must be found", 2, validators.size());
-        Assert.assertEquals("First validator must be custom validator",
-                            CustomValidator.class.getName(), validators.get(0).getClass().getName());
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-    }
-
-    /**
-     * "Validate" SAML 2 token with a custom token validator
-     * If a validator is configured it precedes the SAMLTokenValidator as part of Fediz
-     */
-    @org.junit.Test
-    public void validateSAML2TokenMaxClockSkewNotDefined() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = getFederationConfigurator().getFedizContext("NOCLOCKSKEW");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-    }
-    
-    /**
-     * Validate an encrypted SAML 2 token which includes the role attribute with 2 values
-     * Roles are encoded as a multi-value saml attribute
-     */
-    @org.junit.Test
-    public void validateEncryptedSAML2Token() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = encryptAndSignToken(assertion);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = 
-            getFederationConfigurator().getFedizContext("ROOT_DECRYPTION");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, config);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        assertClaims(wfRes.getClaims(), callbackHandler.getRoleAttributeName());
-    }
-    
-    /**
-     * Validate a HolderOfKey SAML 2 token
-     */
-    @org.junit.Test
-    public void validateHOKSAML2Token() throws Exception {
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-        
-        Crypto clientCrypto = CryptoFactory.getInstance("client-crypto.properties");
-        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
-        cryptoType.setAlias("myclientkey");
-        X509Certificate[] certs = clientCrypto.getX509Certificates(cryptoType);
-        callbackHandler.setCerts(certs);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        WSPasswordCallback[] cb = {
-            new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE)
-        };
-        cbPasswordHandler.handle(cb);
-        String password = cb[0].getPassword();
-
-        assertion.signAssertion("mystskey", password, crypto, false);
-
-        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
-        Element token = assertion.toDOM(doc);
-
-        Element e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
-                                                        FederationConstants.WS_TRUST_13_NS);
-        if (e == null) {
-            e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
-                                                    FederationConstants.WS_TRUST_2005_02_NS);
-        }
-        e.appendChild(token);
-                               
-        String rstr = DOM2Writer.nodeToString(doc);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-        
-        configurator = null;
-        FedizContext config = 
-            getFederationConfigurator().getFedizContext("ROOT_DECRYPTION");
-        
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        try {
-            wfProc.processRequest(wfReq, config);
-            fail("Failure expected on missing client certs");
-        } catch (ProcessingException ex) {
-            // expected
-        }
-        
-        // Now set client certs
-        wfReq.setCerts(certs);      
-        wfProc.processRequest(wfReq, config);
-    }
-    
-    @org.junit.Test
-    public void validateSAML2TokenWithConfigCreatedWithAPI() throws Exception {
-        
-        ContextConfig config = new ContextConfig();
-        
-        config.setName("whatever");
-
-        // Configure certificate store
-        CertificateStores certStores = new CertificateStores();
-        TrustManagersType tm0 = new TrustManagersType();       
-        KeyStoreType ks0 = new KeyStoreType();
-        ks0.setType("JKS");
-        ks0.setPassword("storepass");
-        ks0.setFile("ststrust.jks");
-        tm0.setKeyStore(ks0);
-        certStores.getTrustManager().add(tm0);
-        config.setCertificateStores(certStores);
-        
-        // Configure trusted IDP
-        TrustedIssuers trustedIssuers = new TrustedIssuers();
-        TrustedIssuerType ti0 = new TrustedIssuerType();
-        ti0.setCertificateValidation(ValidationType.CHAIN_TRUST);
-        ti0.setName("FedizSTSIssuer");
-        ti0.setSubject(".*CN=www.sts.com.*");
-        trustedIssuers.getIssuer().add(ti0);
-        config.setTrustedIssuers(trustedIssuers);
-
-        FederationProtocolType protocol = new FederationProtocolType();
-        config.setProtocol(protocol);
-
-        AudienceUris audienceUris = new AudienceUris();
-        audienceUris.getAudienceItem().add("https://localhost/fedizhelloworld");
-        config.setAudienceUris(audienceUris);
-
-        protocol.setRoleURI("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role");
-
-        FedizContext fedContext = new FedizContext(config);
-        fedContext.init();
-        
-        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
-        callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
-        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
-        callbackHandler.setIssuer(TEST_RSTR_ISSUER);
-        callbackHandler.setSubjectName(TEST_USER);
-        ConditionsBean cp = new ConditionsBean();
-        AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
-        audienceRestriction.getAudienceURIs().add(TEST_AUDIENCE);
-        cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
-        callbackHandler.setConditions(cp);
-
-        SAMLCallback samlCallback = new SAMLCallback();
-        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
-        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
-        
-        String rstr = createSamlToken(assertion, "mystskey", true, STSUtil.SAMPLE_RSTR_MSG);
-        
-        FedizRequest wfReq = new FedizRequest();
-        wfReq.setAction(FederationConstants.ACTION_SIGNIN);
-        wfReq.setResponseToken(rstr);
-                
-        FedizProcessor wfProc = new FederationProcessorImpl();
-        FedizResponse wfRes = wfProc.processRequest(wfReq, fedContext);
-        
-        Assert.assertEquals("Principal name wrong", TEST_USER,
-                            wfRes.getUsername());
-        Assert.assertEquals("Issuer wrong", TEST_RSTR_ISSUER, wfRes.getIssuer());
-        Assert.assertEquals("Two roles must be found", 2, wfRes.getRoles()
-                            .size());
-        Assert.assertEquals("Audience wrong", TEST_AUDIENCE, wfRes.getAudience());
-        
-        fedContext.close();
-
-    }
-    
-    
-    private String encryptAndSignToken(
-        SamlAssertionWrapper assertion
-    ) throws Exception {
-        
-        WSPasswordCallback[] cb = {
-            new WSPasswordCallback("mystskey", WSPasswordCallback.SIGNATURE)
-        };
-        cbPasswordHandler.handle(cb);
-        String password = cb[0].getPassword();
-
-        assertion.signAssertion("mystskey", password, crypto, false);
-        
-        Document doc = STSUtil.toSOAPPart(STSUtil.SAMPLE_RSTR_COLL_MSG);
-        Element token = assertion.toDOM(doc);
-
-        Element e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
-                                                        FederationConstants.WS_TRUST_13_NS);
-        if (e == null) {
-            e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
-                                                    FederationConstants.WS_TRUST_2005_02_NS);
-        }
-        e.appendChild(token);
-        
-        WSSecEncrypt builder = new WSSecEncrypt();
-        builder.setUserInfo("mystskey");
-        
-        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
-        builder.setSymmetricEncAlgorithm(WSConstants.AES_128);
-        builder.setKeyEncAlgo(WSConstants.KEYTRANSPORT_RSA15);
-        builder.setEmbedEncryptedKey(true);
-        
-        WSEncryptionPart encryptionPart = new WSEncryptionPart(assertion.getId(), "Element");
-        encryptionPart.setElement(token);
-        
-        Crypto encrCrypto = CryptoFactory.getInstance("signature.properties");
-        builder.prepare(token.getOwnerDocument(), encrCrypto);
-        builder.encryptForRef(null, Collections.singletonList(encryptionPart));
-        
-        // return doc.getDocumentElement();
-        return DOM2Writer.nodeToString(doc);
-    }
-    
-    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign)
-        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
-        return createSamlToken(assertion, alias, sign, STSUtil.SAMPLE_RSTR_COLL_MSG);
-    }
-    
-    private String createSamlToken(SamlAssertionWrapper assertion, String alias, boolean sign, String rstr)
-        throws IOException, UnsupportedCallbackException, WSSecurityException, Exception {
-        WSPasswordCallback[] cb = {
-            new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE)
-        };
-        cbPasswordHandler.handle(cb);
-        String password = cb[0].getPassword();
-
-        if (sign) {
-            assertion.signAssertion(alias, password, crypto, false);
-        }
-        Document doc = STSUtil.toSOAPPart(rstr);
-        Element token = assertion.toDOM(doc);
-
-        Element e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
-                                                        FederationConstants.WS_TRUST_13_NS);
-        if (e == null) {
-            e = FederationProcessorTest.findElement(doc, "RequestedSecurityToken",
-                                                    FederationConstants.WS_TRUST_2005_02_NS);
-        }
-        e.appendChild(token);
-        return DOM2Writer.nodeToString(doc);
-    }
-    
-
-    
-    
-    /**
-     * Returns the first element that matches <code>name</code> and
-     * <code>namespace</code>. <p/> This is a replacement for a XPath lookup
-     * <code>//name</code> with the given namespace. It's somewhat faster than
-     * XPath, and we do not deal with prefixes, just with the real namespace URI
-     * 
-     * @param startNode Where to start the search
-     * @param name Local name of the element
-     * @param namespace Namespace URI of the element
-     * @return The found element or <code>null</code>
-     */
-    public static Element findElement(Node startNode, String name, String namespace) {
-        //
-        // Replace the formerly recursive implementation with a depth-first-loop
-        // lookup
-        //
-        if (startNode == null) {
-            return null;
-        }
-        Node startParent = startNode.getParentNode();
-        Node processedNode = null;
-
-        while (startNode != null) {
-            // start node processing at this point
-            if (startNode.getNodeType() == Node.ELEMENT_NODE
-                && startNode.getLocalName().equals(name)) {
-                String ns = startNode.getNamespaceURI();
-                if (ns != null && ns.equals(namespace)) {
-                    return (Element)startNode;
-                }
-
-                if ((namespace == null || namespace.length() == 0)
-                    && (ns == null || ns.length() == 0)) {
-                    return (Element)startNode;
-                }
-            }
-            processedNode = startNode;
-            startNode = startNode.getFirstChild();
-
-            // no child, this node is done.
-            if (startNode == null) {
-                // close node processing, get sibling
-                startNode = processedNode.getNextSibling();
-            }
-            // no more siblings, get parent, all children
-            // of parent are processed.
-            while (startNode == null) {
-                processedNode = processedNode.getParentNode();
-                if (processedNode == startParent) {
-                    return null;
-                }
-                // close parent node processing (processed node now)
-                startNode = processedNode.getNextSibling();
-            }
-        }
-        return null;
-    }
-
-    private void assertClaims(List<Claim> claims, String roleClaimType) {
-        for (Claim c : claims) {
-            Assert.assertTrue("Invalid ClaimType URI: " + c.getClaimType(), 
-                              c.getClaimType().equals(roleClaimType)
-                              || c.getClaimType().equals(ClaimTypes.COUNTRY)
-                              || c.getClaimType().equals(AbstractSAMLCallbackHandler.CLAIM_TYPE_LANGUAGE)
-                              );
-        }
-    }
-    
-
-}