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/06/09 17:31:18 UTC
git commit: FEDIZ-84 - Support wreq parameter in SP/IdP
Repository: cxf-fediz
Updated Branches:
refs/heads/master 1670ad069 -> 336a959fd
FEDIZ-84 - Support wreq parameter in SP/IdP
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/336a959f
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/336a959f
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/336a959f
Branch: refs/heads/master
Commit: 336a959fd53101cb6c4b8d7fa3ecd2b32312a300
Parents: 1670ad0
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Jun 9 16:30:52 2014 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Jun 9 16:30:52 2014 +0100
----------------------------------------------------------------------
.../cxf/fediz/core/FederationProcessorImpl.java | 29 +-
.../fediz/core/config/FederationProtocol.java | 176 +++-------
.../apache/cxf/fediz/core/spi/WReqCallback.java | 40 +++
.../src/main/resources/schemas/FedizConfig.xsd | 3 +-
.../fediz/core/config/CallbackHandlerTest.java | 25 +-
.../core/config/FedizConfigurationTest.java | 1 -
.../config/FedizConfigurationWriterTest.java | 15 +-
.../fediz/core/config/TestCallbackHandler.java | 8 +
.../service/idp/beans/STSClientAction.java | 38 ++-
.../WEB-INF/federation-validate-request.xml | 1 +
systests/tomcat7/pom.xml | 4 +-
.../BadWReqCallbackHandler.java | 48 +++
.../cxf/fediz/integrationtests/BadWReqTest.java | 313 ++++++++++++++++++
.../integrationtests/TestCallbackHandler.java | 48 +++
.../cxf/fediz/integrationtests/WReqTest.java | 329 +++++++++++++++++++
.../test/resources/fediz_config_bad_wreq.xml | 39 +++
.../src/test/resources/fediz_config_wreq.xml | 39 +++
17 files changed, 1019 insertions(+), 137 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
index 05271c7..d181b2f 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/FederationProcessorImpl.java
@@ -39,7 +39,6 @@ import javax.servlet.http.HttpServletRequest;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-
import org.apache.cxf.fediz.core.config.FederationContext;
import org.apache.cxf.fediz.core.config.FederationProtocol;
import org.apache.cxf.fediz.core.config.KeyManager;
@@ -52,8 +51,8 @@ import org.apache.cxf.fediz.core.spi.IDPCallback;
import org.apache.cxf.fediz.core.spi.RealmCallback;
import org.apache.cxf.fediz.core.spi.SignInQueryCallback;
import org.apache.cxf.fediz.core.spi.WAuthCallback;
+import org.apache.cxf.fediz.core.spi.WReqCallback;
import org.apache.cxf.fediz.core.util.DOMUtils;
-
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.dom.WSConstants;
@@ -363,6 +362,9 @@ public class FederationProcessorImpl implements FederationProcessor {
String wAuth = resolveAuthenticationType(request, config);
LOG.info("WAuth: " + wAuth);
+ String wReq = resolveRequest(request, config);
+ LOG.info("WReq: " + wReq);
+
String homeRealm = resolveHomeRealm(request, config);
LOG.info("HomeRealm: " + homeRealm);
@@ -408,6 +410,12 @@ public class FederationProcessorImpl implements FederationProcessor {
.append(URLEncoder.encode(wAuth, "UTF-8"));
}
+ // add tokenRequest parameter wreq if set
+ if (wReq != null && wReq.length() > 0) {
+ sb.append('&').append(FederationConstants.PARAM_REQUEST).append('=')
+ .append(URLEncoder.encode(wReq, "UTF-8"));
+ }
+
// add home realm parameter whr if set
if (homeRealm != null && homeRealm.length() > 0) {
sb.append('&').append(FederationConstants.PARAM_HOME_REALM).append('=')
@@ -560,6 +568,23 @@ public class FederationProcessorImpl implements FederationProcessor {
}
return wAuth;
}
+
+ private String resolveRequest(HttpServletRequest request, FederationContext config)
+ throws IOException, UnsupportedCallbackException {
+ Object wReqObj = ((FederationProtocol)config.getProtocol()).getRequest();
+ String wReq = null;
+ if (wReqObj != null) {
+ if (wReqObj instanceof String) {
+ wReq = (String)wReqObj;
+ } else if (wReqObj instanceof CallbackHandler) {
+ CallbackHandler wauthCB = (CallbackHandler)wReqObj;
+ WReqCallback callback = new WReqCallback(request);
+ wauthCB.handle(new Callback[] {callback});
+ wReq = callback.getWreq();
+ }
+ }
+ return wReq;
+ }
private String resolveIssuer(HttpServletRequest request, FederationContext config) throws IOException,
UnsupportedCallbackException {
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationProtocol.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationProtocol.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationProtocol.java
index 86bff41..e63b5dc 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationProtocol.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FederationProtocol.java
@@ -40,6 +40,7 @@ public class FederationProtocol extends Protocol {
private static final Logger LOG = LoggerFactory.getLogger(FederationProtocol.class);
+ private Object request;
private Object authenticationType;
private Object issuer;
private Object homeRealm;
@@ -99,26 +100,7 @@ public class FederationProtocol extends Protocol {
return this.realm;
}
CallbackType cbt = getFederationProtocol().getRealm();
- if (cbt == null) {
- return null;
- }
- if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
- this.realm = new String(cbt.getValue());
- } else if (cbt.getType().equals(ArgumentType.CLASS)) {
- try {
- if (this.classloader == null) {
- this.realm = ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
- } else {
- this.realm = this.classloader.loadClass(cbt.getValue()).newInstance();
- }
- } catch (Exception e) {
- LOG.error("Failed to create instance of " + cbt.getValue(), e);
- throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
- }
- } else {
- LOG.error("Only String and Class are supported for 'Realm'");
- throw new IllegalStateException("Only String and Class are supported for 'Realm'");
- }
+ this.realm = loadCallbackType(cbt, "Realm");
return this.realm;
}
@@ -167,26 +149,7 @@ public class FederationProtocol extends Protocol {
return this.authenticationType;
}
CallbackType cbt = getFederationProtocol().getAuthenticationType();
- if (cbt == null) {
- return null;
- }
- if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
- this.authenticationType = new String(cbt.getValue());
- } else if (cbt.getType().equals(ArgumentType.CLASS)) {
- try {
- if (this.classloader == null) {
- this.authenticationType = ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
- } else {
- this.authenticationType = this.classloader.loadClass(cbt.getValue()).newInstance();
- }
- } catch (Exception e) {
- LOG.error("Failed to create instance of " + cbt.getValue(), e);
- throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
- }
- } else {
- LOG.error("Only String and Class are supported for 'AuthenticationType'");
- throw new IllegalStateException("Only String and Class are supported for AuthenticationType");
- }
+ this.authenticationType = loadCallbackType(cbt, "AuthenticationType");
return this.authenticationType;
}
@@ -207,26 +170,7 @@ public class FederationProtocol extends Protocol {
return this.homeRealm;
}
CallbackType cbt = getFederationProtocol().getHomeRealm();
- if (cbt == null) {
- return null;
- }
- if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
- this.homeRealm = new String(cbt.getValue());
- } else if (cbt.getType().equals(ArgumentType.CLASS)) {
- try {
- if (this.classloader == null) {
- this.homeRealm = ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
- } else {
- this.homeRealm = this.classloader.loadClass(cbt.getValue()).newInstance();
- }
- } catch (Exception e) {
- LOG.error("Failed to create instance of " + cbt.getValue(), e);
- throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
- }
- } else {
- LOG.error("Only String and Class are supported for 'HomeRealm'");
- throw new IllegalStateException("Only String and Class are supported for 'HomeRealm'");
- }
+ this.homeRealm = loadCallbackType(cbt, "HomeRealm");
return this.homeRealm;
}
@@ -247,23 +191,7 @@ public class FederationProtocol extends Protocol {
return this.issuer;
}
CallbackType cbt = getFederationProtocol().getIssuer();
- if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
- this.issuer = new String(cbt.getValue());
- } else if (cbt.getType().equals(ArgumentType.CLASS)) {
- try {
- if (this.classloader == null) {
- this.issuer = ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
- } else {
- this.issuer = this.classloader.loadClass(cbt.getValue()).newInstance();
- }
- } catch (Exception e) {
- LOG.error("Failed to create instance of " + cbt.getValue(), e);
- throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
- }
- } else {
- LOG.error("Only String and Class are supported for 'Issuer'");
- throw new IllegalStateException("Only String and Class are supported for 'Issuer'");
- }
+ this.issuer = loadCallbackType(cbt, "Issuer");
return this.issuer;
}
@@ -284,26 +212,7 @@ public class FederationProtocol extends Protocol {
return this.freshness;
}
CallbackType cbt = getFederationProtocol().getFreshness();
- if (cbt == null) {
- return null;
- }
- if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
- this.freshness = new String(cbt.getValue());
- } else if (cbt.getType().equals(ArgumentType.CLASS)) {
- try {
- if (this.classloader == null) {
- this.freshness = ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
- } else {
- this.freshness = this.classloader.loadClass(cbt.getValue()).newInstance();
- }
- } catch (Exception e) {
- LOG.error("Failed to create instance of " + cbt.getValue(), e);
- throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
- }
- } else {
- LOG.error("Only String and Class are supported for 'Freshness'");
- throw new IllegalStateException("Only String and Class are supported for 'Freshness'");
- }
+ this.freshness = loadCallbackType(cbt, "Freshness");
return this.freshness;
}
@@ -324,26 +233,7 @@ public class FederationProtocol extends Protocol {
return this.signInQuery;
}
CallbackType cbt = getFederationProtocol().getSignInQuery();
- if (cbt == null) {
- return null;
- }
- if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
- this.signInQuery = new String(cbt.getValue());
- } else if (cbt.getType().equals(ArgumentType.CLASS)) {
- try {
- if (this.classloader == null) {
- this.signInQuery = ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
- } else {
- this.signInQuery = this.classloader.loadClass(cbt.getValue()).newInstance();
- }
- } catch (Exception e) {
- LOG.error("Failed to create instance of " + cbt.getValue(), e);
- throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
- }
- } else {
- LOG.error("Only String and Class are supported for 'SignInQuery'");
- throw new IllegalStateException("Only String and Class are supported for 'SignInQuery'");
- }
+ this.signInQuery = loadCallbackType(cbt, "SignInQuery");
return this.signInQuery;
}
@@ -358,6 +248,27 @@ public class FederationProtocol extends Protocol {
+ "java.lang.String or javax.security.auth.callback.CallbackHandler.");
}
}
+
+ public Object getRequest() {
+ if (this.request != null) {
+ return this.request;
+ }
+ CallbackType cbt = getFederationProtocol().getRequest();
+ this.request = loadCallbackType(cbt, "Request");
+ return this.request;
+ }
+
+ public void setRequest(Object value) {
+ final boolean isString = value instanceof String;
+ final boolean isCallbackHandler = value instanceof CallbackHandler;
+ if (isString || isCallbackHandler) {
+ this.request = value;
+ } else {
+ LOG.error("Unsupported 'Request' object");
+ throw new IllegalArgumentException("Unsupported 'Request' object. Type must be "
+ + "java.lang.String or javax.security.auth.callback.CallbackHandler.");
+ }
+ }
public String getReply() {
return getFederationProtocol().getReply();
@@ -367,14 +278,6 @@ public class FederationProtocol extends Protocol {
getFederationProtocol().setReply(value);
}
- public String getRequest() {
- return getFederationProtocol().getRequest();
- }
-
- public void setRequest(String value) {
- getFederationProtocol().setRequest(value);
- }
-
public List<Claim> getClaimTypesRequested() {
ClaimTypesRequested claimsRequested = getFederationProtocol().getClaimTypesRequested();
List<Claim> claims = new ArrayList<Claim>();
@@ -411,5 +314,28 @@ public class FederationProtocol extends Protocol {
public void setClassloader(ClassLoader classloader) {
this.classloader = classloader;
}
+
+ private Object loadCallbackType(CallbackType cbt, String name) {
+ if (cbt == null) {
+ return null;
+ }
+ if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) {
+ return new String(cbt.getValue());
+ } else if (cbt.getType().equals(ArgumentType.CLASS)) {
+ try {
+ if (this.classloader == null) {
+ return ClassLoaderUtils.loadClass(cbt.getValue(), this.getClass()).newInstance();
+ } else {
+ return this.classloader.loadClass(cbt.getValue()).newInstance();
+ }
+ } catch (Exception e) {
+ LOG.error("Failed to create instance of " + cbt.getValue(), e);
+ throw new IllegalStateException("Failed to create instance of " + cbt.getValue());
+ }
+ } else {
+ LOG.error("Only String and Class are supported for '" + name + "'");
+ throw new IllegalStateException("Only String and Class are supported for '" + name + "'");
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/main/java/org/apache/cxf/fediz/core/spi/WReqCallback.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/spi/WReqCallback.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/spi/WReqCallback.java
new file mode 100644
index 0000000..e5752b0
--- /dev/null
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/spi/WReqCallback.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.fediz.core.spi;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class WReqCallback extends AbstractServletCallback {
+
+ private String wreq;
+
+ public WReqCallback(HttpServletRequest request) {
+ super(request);
+ }
+
+ public String getWreq() {
+ return wreq;
+ }
+
+ public void setWreq(String wreq) {
+ this.wreq = wreq;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/main/resources/schemas/FedizConfig.xsd
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/resources/schemas/FedizConfig.xsd b/plugins/core/src/main/resources/schemas/FedizConfig.xsd
index a563085..c9e670c 100644
--- a/plugins/core/src/main/resources/schemas/FedizConfig.xsd
+++ b/plugins/core/src/main/resources/schemas/FedizConfig.xsd
@@ -132,6 +132,7 @@
<xs:element name="issuer" type="CallbackType" />
<xs:element name="homeRealm" type="CallbackType" />
<xs:element name="authenticationType" type="CallbackType" />
+ <xs:element name="request" type="CallbackType" />
<xs:element name="freshness" type="CallbackType" />
<xs:element name="signInQuery" type="CallbackType" />
@@ -144,8 +145,6 @@
<xs:element name="reply" type="xs:string" />
- <xs:element name="request" type="xs:string" />
-
<xs:element name="claimTypesRequested">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/CallbackHandlerTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/CallbackHandlerTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/CallbackHandlerTest.java
index 57c6161..05b6e0e 100644
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/CallbackHandlerTest.java
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/CallbackHandlerTest.java
@@ -49,6 +49,7 @@ import org.apache.cxf.fediz.core.spi.IDPCallback;
import org.apache.cxf.fediz.core.spi.RealmCallback;
import org.apache.cxf.fediz.core.spi.SignInQueryCallback;
import org.apache.cxf.fediz.core.spi.WAuthCallback;
+import org.apache.cxf.fediz.core.spi.WReqCallback;
import org.junit.AfterClass;
import org.junit.Assert;
@@ -131,7 +132,6 @@ public class CallbackHandlerTest {
protocol.setRealm(freshness);
protocol.setReply(REPLY);
- protocol.setRequest("REQUEST");
protocol.setVersion(PROTOCOL_VERSION);
return rootConfig;
@@ -157,6 +157,11 @@ public class CallbackHandlerTest {
authType.setValue(TestCallbackHandler.TEST_WAUTH);
protocol.setAuthenticationType(authType);
+ CallbackType tokenRequest = new CallbackType();
+ tokenRequest.setType(ArgumentType.STRING);
+ tokenRequest.setValue(TestCallbackHandler.TEST_WREQ);
+ protocol.setRequest(tokenRequest);
+
CallbackType signInQueryType = new CallbackType();
signInQueryType.setType(ArgumentType.STRING);
signInQueryType.setValue(TEST_SIGNIN_QUERY);
@@ -185,6 +190,11 @@ public class CallbackHandlerTest {
authType.setValue(CALLBACKHANDLER_CLASS);
protocol.setAuthenticationType(authType);
+ CallbackType tokenRequest = new CallbackType();
+ tokenRequest.setType(ArgumentType.CLASS);
+ tokenRequest.setValue(CALLBACKHANDLER_CLASS);
+ protocol.setRequest(tokenRequest);
+
CallbackType signInQueryType = new CallbackType();
signInQueryType.setType(ArgumentType.CLASS);
signInQueryType.setValue(CALLBACKHANDLER_CLASS);
@@ -230,6 +240,14 @@ public class CallbackHandlerTest {
String wAuth = callbackWA.getWauth();
Assert.assertEquals(TestCallbackHandler.TEST_WAUTH, wAuth);
+ Object wReqObj = fp.getRequest();
+ Assert.assertTrue(wReqObj instanceof CallbackHandler);
+ CallbackHandler wreqCB = (CallbackHandler)wReqObj;
+ WReqCallback callbackReq = new WReqCallback(null);
+ wreqCB.handle(new Callback[] {callbackReq});
+ String wReq = callbackReq.getWreq();
+ Assert.assertEquals(TestCallbackHandler.TEST_WREQ, wReq);
+
Object homeRealmObj = fp.getHomeRealm();
Assert.assertTrue(homeRealmObj instanceof CallbackHandler);
CallbackHandler hrCB = (CallbackHandler)homeRealmObj;
@@ -284,6 +302,11 @@ public class CallbackHandlerTest {
String wAuth = (String)wAuthObj;
Assert.assertEquals(TestCallbackHandler.TEST_WAUTH, wAuth);
+ Object wReqObj = fp.getRequest();
+ Assert.assertTrue(wReqObj instanceof String);
+ String wReq = (String)wReqObj;
+ Assert.assertEquals(TestCallbackHandler.TEST_WREQ, wReq);
+
Object homeRealmObj = fp.getHomeRealm();
Assert.assertTrue(homeRealmObj instanceof String);
String hr = (String)homeRealmObj;
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationTest.java
index 69e7462..eb0bb7e 100644
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationTest.java
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationTest.java
@@ -197,7 +197,6 @@ public class FedizConfigurationTest {
protocol.setRealm(realm);
protocol.setReply(REPLY);
- protocol.setRequest("REQUEST");
protocol.setVersion(PROTOCOL_VERSION);
CallbackType issuer = new CallbackType();
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationWriterTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationWriterTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationWriterTest.java
index 1fe0b22..e68c0e9 100644
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationWriterTest.java
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/FedizConfigurationWriterTest.java
@@ -82,6 +82,11 @@ public class FedizConfigurationWriterTest {
private static final String CONFIG_FILE = "./target/fediz_test_config.xml";
+ private static final String TEST_WREQ =
+ "<RequestSecurityToken xmlns=\"http://docs.oasis-open.org/ws-sx/ws-trust/200512\">"
+ + "<t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</t:TokenType>"
+ + "</RequestSecurityToken>";
+
@AfterClass
@@ -137,12 +142,17 @@ public class FedizConfigurationWriterTest {
CallbackType authType = new CallbackType();
authType.setType(ArgumentType.STRING);
authType.setValue(AUTH_TYPE_VALUE);
+
+ CallbackType tokenRequest = new CallbackType();
+ tokenRequest.setType(ArgumentType.STRING);
+ tokenRequest.setValue(TEST_WREQ);
AudienceUris audienceUris = new AudienceUris();
audienceUris.getAudienceItem().add(AUDIENCE_URI_1);
config.setAudienceUris(audienceUris);
protocol.setAuthenticationType(authType);
+ protocol.setRequest(tokenRequest);
protocol.setRoleDelimiter(ROLE_DELIMITER);
protocol.setRoleURI(ROLE_URI);
@@ -172,7 +182,6 @@ public class FedizConfigurationWriterTest {
protocol.setRealm(realm);
protocol.setReply(REPLY);
- protocol.setRequest("REQUEST");
protocol.setVersion(PROTOCOL_VERSION);
CallbackType issuer = new CallbackType();
@@ -264,6 +273,10 @@ public class FedizConfigurationWriterTest {
Assert.assertTrue(auth instanceof String);
Assert.assertEquals((String)auth, AUTH_TYPE_VALUE);
+ Object wreq = fedProtocol.getRequest();
+ Assert.assertTrue(wreq instanceof String);
+ Assert.assertEquals((String)wreq, TEST_WREQ);
+
//Assert.assertEquals(ValidationMethod.CHAIN_TRUST, fedContext.getCertificateValidation());
List<String> audienceUris = fedContext.getAudienceUris();
Assert.assertEquals(1, audienceUris.size());
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/TestCallbackHandler.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/TestCallbackHandler.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/TestCallbackHandler.java
index f0cc71c..6f13a89 100644
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/TestCallbackHandler.java
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/config/TestCallbackHandler.java
@@ -33,6 +33,7 @@ import org.apache.cxf.fediz.core.spi.IDPCallback;
import org.apache.cxf.fediz.core.spi.RealmCallback;
import org.apache.cxf.fediz.core.spi.SignInQueryCallback;
import org.apache.cxf.fediz.core.spi.WAuthCallback;
+import org.apache.cxf.fediz.core.spi.WReqCallback;
public class TestCallbackHandler implements CallbackHandler {
@@ -41,6 +42,10 @@ public class TestCallbackHandler implements CallbackHandler {
static final String TEST_IDP = "http://rp.example.com/";
static final String TEST_WAUTH = "up";
static final String TEST_SIGNIN_QUERY = "pubid=myid";
+ static final String TEST_WREQ =
+ "<RequestSecurityToken xmlns=\"http://docs.oasis-open.org/ws-sx/ws-trust/200512\">"
+ + "<TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</TokenType>"
+ + "</RequestSecurityToken>";
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
@@ -53,6 +58,9 @@ public class TestCallbackHandler implements CallbackHandler {
} else if (callbacks[i] instanceof WAuthCallback) {
WAuthCallback callback = (WAuthCallback) callbacks[i];
callback.setWauth(TEST_WAUTH);
+ } else if (callbacks[i] instanceof WReqCallback) {
+ WReqCallback callback = (WReqCallback) callbacks[i];
+ callback.setWreq(TEST_WREQ);
} else if (callbacks[i] instanceof IDPCallback) {
IDPCallback callback = (IDPCallback) callbacks[i];
callback.setIssuerUrl(new URL(TEST_IDP));
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java
index 4439033..0ea2cd4 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java
@@ -20,6 +20,7 @@ package org.apache.cxf.fediz.service.idp.beans;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.X509Certificate;
@@ -39,6 +40,7 @@ import org.apache.cxf.BusFactory;
import org.apache.cxf.fediz.core.FederationConstants;
import org.apache.cxf.fediz.core.exception.ProcessingException;
import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
+import org.apache.cxf.fediz.core.util.DOMUtils;
import org.apache.cxf.fediz.service.idp.IdpSTSClient;
import org.apache.cxf.fediz.service.idp.domain.Application;
import org.apache.cxf.fediz.service.idp.domain.Idp;
@@ -197,7 +199,37 @@ public class STSClientAction {
throw new ProcessingException(TYPE.BAD_REQUEST);
}
- if (serviceConfig.getTokenType() != null && serviceConfig.getTokenType().length() > 0) {
+ // Parse wreq parameter - we only support parsing TokenType and KeyType for now
+ String wreq = (String)WebUtils.getAttributeFromFlowScope(context, FederationConstants.PARAM_REQUEST);
+ String stsTokenType = null;
+ String stsKeyType = keyType;
+ if (wreq != null) {
+ try {
+ Document wreqDoc = DOMUtils.readXml(new StringReader(wreq));
+ Element wreqElement = wreqDoc.getDocumentElement();
+ if (wreqElement != null && "RequestSecurityToken".equals(wreqElement.getLocalName())
+ && (STSUtils.WST_NS_05_12.equals(wreqElement.getNamespaceURI())
+ || HTTP_SCHEMAS_XMLSOAP_ORG_WS_2005_02_TRUST.equals(wreqElement.getNamespaceURI()))) {
+ Element tokenTypeElement =
+ DOMUtils.getFirstChildWithName(wreqElement, wreqElement.getNamespaceURI(), "TokenType");
+ if (tokenTypeElement != null) {
+ stsTokenType = tokenTypeElement.getTextContent();
+ }
+ Element keyTypeElement =
+ DOMUtils.getFirstChildWithName(wreqElement, wreqElement.getNamespaceURI(), "KeyType");
+ if (keyTypeElement != null) {
+ stsKeyType = keyTypeElement.getTextContent();
+ }
+ }
+ } catch (Exception e) {
+ LOG.warn("Error parsing 'wreq' parameter: " + e.getMessage());
+ throw new ProcessingException(TYPE.BAD_REQUEST);
+ }
+ }
+
+ if (stsTokenType != null) {
+ sts.setTokenType(stsTokenType);
+ } else if (serviceConfig.getTokenType() != null && serviceConfig.getTokenType().length() > 0) {
sts.setTokenType(serviceConfig.getTokenType());
} else {
sts.setTokenType(getTokenType());
@@ -209,8 +241,8 @@ public class STSClientAction {
LOG.debug("TokenType {} set for realm {}", sts.getTokenType(), wtrealm);
- sts.setKeyType(keyType);
- if (HTTP_DOCS_OASIS_OPEN_ORG_WS_SX_WS_TRUST_200512_PUBLICKEY.equals(keyType)) {
+ sts.setKeyType(stsKeyType);
+ if (HTTP_DOCS_OASIS_OPEN_ORG_WS_SX_WS_TRUST_200512_PUBLICKEY.equals(stsKeyType)) {
HttpServletRequest servletRequest = WebUtils.getHttpServletRequest(context);
if (servletRequest != null) {
X509Certificate certs[] =
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
----------------------------------------------------------------------
diff --git a/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml b/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
index 6f7d232..9c30318 100644
--- a/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
+++ b/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
@@ -31,6 +31,7 @@
<set name="flowScope.wfresh" value="requestParameters.wfresh" />
<set name="flowScope.whr" value="requestParameters.whr" />
<set name="flowScope.wresult" value="requestParameters.wresult" />
+ <set name="flowScope.wreq" value="requestParameters.wreq" />
<evaluate expression="requestScope.getString('wauth','default')"
result="flowScope.wauth" />
<set name="flowScope.idpConfig" value="config.getIDP(null)" />
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/systests/tomcat7/pom.xml
----------------------------------------------------------------------
diff --git a/systests/tomcat7/pom.xml b/systests/tomcat7/pom.xml
index d58f758..69e869e 100644
--- a/systests/tomcat7/pom.xml
+++ b/systests/tomcat7/pom.xml
@@ -102,14 +102,14 @@
<directory>src/test/resources</directory>
<filtering>true</filtering>
<includes>
- <include>**/fediz_config.xml</include>
+ <include>**/fediz_config*.xml</include>
</includes>
</testResource>
<testResource>
<directory>src/test/resources</directory>
<filtering>false</filtering>
<excludes>
- <exclude>**/fediz_config.xml</exclude>
+ <exclude>**/fediz_config*.xml</exclude>
</excludes>
</testResource>
</testResources>
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqCallbackHandler.java
----------------------------------------------------------------------
diff --git a/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqCallbackHandler.java b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqCallbackHandler.java
new file mode 100644
index 0000000..a35d286
--- /dev/null
+++ b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqCallbackHandler.java
@@ -0,0 +1,48 @@
+/**
+ * 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.integrationtests;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.cxf.fediz.core.spi.WReqCallback;
+
+public class BadWReqCallbackHandler implements CallbackHandler {
+
+ static final String TEST_WREQ =
+ "<RequestSecurityToken xmlns=\"http://docs.oasis-open.org/ws-sx/ws-trust/200512\">"
+ + "<TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV3.0</TokenType>"
+ + "</RequestSecurityToken>";
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof WReqCallback) {
+ WReqCallback callback = (WReqCallback) callbacks[i];
+ callback.setWreq(TEST_WREQ);
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqTest.java
----------------------------------------------------------------------
diff --git a/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqTest.java b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqTest.java
new file mode 100644
index 0000000..0c9d7fb
--- /dev/null
+++ b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/BadWReqTest.java
@@ -0,0 +1,313 @@
+/**
+ * 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.integrationtests;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.htmlparser.jericho.Element;
+import net.htmlparser.jericho.FormField;
+import net.htmlparser.jericho.FormFields;
+import net.htmlparser.jericho.HTMLElementName;
+import net.htmlparser.jericho.Source;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.cxf.fediz.tomcat.FederationAuthenticator;
+import org.apache.http.Consts;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.LaxRedirectStrategy;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+/**
+ * A test for sending a TokenType request to the IdP via the "wreq" parameter. This test sends
+ * a "bad" TokenType, and so a failure is expected.
+ */
+public class BadWReqTest {
+
+ static String idpHttpsPort;
+ static String rpHttpsPort;
+
+ private static Tomcat idpServer;
+ private static Tomcat rpServer;
+
+ @BeforeClass
+ public static void init() {
+ System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
+ System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
+ System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.springframework.webflow", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.springframework.security.web", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.cxf.fediz", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.cxf", "info");
+
+ idpHttpsPort = System.getProperty("idp.https.port");
+ Assert.assertNotNull("Property 'idp.https.port' null", idpHttpsPort);
+ rpHttpsPort = System.getProperty("rp.https.port");
+ Assert.assertNotNull("Property 'rp.https.port' null", rpHttpsPort);
+
+ initIdp();
+ initRp();
+ }
+
+ private static void initIdp() {
+ try {
+ idpServer = new Tomcat();
+ idpServer.setPort(0);
+ String currentDir = new File(".").getCanonicalPath();
+ idpServer.setBaseDir(currentDir + File.separator + "target");
+
+ idpServer.getHost().setAppBase("tomcat/idp/webapps");
+ idpServer.getHost().setAutoDeploy(true);
+ idpServer.getHost().setDeployOnStartup(true);
+
+ Connector httpsConnector = new Connector();
+ httpsConnector.setPort(Integer.parseInt(idpHttpsPort));
+ httpsConnector.setSecure(true);
+ httpsConnector.setScheme("https");
+ //httpsConnector.setAttribute("keyAlias", keyAlias);
+ httpsConnector.setAttribute("keystorePass", "tompass");
+ httpsConnector.setAttribute("keystoreFile", "test-classes/server.jks");
+ httpsConnector.setAttribute("truststorePass", "tompass");
+ httpsConnector.setAttribute("truststoreFile", "test-classes/server.jks");
+ httpsConnector.setAttribute("clientAuth", "want");
+ // httpsConnector.setAttribute("clientAuth", "false");
+ httpsConnector.setAttribute("sslProtocol", "TLS");
+ httpsConnector.setAttribute("SSLEnabled", true);
+
+ idpServer.getService().addConnector(httpsConnector);
+
+ idpServer.addWebapp("/fediz-idp-sts", "fediz-idp-sts");
+ idpServer.addWebapp("/fediz-idp", "fediz-idp");
+
+ idpServer.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void initRp() {
+ try {
+ rpServer = new Tomcat();
+ rpServer.setPort(0);
+ String currentDir = new File(".").getCanonicalPath();
+ rpServer.setBaseDir(currentDir + File.separator + "target");
+
+ rpServer.getHost().setAppBase("tomcat/rp/webapps");
+ rpServer.getHost().setAutoDeploy(true);
+ rpServer.getHost().setDeployOnStartup(true);
+
+ Connector httpsConnector = new Connector();
+ httpsConnector.setPort(Integer.parseInt(rpHttpsPort));
+ httpsConnector.setSecure(true);
+ httpsConnector.setScheme("https");
+ //httpsConnector.setAttribute("keyAlias", keyAlias);
+ httpsConnector.setAttribute("keystorePass", "tompass");
+ httpsConnector.setAttribute("keystoreFile", "test-classes/server.jks");
+ httpsConnector.setAttribute("truststorePass", "tompass");
+ httpsConnector.setAttribute("truststoreFile", "test-classes/server.jks");
+ // httpsConnector.setAttribute("clientAuth", "false");
+ httpsConnector.setAttribute("clientAuth", "want");
+ httpsConnector.setAttribute("sslProtocol", "TLS");
+ httpsConnector.setAttribute("SSLEnabled", true);
+
+ rpServer.getService().addConnector(httpsConnector);
+
+ //Context ctx =
+ Context cxt = rpServer.addWebapp("/fedizhelloworld", "simpleWebapp");
+ FederationAuthenticator fa = new FederationAuthenticator();
+ fa.setConfigFile(currentDir + File.separator + "target" + File.separator
+ + "test-classes" + File.separator + "fediz_config_bad_wreq.xml");
+ cxt.getPipeline().addValve(fa);
+
+
+ rpServer.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @AfterClass
+ public static void cleanup() {
+ try {
+ if (idpServer.getServer() != null
+ && idpServer.getServer().getState() != LifecycleState.DESTROYED) {
+ if (idpServer.getServer().getState() != LifecycleState.STOPPED) {
+ idpServer.stop();
+ }
+ idpServer.destroy();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ try {
+ if (rpServer.getServer() != null
+ && rpServer.getServer().getState() != LifecycleState.DESTROYED) {
+ if (rpServer.getServer().getState() != LifecycleState.STOPPED) {
+ rpServer.stop();
+ }
+ rpServer.destroy();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public String getIdpHttpsPort() {
+ return idpHttpsPort;
+ }
+
+ public String getRpHttpsPort() {
+ return rpHttpsPort;
+ }
+
+ public String getServletContextName() {
+ return "fedizhelloworld";
+ }
+
+ @org.junit.Test
+ public void testSAML1TokenViaWReq() throws Exception {
+ String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/secure/fedservlet";
+ String user = "alice";
+ String password = "ecila";
+ sendHttpGet(url, user, password);
+ }
+
+ private String sendHttpGet(String url, String user, String password) throws Exception {
+ return sendHttpGet(url, user, password, 500, 403);
+ }
+
+ private String sendHttpGet(String url, String user, String password, int returnCodeIDP, int returnCodeRP)
+ throws Exception {
+ DefaultHttpClient httpclient = new DefaultHttpClient();
+ try {
+ httpclient.getCredentialsProvider().setCredentials(
+ new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+ new UsernamePasswordCredentials(user, password));
+
+ KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream instream = new FileInputStream(new File("./target/test-classes/client.jks"));
+ try {
+ trustStore.load(instream, "clientpass".toCharArray());
+ } finally {
+ try {
+ instream.close();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
+ Scheme schIdp = new Scheme("https", Integer.parseInt(getIdpHttpsPort()), socketFactory);
+ httpclient.getConnectionManager().getSchemeRegistry().register(schIdp);
+ Scheme schRp = new Scheme("https", Integer.parseInt(getRpHttpsPort()), socketFactory);
+ httpclient.getConnectionManager().getSchemeRegistry().register(schRp);
+
+ HttpGet httpget = new HttpGet(url);
+
+ HttpResponse response = httpclient.execute(httpget);
+ HttpEntity entity = response.getEntity();
+
+ System.out.println(response.getStatusLine());
+ if (entity != null) {
+ System.out.println("Response content length: " + entity.getContentLength());
+ }
+ Assert.assertTrue("IDP HTTP Response code: " + response.getStatusLine().getStatusCode()
+ + " [Expected: " + returnCodeIDP + "]",
+ returnCodeIDP == response.getStatusLine().getStatusCode());
+
+ if (response.getStatusLine().getStatusCode() != 200) {
+ return null;
+ }
+
+ // Redirect to a POST is not supported without user interaction
+ // http://www.ietf.org/rfc/rfc2616.txt
+ // If the 301 status code is received in response to a request other
+ // than GET or HEAD, the user agent MUST NOT automatically redirect the
+ // request unless it can be confirmed by the user, since this might
+ // change the conditions under which the request was issued.
+
+ httpclient.setRedirectStrategy(new LaxRedirectStrategy());
+
+ Source source = new Source(EntityUtils.toString(entity));
+ List <NameValuePair> nvps = new ArrayList <NameValuePair>();
+ FormFields formFields = source.getFormFields();
+
+ List<Element> forms = source.getAllElements(HTMLElementName.FORM);
+ Assert.assertEquals("Only one form expected but got " + forms.size(), 1, forms.size());
+ String postUrl = forms.get(0).getAttributeValue("action");
+
+ Assert.assertNotNull("Form field 'wa' not found", formFields.get("wa"));
+ Assert.assertNotNull("Form field 'wresult' not found", formFields.get("wresult"));
+
+ for (FormField formField : formFields) {
+ if (formField.getUserValueCount() != 0) {
+ nvps.add(new BasicNameValuePair(formField.getName(),
+ formField.getValues().get(0)));
+ }
+ }
+ HttpPost httppost = new HttpPost(postUrl);
+ httppost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
+
+ response = httpclient.execute(httppost);
+
+ entity = response.getEntity();
+ System.out.println(response.getStatusLine());
+ Assert.assertTrue("RP HTTP Response code: " + response.getStatusLine().getStatusCode()
+ + " [Expected: " + returnCodeRP + "]",
+ returnCodeRP == response.getStatusLine().getStatusCode());
+
+ if (entity != null) {
+ System.out.println("Response content length: " + entity.getContentLength());
+ }
+
+ return EntityUtils.toString(entity);
+ } finally {
+ // When HttpClient instance is no longer needed,
+ // shut down the connection manager to ensure
+ // immediate deallocation of all system resources
+ httpclient.getConnectionManager().shutdown();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/TestCallbackHandler.java
----------------------------------------------------------------------
diff --git a/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/TestCallbackHandler.java b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/TestCallbackHandler.java
new file mode 100644
index 0000000..eca3695
--- /dev/null
+++ b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/TestCallbackHandler.java
@@ -0,0 +1,48 @@
+/**
+ * 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.integrationtests;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.cxf.fediz.core.spi.WReqCallback;
+
+public class TestCallbackHandler implements CallbackHandler {
+
+ static final String TEST_WREQ =
+ "<RequestSecurityToken xmlns=\"http://docs.oasis-open.org/ws-sx/ws-trust/200512\">"
+ + "<TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</TokenType>"
+ + "</RequestSecurityToken>";
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof WReqCallback) {
+ WReqCallback callback = (WReqCallback) callbacks[i];
+ callback.setWreq(TEST_WREQ);
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/WReqTest.java
----------------------------------------------------------------------
diff --git a/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/WReqTest.java b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/WReqTest.java
new file mode 100644
index 0000000..d6f3a7a
--- /dev/null
+++ b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/WReqTest.java
@@ -0,0 +1,329 @@
+/**
+ * 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.integrationtests;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.htmlparser.jericho.Element;
+import net.htmlparser.jericho.FormField;
+import net.htmlparser.jericho.FormFields;
+import net.htmlparser.jericho.HTMLElementName;
+import net.htmlparser.jericho.Source;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.cxf.fediz.core.ClaimTypes;
+import org.apache.cxf.fediz.tomcat.FederationAuthenticator;
+import org.apache.http.Consts;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.LaxRedirectStrategy;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+/**
+ * A test for sending a TokenType request to the IdP via the "wreq" parameter.
+ */
+public class WReqTest {
+
+ static String idpHttpsPort;
+ static String rpHttpsPort;
+
+ private static Tomcat idpServer;
+ private static Tomcat rpServer;
+
+ @BeforeClass
+ public static void init() {
+ System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
+ System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
+ System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.springframework.webflow", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.springframework.security.web", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.cxf.fediz", "info");
+ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.cxf", "info");
+
+ idpHttpsPort = System.getProperty("idp.https.port");
+ Assert.assertNotNull("Property 'idp.https.port' null", idpHttpsPort);
+ rpHttpsPort = System.getProperty("rp.https.port");
+ Assert.assertNotNull("Property 'rp.https.port' null", rpHttpsPort);
+
+ initIdp();
+ initRp();
+ }
+
+ private static void initIdp() {
+ try {
+ idpServer = new Tomcat();
+ idpServer.setPort(0);
+ String currentDir = new File(".").getCanonicalPath();
+ idpServer.setBaseDir(currentDir + File.separator + "target");
+
+ idpServer.getHost().setAppBase("tomcat/idp/webapps");
+ idpServer.getHost().setAutoDeploy(true);
+ idpServer.getHost().setDeployOnStartup(true);
+
+ Connector httpsConnector = new Connector();
+ httpsConnector.setPort(Integer.parseInt(idpHttpsPort));
+ httpsConnector.setSecure(true);
+ httpsConnector.setScheme("https");
+ //httpsConnector.setAttribute("keyAlias", keyAlias);
+ httpsConnector.setAttribute("keystorePass", "tompass");
+ httpsConnector.setAttribute("keystoreFile", "test-classes/server.jks");
+ httpsConnector.setAttribute("truststorePass", "tompass");
+ httpsConnector.setAttribute("truststoreFile", "test-classes/server.jks");
+ httpsConnector.setAttribute("clientAuth", "want");
+ // httpsConnector.setAttribute("clientAuth", "false");
+ httpsConnector.setAttribute("sslProtocol", "TLS");
+ httpsConnector.setAttribute("SSLEnabled", true);
+
+ idpServer.getService().addConnector(httpsConnector);
+
+ idpServer.addWebapp("/fediz-idp-sts", "fediz-idp-sts");
+ idpServer.addWebapp("/fediz-idp", "fediz-idp");
+
+ idpServer.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void initRp() {
+ try {
+ rpServer = new Tomcat();
+ rpServer.setPort(0);
+ String currentDir = new File(".").getCanonicalPath();
+ rpServer.setBaseDir(currentDir + File.separator + "target");
+
+ rpServer.getHost().setAppBase("tomcat/rp/webapps");
+ rpServer.getHost().setAutoDeploy(true);
+ rpServer.getHost().setDeployOnStartup(true);
+
+ Connector httpsConnector = new Connector();
+ httpsConnector.setPort(Integer.parseInt(rpHttpsPort));
+ httpsConnector.setSecure(true);
+ httpsConnector.setScheme("https");
+ //httpsConnector.setAttribute("keyAlias", keyAlias);
+ httpsConnector.setAttribute("keystorePass", "tompass");
+ httpsConnector.setAttribute("keystoreFile", "test-classes/server.jks");
+ httpsConnector.setAttribute("truststorePass", "tompass");
+ httpsConnector.setAttribute("truststoreFile", "test-classes/server.jks");
+ // httpsConnector.setAttribute("clientAuth", "false");
+ httpsConnector.setAttribute("clientAuth", "want");
+ httpsConnector.setAttribute("sslProtocol", "TLS");
+ httpsConnector.setAttribute("SSLEnabled", true);
+
+ rpServer.getService().addConnector(httpsConnector);
+
+ //Context ctx =
+ Context cxt = rpServer.addWebapp("/fedizhelloworld", "simpleWebapp");
+ FederationAuthenticator fa = new FederationAuthenticator();
+ fa.setConfigFile(currentDir + File.separator + "target" + File.separator
+ + "test-classes" + File.separator + "fediz_config_wreq.xml");
+ cxt.getPipeline().addValve(fa);
+
+
+ rpServer.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @AfterClass
+ public static void cleanup() {
+ try {
+ if (idpServer.getServer() != null
+ && idpServer.getServer().getState() != LifecycleState.DESTROYED) {
+ if (idpServer.getServer().getState() != LifecycleState.STOPPED) {
+ idpServer.stop();
+ }
+ idpServer.destroy();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ try {
+ if (rpServer.getServer() != null
+ && rpServer.getServer().getState() != LifecycleState.DESTROYED) {
+ if (rpServer.getServer().getState() != LifecycleState.STOPPED) {
+ rpServer.stop();
+ }
+ rpServer.destroy();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public String getIdpHttpsPort() {
+ return idpHttpsPort;
+ }
+
+ public String getRpHttpsPort() {
+ return rpHttpsPort;
+ }
+
+ public String getServletContextName() {
+ return "fedizhelloworld";
+ }
+
+ @org.junit.Test
+ public void testSAML1TokenViaWReq() throws Exception {
+ String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/secure/fedservlet";
+ String user = "alice";
+ String password = "ecila";
+ String response = sendHttpGet(url, user, password);
+
+ Assert.assertTrue("Principal not " + user, response.indexOf("userPrincipal=" + user) > 0);
+ Assert.assertTrue("User " + user + " does not have role Admin", response.indexOf("role:Admin=false") > 0);
+ Assert.assertTrue("User " + user + " does not have role Manager", response.indexOf("role:Manager=false") > 0);
+ Assert.assertTrue("User " + user + " must have role User", response.indexOf("role:User=true") > 0);
+
+ String claim = ClaimTypes.FIRSTNAME.toString();
+ Assert.assertTrue("User " + user + " claim " + claim + " is not 'Alice'",
+ response.indexOf(claim + "=Alice") > 0);
+ claim = ClaimTypes.LASTNAME.toString();
+ Assert.assertTrue("User " + user + " claim " + claim + " is not 'Smith'",
+ response.indexOf(claim + "=Smith") > 0);
+ claim = ClaimTypes.EMAILADDRESS.toString();
+ Assert.assertTrue("User " + user + " claim " + claim + " is not 'alice@realma.org'",
+ response.indexOf(claim + "=alice@realma.org") > 0);
+
+ }
+
+ private String sendHttpGet(String url, String user, String password) throws Exception {
+ return sendHttpGet(url, user, password, 200, 200);
+ }
+
+ private String sendHttpGet(String url, String user, String password, int returnCodeIDP, int returnCodeRP)
+ throws Exception {
+ DefaultHttpClient httpclient = new DefaultHttpClient();
+ try {
+ httpclient.getCredentialsProvider().setCredentials(
+ new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+ new UsernamePasswordCredentials(user, password));
+
+ KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream instream = new FileInputStream(new File("./target/test-classes/client.jks"));
+ try {
+ trustStore.load(instream, "clientpass".toCharArray());
+ } finally {
+ try {
+ instream.close();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
+ Scheme schIdp = new Scheme("https", Integer.parseInt(getIdpHttpsPort()), socketFactory);
+ httpclient.getConnectionManager().getSchemeRegistry().register(schIdp);
+ Scheme schRp = new Scheme("https", Integer.parseInt(getRpHttpsPort()), socketFactory);
+ httpclient.getConnectionManager().getSchemeRegistry().register(schRp);
+
+ HttpGet httpget = new HttpGet(url);
+
+ HttpResponse response = httpclient.execute(httpget);
+ HttpEntity entity = response.getEntity();
+
+ System.out.println(response.getStatusLine());
+ if (entity != null) {
+ System.out.println("Response content length: " + entity.getContentLength());
+ }
+ Assert.assertTrue("IDP HTTP Response code: " + response.getStatusLine().getStatusCode()
+ + " [Expected: " + returnCodeIDP + "]",
+ returnCodeIDP == response.getStatusLine().getStatusCode());
+
+ if (response.getStatusLine().getStatusCode() != 200) {
+ return null;
+ }
+
+ // Redirect to a POST is not supported without user interaction
+ // http://www.ietf.org/rfc/rfc2616.txt
+ // If the 301 status code is received in response to a request other
+ // than GET or HEAD, the user agent MUST NOT automatically redirect the
+ // request unless it can be confirmed by the user, since this might
+ // change the conditions under which the request was issued.
+
+ httpclient.setRedirectStrategy(new LaxRedirectStrategy());
+
+ Source source = new Source(EntityUtils.toString(entity));
+ List <NameValuePair> nvps = new ArrayList <NameValuePair>();
+ FormFields formFields = source.getFormFields();
+
+ List<Element> forms = source.getAllElements(HTMLElementName.FORM);
+ Assert.assertEquals("Only one form expected but got " + forms.size(), 1, forms.size());
+ String postUrl = forms.get(0).getAttributeValue("action");
+
+ Assert.assertNotNull("Form field 'wa' not found", formFields.get("wa"));
+ Assert.assertNotNull("Form field 'wresult' not found", formFields.get("wresult"));
+
+ for (FormField formField : formFields) {
+ if (formField.getUserValueCount() != 0) {
+ nvps.add(new BasicNameValuePair(formField.getName(),
+ formField.getValues().get(0)));
+ }
+ }
+ HttpPost httppost = new HttpPost(postUrl);
+ httppost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
+
+ response = httpclient.execute(httppost);
+
+ entity = response.getEntity();
+ System.out.println(response.getStatusLine());
+ Assert.assertTrue("RP HTTP Response code: " + response.getStatusLine().getStatusCode()
+ + " [Expected: " + returnCodeRP + "]",
+ returnCodeRP == response.getStatusLine().getStatusCode());
+
+ if (entity != null) {
+ System.out.println("Response content length: " + entity.getContentLength());
+ }
+
+ return EntityUtils.toString(entity);
+ } finally {
+ // When HttpClient instance is no longer needed,
+ // shut down the connection manager to ensure
+ // immediate deallocation of all system resources
+ httpclient.getConnectionManager().shutdown();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/systests/tomcat7/src/test/resources/fediz_config_bad_wreq.xml
----------------------------------------------------------------------
diff --git a/systests/tomcat7/src/test/resources/fediz_config_bad_wreq.xml b/systests/tomcat7/src/test/resources/fediz_config_bad_wreq.xml
new file mode 100644
index 0000000..a518910
--- /dev/null
+++ b/systests/tomcat7/src/test/resources/fediz_config_bad_wreq.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Place in Tomcat conf folder or other location as designated in this sample's webapp/META-INF/context.xml file.
+ Keystore referenced below must have IDP STS' public cert included in it. This example re-uses the Tomcat SSL
+ keystore (tomcat-rp.jks) for this task; alternatively you may wish to use a Fediz-specific keystore instead.
+-->
+<FedizConfig>
+ <contextConfig name="/fedizhelloworld">
+ <audienceUris>
+ <audienceItem>urn:org:apache:cxf:fediz:fedizhelloworld</audienceItem>
+ </audienceUris>
+ <certificateStores>
+ <trustManager>
+ <keyStore file="test-classes/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="federationProtocolType" version="1.0.0">
+ <realm>urn:org:apache:cxf:fediz:fedizhelloworld</realm>
+ <issuer>https://localhost:${idp.https.port}/fediz-idp/federation</issuer>
+ <roleDelimiter>,</roleDelimiter>
+ <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+ <freshness>10</freshness>
+ <homeRealm type="String">urn:org:apache:cxf:fediz:idp:realm-A</homeRealm>
+ <claimTypesRequested>
+ <claimType type="a particular claim type"
+ optional="true" />
+ </claimTypesRequested>
+ <request type="Class">org.apache.cxf.fediz.integrationtests.BadWReqCallbackHandler</request>
+ </protocol>
+ <logoutURL>/secure/logout</logoutURL>
+ <logoutRedirectTo>/index.html</logoutRedirectTo>
+ </contextConfig>
+</FedizConfig>
+
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/336a959f/systests/tomcat7/src/test/resources/fediz_config_wreq.xml
----------------------------------------------------------------------
diff --git a/systests/tomcat7/src/test/resources/fediz_config_wreq.xml b/systests/tomcat7/src/test/resources/fediz_config_wreq.xml
new file mode 100644
index 0000000..d5263ef
--- /dev/null
+++ b/systests/tomcat7/src/test/resources/fediz_config_wreq.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Place in Tomcat conf folder or other location as designated in this sample's webapp/META-INF/context.xml file.
+ Keystore referenced below must have IDP STS' public cert included in it. This example re-uses the Tomcat SSL
+ keystore (tomcat-rp.jks) for this task; alternatively you may wish to use a Fediz-specific keystore instead.
+-->
+<FedizConfig>
+ <contextConfig name="/fedizhelloworld">
+ <audienceUris>
+ <audienceItem>urn:org:apache:cxf:fediz:fedizhelloworld</audienceItem>
+ </audienceUris>
+ <certificateStores>
+ <trustManager>
+ <keyStore file="test-classes/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="federationProtocolType" version="1.0.0">
+ <realm>urn:org:apache:cxf:fediz:fedizhelloworld</realm>
+ <issuer>https://localhost:${idp.https.port}/fediz-idp/federation</issuer>
+ <roleDelimiter>,</roleDelimiter>
+ <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+ <freshness>10</freshness>
+ <homeRealm type="String">urn:org:apache:cxf:fediz:idp:realm-A</homeRealm>
+ <claimTypesRequested>
+ <claimType type="a particular claim type"
+ optional="true" />
+ </claimTypesRequested>
+ <request type="Class">org.apache.cxf.fediz.integrationtests.TestCallbackHandler</request>
+ </protocol>
+ <logoutURL>/secure/logout</logoutURL>
+ <logoutRedirectTo>/index.html</logoutRedirectTo>
+ </contextConfig>
+</FedizConfig>
+