cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject cxf git commit: Add the ability to the STS LoginModule to disable OnBehalfOf
Date Tue, 06 Jan 2015 13:44:30 GMT
Repository: cxf
Updated Branches:
  refs/heads/master de09800f0 -> dae46f8c0


Add the ability to the STS LoginModule to disable OnBehalfOf


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

Branch: refs/heads/master
Commit: dae46f8c027afb58879d5c305cb6dc0a3a964750
Parents: de09800
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Tue Jan 6 13:43:17 2015 +0000
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Tue Jan 6 13:43:17 2015 +0000

----------------------------------------------------------------------
 .../cxf/ws/security/trust/STSLoginModule.java   |  21 ++-
 .../ws/security/trust/STSTokenValidator.java    |  27 +++-
 .../apache/cxf/systest/sts/jaas/JAASTest.java   | 129 ++++++++++++++++++-
 .../apache/cxf/systest/sts/jaas/DoubleIt.wsdl   |   3 +
 .../apache/cxf/systest/sts/jaas/cxf-service.xml |  21 +++
 .../systests/basic/src/test/resources/sts.jaas  |   9 ++
 6 files changed, 200 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/dae46f8c/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java
----------------------------------------------------------------------
diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java
index 5d634ab..029c11b 100644
--- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java
@@ -75,12 +75,24 @@ public class STSLoginModule implements LoginModule {
     /**
      * Whether we require roles or not from the STS. If this is not set then the 
      * WS-Trust validate binding is used. If it is set then the issue binding is 
-     * used, where the Username + Password credentials are passed via "OnBehalfOf".
-     * In addition, claims are added to the request for the standard "role" ClaimType.
+     * used, where the Username + Password credentials are passed via "OnBehalfOf"
+     * (unless the DISABLE_ON_BEHALF_OF property is set to "true", see below). In addition,

+     * claims are added to the request for the standard "role" ClaimType.
      */
     public static final String REQUIRE_ROLES = "require.roles";
     
     /**
+     * Whether to disable passing Username + Password credentials via "OnBehalfOf". If the
+     * REQUIRE_ROLES property (see above) is set to "true", then the Issue Binding is used
+     * and the credentials are passed via OnBehalfOf. If this (DISABLE_ON_BEHALF_OF) property
+     * is set to "true", then the credentials instead are passed through to the 
+     * WS-SecurityPolicy layer and used depending on the security policy of the STS endpoint.
+     * For example, if the STS endpoint requires a WS-Security UsernameToken, then the 
+     * credentials are inserted here.
+     */
+    public static final String DISABLE_ON_BEHALF_OF = "disable.on.behalf.of";
+    
+    /**
      * The WSDL Location of the STS
      */
     public static final String WSDL_LOCATION = "wsdl.location";
@@ -123,6 +135,7 @@ public class STSLoginModule implements LoginModule {
     private Subject subject;
     private CallbackHandler callbackHandler;
     private boolean requireRoles;
+    private boolean disableOnBehalfOf;
     private String wsdlLocation;
     private String serviceName;
     private String endpointName;
@@ -140,6 +153,9 @@ public class STSLoginModule implements LoginModule {
         if (options.containsKey(REQUIRE_ROLES)) {
             requireRoles = Boolean.parseBoolean((String)options.get(REQUIRE_ROLES));
         }
+        if (options.containsKey(DISABLE_ON_BEHALF_OF)) {
+            disableOnBehalfOf = Boolean.parseBoolean((String)options.get(DISABLE_ON_BEHALF_OF));
+        }
         if (options.containsKey(WSDL_LOCATION)) {
             wsdlLocation = (String)options.get(WSDL_LOCATION);
         }
@@ -199,6 +215,7 @@ public class STSLoginModule implements LoginModule {
         
         STSTokenValidator validator = new STSTokenValidator(true);
         validator.setUseIssueBinding(requireRoles);
+        validator.setUseOnBehalfOf(!disableOnBehalfOf);
         
         // Authenticate token
         try {

http://git-wip-us.apache.org/repos/asf/cxf/blob/dae46f8c/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenValidator.java
----------------------------------------------------------------------
diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenValidator.java
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenValidator.java
index f58e12e..da7f06b 100644
--- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenValidator.java
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenValidator.java
@@ -45,13 +45,18 @@ import org.apache.wss4j.dom.validate.Validator;
 
 /**
  * A WSS4J-based Validator to validate a received WS-Security credential by dispatching
- * it to a STS via WS-Trust. The default binding is "validate", but "issue" using "OnBehalfOf"
- * is also possible by setting the "useIssueBinding" property.
+ * it to a STS via WS-Trust. The default binding is "validate", but "issue" is also possible
+ * by setting the "useIssueBinding" property. In this case, the credentials are sent via
+ * "OnBehalfOf" unless the "useOnBehalfOf" property is set to "false", in which case the
+ * credentials are used depending on the security policy of the STS endpoint (e.g. in a 
+ * UsernameToken if this is what the policy requires). Setting "useOnBehalfOf" to "false"
+ 
+ * "useIssueBinding" to "true" only works for validating UsernameTokens.
  */
 public class STSTokenValidator implements Validator {
     private STSSamlAssertionValidator samlValidator = new STSSamlAssertionValidator();
     private boolean alwaysValidateToSts;
     private boolean useIssueBinding;
+    private boolean useOnBehalfOf = true;
     private STSClient stsClient;
     private TokenStore tokenStore;
     
@@ -125,11 +130,19 @@ public class STSTokenValidator implements Validator {
                 
                 SecurityToken returnedToken = null;
                 
-                if (useIssueBinding) {
+                if (useIssueBinding && useOnBehalfOf) {
                     ElementCallbackHandler callbackHandler = new ElementCallbackHandler(tokenElement);
                     c.setOnBehalfOf(callbackHandler);
                     returnedToken = c.requestSecurityToken();
                     c.setOnBehalfOf(null);
+                } else if (useIssueBinding && !useOnBehalfOf && credential.getUsernametoken()
!= null) {
+                    c.getProperties().put(SecurityConstants.USERNAME, 
+                                          credential.getUsernametoken().getName());
+                    c.getProperties().put(SecurityConstants.PASSWORD, 
+                                          credential.getUsernametoken().getPassword());
+                    returnedToken = c.requestSecurityToken();
+                    c.getProperties().remove(SecurityConstants.USERNAME);
+                    c.getProperties().remove(SecurityConstants.PASSWORD);
                 } else {
                     List<SecurityToken> tokens = c.validateSecurityToken(token);
                     returnedToken = tokens.get(0);
@@ -214,6 +227,14 @@ public class STSTokenValidator implements Validator {
         this.useIssueBinding = useIssueBinding;
     }
     
+    public boolean isUseOnBehalfOf() {
+        return useOnBehalfOf;
+    }
+
+    public void setUseOnBehalfOf(boolean useOnBehalfOf) {
+        this.useOnBehalfOf = useOnBehalfOf;
+    }
+    
     public STSClient getStsClient() {
         return stsClient;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/dae46f8c/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java
----------------------------------------------------------------------
diff --git a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java
b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java
index eab5830..cdc2043 100644
--- a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java
+++ b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java
@@ -205,18 +205,136 @@ public class JAASTest extends AbstractBusClientServerTestBase {
     }
     
     @org.junit.Test
+    public void testSuccessfulPassthroughInvocation() throws Exception {
+
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = JAASTest.class.getResource("cxf-client.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        SpringBusFactory.setDefaultBus(bus);
+        SpringBusFactory.setThreadDefaultBus(bus);
+
+        URL wsdl = JAASTest.class.getResource("DoubleIt.wsdl");
+        Service service = Service.create(wsdl, SERVICE_QNAME);
+        QName portQName = new QName(NAMESPACE, "DoubleItUTPort3");
+        DoubleItPortType utPort = 
+            service.getPort(portQName, DoubleItPortType.class);
+        updateAddressPort(utPort, PORT);
+        
+        ((BindingProvider)utPort).getRequestContext().put(
+            SecurityConstants.USERNAME, "alice");
+        ((BindingProvider)utPort).getRequestContext().put(
+            SecurityConstants.PASSWORD, "clarinet");
+        
+        doubleIt(utPort, 25);
+        
+        // Note that the UsernameToken should be cached for the second invocation
+        doubleIt(utPort, 35);
+        
+        ((java.io.Closeable)utPort).close();
+        bus.shutdown(true);
+    }
+    
+    @org.junit.Test
+    public void testUnsuccessfulAuthenticationPassthroughInvocation() throws Exception {
+
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = JAASTest.class.getResource("cxf-client.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        SpringBusFactory.setDefaultBus(bus);
+        SpringBusFactory.setThreadDefaultBus(bus);
+
+        URL wsdl = JAASTest.class.getResource("DoubleIt.wsdl");
+        Service service = Service.create(wsdl, SERVICE_QNAME);
+        QName portQName = new QName(NAMESPACE, "DoubleItUTPort3");
+        DoubleItPortType utPort = 
+            service.getPort(portQName, DoubleItPortType.class);
+        updateAddressPort(utPort, PORT);
+        
+        ((BindingProvider)utPort).getRequestContext().put(
+            SecurityConstants.USERNAME, "alice");
+        ((BindingProvider)utPort).getRequestContext().put(
+            SecurityConstants.PASSWORD, "clarinet2");
+        
+        try {
+            doubleIt(utPort, 25);
+            fail("Failure expected on an incorrect password");
+        } catch (Exception ex) {
+            // expected
+        }
+        
+        ((java.io.Closeable)utPort).close();
+        bus.shutdown(true);
+    }
+    
+    @org.junit.Test
+    public void testUnsuccessfulAuthorizationPassthroughInvocation() throws Exception {
+
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = JAASTest.class.getResource("cxf-client.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        SpringBusFactory.setDefaultBus(bus);
+        SpringBusFactory.setThreadDefaultBus(bus);
+
+        URL wsdl = JAASTest.class.getResource("DoubleIt.wsdl");
+        Service service = Service.create(wsdl, SERVICE_QNAME);
+        QName portQName = new QName(NAMESPACE, "DoubleItUTPort3");
+        DoubleItPortType utPort = 
+            service.getPort(portQName, DoubleItPortType.class);
+        updateAddressPort(utPort, PORT);
+        
+        ((BindingProvider)utPort).getRequestContext().put(
+            SecurityConstants.USERNAME, "bob");
+        ((BindingProvider)utPort).getRequestContext().put(
+            SecurityConstants.PASSWORD, "trombone");
+        
+        try {
+            doubleIt(utPort, 25);
+            fail("Failure expected on an incorrect role");
+        } catch (Exception ex) {
+            // expected
+        }
+        
+        ((java.io.Closeable)utPort).close();
+        bus.shutdown(true);
+    }
+    
+    @org.junit.Test
     public void testJAXRSSuccessfulInvocation() throws Exception {
-        doubleIt("alice", "clarinet", false);
+        final String address = "https://localhost:" + PORT + "/doubleit/services/doubleit-rs";
+        doubleIt("alice", "clarinet", address, false);
     }
     
     @org.junit.Test
     public void testJAXRSUnsuccessfulAuthentication() throws Exception {
-        doubleIt("alice", "clarinet2", true);
+        final String address = "https://localhost:" + PORT + "/doubleit/services/doubleit-rs";
+        doubleIt("alice", "clarinet2", address, true);
     }
     
     @org.junit.Test
     public void testJAXRSUnsuccessfulAuthorization() throws Exception {
-        doubleIt("bob", "trombone", true);
+        final String address = "https://localhost:" + PORT + "/doubleit/services/doubleit-rs";
+        doubleIt("bob", "trombone", address, true);
+    }
+    
+    @org.junit.Test
+    public void testJAXRSSuccessfulPassthroughInvocation() throws Exception {
+        final String address = "https://localhost:" + PORT + "/doubleit/services/doubleit-rs3";
+        doubleIt("alice", "clarinet", address, false);
+    }
+    
+    @org.junit.Test
+    public void testJAXRSUnsuccessfulAuthenticationPassthroughInvocation() throws Exception
{
+        final String address = "https://localhost:" + PORT + "/doubleit/services/doubleit-rs3";
+        doubleIt("alice", "clarinet2", address, true);
+    }
+    
+    @org.junit.Test
+    public void testJAXRSUnsuccessfulAuthorizationPassthroughInvocation() throws Exception
{
+        final String address = "https://localhost:" + PORT + "/doubleit/services/doubleit-rs3";
+        doubleIt("bob", "trombone", address, true);
     }
     
     private static void doubleIt(DoubleItPortType port, int numToDouble) {
@@ -224,9 +342,10 @@ public class JAASTest extends AbstractBusClientServerTestBase {
         assertEquals(numToDouble * 2 , resp);
     }
     
-    private static void doubleIt(String username, String password, boolean authFailureExpected)
{
+    private static void doubleIt(String username, String password, 
+                                 String address,
+                                 boolean authFailureExpected) {
         final String configLocation = "org/apache/cxf/systest/sts/jaas/cxf-client.xml";
-        final String address = "https://localhost:" + PORT + "/doubleit/services/doubleit-rs";
         final int numToDouble = 25;  
        
         WebClient client = null;

http://git-wip-us.apache.org/repos/asf/cxf/blob/dae46f8c/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl
----------------------------------------------------------------------
diff --git a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl
b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl
index 25b6d90..d157fc1 100644
--- a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl
+++ b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl
@@ -39,6 +39,9 @@
         <wsdl:port name="DoubleItUTPort2" binding="tns:DoubleItUTBinding">
             <soap:address location="https://localhost:8081/doubleit/services/doubleitut2"/>
         </wsdl:port>
+        <wsdl:port name="DoubleItUTPort3" binding="tns:DoubleItUTBinding">
+            <soap:address location="https://localhost:8081/doubleit/services/doubleitut3"/>
+        </wsdl:port>
     </wsdl:service>
     <wsp:Policy wsu:Id="DoubleItUTPolicy">
         <wsp:ExactlyOne>

http://git-wip-us.apache.org/repos/asf/cxf/blob/dae46f8c/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml
----------------------------------------------------------------------
diff --git a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml
b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml
index 52b1bf6..00669a6 100644
--- a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml
+++ b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml
@@ -80,6 +80,20 @@
         </jaxws:inInterceptors>
     </jaxws:endpoint>
     
+    <bean id="authenticationInterceptor3" class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
+        <property name="contextName" value="sts_standalone_passthrough"/>
+    </bean>
+    
+    <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="doubleitut3"
implementor="org.apache.cxf.systest.sts.jaas.DoubleItPortTypeImpl" endpointName="s:DoubleItUTPort3"
serviceName="s:DoubleItService" depends-on="ClientAuthHttpsSettings" address="https://localhost:${testutil.ports.Server}/doubleit/services/doubleitut3"
wsdlLocation="org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl">
+        <jaxws:properties>
+            <entry key="ws-security.validate.token" value="false"/>
+        </jaxws:properties>
+        <jaxws:inInterceptors>
+            <ref bean="authenticationInterceptor3"/>
+            <ref bean="authorizationInterceptor"/>
+        </jaxws:inInterceptors>
+    </jaxws:endpoint>
+    
     <!-- JAX-RS service -->
     <jaxrs:server modelRef="classpath:org/apache/cxf/systest/sts/jaas/jaxrs.xml" depends-on="ClientAuthHttpsSettings"
address="https://localhost:${testutil.ports.Server}/doubleit/services/doubleit-rs">
         <jaxrs:properties>
@@ -91,6 +105,13 @@
         </jaxrs:inInterceptors>
     </jaxrs:server>
     
+    <jaxrs:server modelRef="classpath:org/apache/cxf/systest/sts/jaas/jaxrs.xml" depends-on="ClientAuthHttpsSettings"
address="https://localhost:${testutil.ports.Server}/doubleit/services/doubleit-rs3">
+        <jaxrs:inInterceptors>
+            <ref bean="authenticationInterceptor3"/>
+            <ref bean="authorizationInterceptor"/>
+        </jaxrs:inInterceptors>
+    </jaxrs:server>
+    
     <httpj:engine-factory id="ClientAuthHttpsSettings" bus="cxf">
         <httpj:engine port="${testutil.ports.Server}">
             <httpj:tlsServerParameters>

http://git-wip-us.apache.org/repos/asf/cxf/blob/dae46f8c/services/sts/systests/basic/src/test/resources/sts.jaas
----------------------------------------------------------------------
diff --git a/services/sts/systests/basic/src/test/resources/sts.jaas b/services/sts/systests/basic/src/test/resources/sts.jaas
index 1ae10af..b9da508 100644
--- a/services/sts/systests/basic/src/test/resources/sts.jaas
+++ b/services/sts/systests/basic/src/test/resources/sts.jaas
@@ -12,3 +12,12 @@ sts_standalone {
     ws-security.username="bob"
     ws-security.password="trombone";
 };
+
+sts_standalone_passthrough {
+    org.apache.cxf.ws.security.trust.STSLoginModule required 
+    require.roles="true"
+    disable.on.behalf.of="true"
+    wsdl.location="https://localhost:${testutil.ports.STSServer}/SecurityTokenService/Transport?wsdl"
+    service.name="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}SecurityTokenService"
+    endpoint.name="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}Transport_Port";
+};


Mime
View raw message