Author: coheigea
Date: Wed Mar 27 15:20:30 2013
New Revision: 1461639
URL: http://svn.apache.org/r1461639
Log:
[CXF-4931] - Create the SecurityContext from a JAAS Subject in the WS-* layer
if available
Added:
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/server/CustomUTValidator.java
Modified:
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUt.wsdl
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/client/client.xml
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/server/server.xml
Modified:
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
URL:
http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java?rev=1461639&r1=1461638&r2=1461639&view=diff
==============================================================================
---
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
(original)
+++
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
Wed Mar 27 15:20:30 2013
@@ -275,6 +275,23 @@ public final class SecurityConstants {
*/
public static final String SUBJECT_CERT_CONSTRAINTS =
"ws-security.subject.cert.constraints";
+ /**
+ * The Subject Role Classifier to use. If one of the WSS4J Validators
returns a JAAS Subject
+ * from Validation, then the WSS4JInInterceptor will attempt to create a
SecurityContext
+ * based on this Subject. If this value is not specified, then it tries to
get roles using
+ * the DefaultSecurityContext in cxf-rt-core. Otherwise it uses this value
in combination
+ * with the SUBJECT_ROLE_CLASSIFIER_TYPE to get the roles from the Subject.
+ */
+ public static final String SUBJECT_ROLE_CLASSIFIER =
"ws-security.role.classifier";
+
+ /**
+ * The Subject Role Classifier Type to use. If one of the WSS4J Validators
returns a JAAS Subject
+ * from Validation, then the WSS4JInInterceptor will attempt to create a
SecurityContext
+ * based on this Subject. Currently accepted values are "prefix" or
"classname". Must be
+ * used in conjunction with the SUBJECT_ROLE_CLASSIFIER. The default value
is "prefix".
+ */
+ public static final String SUBJECT_ROLE_CLASSIFIER_TYPE =
"ws-security.role.classifier.type";
+
//
// Validator implementations for validating received security tokens
//
@@ -442,7 +459,7 @@ public final class SecurityConstants {
STS_TOKEN_DO_CANCEL, CACHE_ISSUED_TOKEN_IN_ENDPOINT,
DISABLE_STS_CLIENT_WSMEX_CALL_USING_EPR_ADDRESS, STS_TOKEN_CRYPTO,
STS_TOKEN_PROPERTIES, STS_TOKEN_USERNAME, STS_TOKEN_ACT_AS,
STS_TOKEN_ON_BEHALF_OF,
- TOKEN, TOKEN_ID
+ TOKEN, TOKEN_ID, SUBJECT_ROLE_CLASSIFIER,
SUBJECT_ROLE_CLASSIFIER_TYPE
}));
ALL_PROPERTIES = Collections.unmodifiableSet(s);
}
Modified:
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java?rev=1461639&r1=1461638&r2=1461639&view=diff
==============================================================================
---
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
(original)
+++
cxf/branches/wss4j2.0-port/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
Wed Mar 27 15:20:30 2013
@@ -30,6 +30,7 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
@@ -57,6 +58,8 @@ import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.URIMappingInterceptor;
+import org.apache.cxf.interceptor.security.DefaultSecurityContext;
+import org.apache.cxf.interceptor.security.RolePrefixSecurityContextImpl;
import org.apache.cxf.interceptor.security.SAMLSecurityContext;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.phase.Phase;
@@ -465,7 +468,25 @@ public class WSS4JInInterceptor extends
for (WSSecurityEngineResult o : wsResult) {
final Principal p =
(Principal)o.get(WSSecurityEngineResult.TAG_PRINCIPAL);
- if (p != null && isSecurityContextPrincipal(p, wsResult)) {
+ final Subject subject =
(Subject)o.get(WSSecurityEngineResult.TAG_SUBJECT);
+ if (subject != null) {
+ String roleClassifier =
+
(String)msg.getContextualProperty(SecurityConstants.SUBJECT_ROLE_CLASSIFIER);
+ if (roleClassifier != null && !"".equals(roleClassifier)) {
+ String roleClassifierType =
+
(String)msg.getContextualProperty(SecurityConstants.SUBJECT_ROLE_CLASSIFIER_TYPE);
+ if (roleClassifierType == null ||
"".equals(roleClassifierType)) {
+ roleClassifierType = "prefix";
+ }
+ msg.put(
+ SecurityContext.class,
+ new RolePrefixSecurityContextImpl(subject,
roleClassifier, roleClassifierType)
+ );
+ } else {
+ msg.put(SecurityContext.class, new
DefaultSecurityContext(subject));
+ }
+ break;
+ } else if (p != null && isSecurityContextPrincipal(p, wsResult)) {
msg.put(PRINCIPAL_RESULT, p);
if (!utWithCallbacks) {
WSS4JTokenConverter.convertToken(msg, p);
@@ -488,6 +509,7 @@ public class WSS4JInInterceptor extends
} else {
msg.put(SecurityContext.class, createSecurityContext(p));
}
+ break;
}
}
}
Modified:
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
URL:
http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java?rev=1461639&r1=1461638&r2=1461639&view=diff
==============================================================================
---
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
(original)
+++
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
Wed Mar 27 15:20:30 2013
@@ -22,6 +22,7 @@ package org.apache.cxf.systest.ws.ut;
import java.net.URL;
import javax.xml.namespace.QName;
+import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import org.apache.cxf.Bus;
@@ -31,6 +32,7 @@ import org.apache.cxf.frontend.ClientPro
import org.apache.cxf.systest.ws.common.SecurityTestUtil;
import org.apache.cxf.systest.ws.ut.server.Server;
import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.ws.security.SecurityConstants;
import org.example.contract.doubleit.DoubleItPortType;
import org.junit.BeforeClass;
@@ -322,4 +324,37 @@ public class UsernameTokenTest extends A
bus.shutdown(true);
}
+ @org.junit.Test
+ public void testPlaintextPrincipal() throws Exception {
+
+ SpringBusFactory bf = new SpringBusFactory();
+ URL busFile = UsernameTokenTest.class.getResource("client/client.xml");
+
+ Bus bus = bf.createBus(busFile.toString());
+ SpringBusFactory.setDefaultBus(bus);
+ SpringBusFactory.setThreadDefaultBus(bus);
+
+ URL wsdl = UsernameTokenTest.class.getResource("DoubleItUt.wsdl");
+ Service service = Service.create(wsdl, SERVICE_QNAME);
+ QName portQName = new QName(NAMESPACE,
"DoubleItPlaintextPrincipalPort");
+ DoubleItPortType utPort =
+ service.getPort(portQName, DoubleItPortType.class);
+ updateAddressPort(utPort, PORT);
+
+
((BindingProvider)utPort).getRequestContext().put(SecurityConstants.USERNAME,
"Alice");
+
+ utPort.doubleIt(25);
+
+ try {
+
((BindingProvider)utPort).getRequestContext().put(SecurityConstants.USERNAME,
"Frank");
+ utPort.doubleIt(30);
+ fail("Failure expected on a user with the wrong role");
+ } catch (javax.xml.ws.soap.SOAPFaultException ex) {
+ String error = "Unauthorized";
+ assertTrue(ex.getMessage().contains(error));
+ }
+
+ ((java.io.Closeable)utPort).close();
+ bus.shutdown(true);
+ }
}
Added:
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/server/CustomUTValidator.java
URL:
http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/server/CustomUTValidator.java?rev=1461639&view=auto
==============================================================================
---
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/server/CustomUTValidator.java
(added)
+++
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/server/CustomUTValidator.java
Wed Mar 27 15:20:30 2013
@@ -0,0 +1,60 @@
+/**
+ * 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.systest.ws.ut.server;
+
+import javax.security.auth.Subject;
+
+import org.apache.cxf.common.security.SimpleGroup;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSUsernameTokenPrincipal;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.UsernameTokenValidator;
+
+/**
+ * A custom UsernameToken Validator that wraps the default Validator in WSS4J
and set a Subject
+ * on the context as well. It adds a role for "Alice" of "manager", and a role
for everyone of
+ * "worker".
+ */
+public class CustomUTValidator extends UsernameTokenValidator {
+
+ public Credential validate(Credential credential, RequestData data) throws
WSSecurityException {
+ Credential cred = super.validate(credential, data);
+
+ UsernameToken ut = credential.getUsernametoken();
+ WSUsernameTokenPrincipal principal =
+ new WSUsernameTokenPrincipal(ut.getName(), ut.isHashed());
+ principal.setCreatedTime(ut.getCreated());
+ principal.setNonce(principal.getNonce());
+ principal.setPassword(ut.getPassword());
+ principal.setPasswordType(ut.getPasswordType());
+
+ Subject subject = new Subject();
+ subject.getPrincipals().add(principal);
+ if ("Alice".equals(ut.getName())) {
+ subject.getPrincipals().add(new SimpleGroup("manager",
ut.getName()));
+ }
+ subject.getPrincipals().add(new SimpleGroup("worker", ut.getName()));
+ cred.setSubject(subject);
+
+ return cred;
+ }
+}
Modified:
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUt.wsdl
URL:
http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUt.wsdl?rev=1461639&r1=1461638&r2=1461639&view=diff
==============================================================================
---
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUt.wsdl
(original)
+++
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/DoubleItUt.wsdl
Wed Mar 27 15:20:30 2013
@@ -224,6 +224,9 @@
<wsdl:port name="DoubleItDigestNoBindingPort"
binding="tns:DoubleItInlinePolicyBinding2">
<soap:address
location="https://localhost:9009/DoubleItUTDigestNoBinding" />
</wsdl:port>
+ <wsdl:port name="DoubleItPlaintextPrincipalPort"
binding="tns:DoubleItPlaintextBinding">
+ <soap:address
location="https://localhost:9009/DoubleItUTPlaintextPrincipal" />
+ </wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="DoubleItPlaintextPolicy">
Modified:
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/client/client.xml
URL:
http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/client/client.xml?rev=1461639&r1=1461638&r2=1461639&view=diff
==============================================================================
---
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/client/client.xml
(original)
+++
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/client/client.xml
Wed Mar 27 15:20:30 2013
@@ -41,9 +41,6 @@
<http:conduit name="https://localhost:.*">
<http:tlsClientParameters disableCNCheck="true">
- <sec:keyManagers keyPassword="password">
- <sec:keyStore type="jks" password="password"
resource="org/apache/cxf/systest/ws/security/Morpit.jks"/>
- </sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="jks" password="password"
resource="org/apache/cxf/systest/ws/security/Truststore.jks"/>
</sec:trustManagers>
@@ -238,4 +235,12 @@
</jaxws:features>
</jaxws:client>
+ <jaxws:client
name="{http://www.example.org/contract/DoubleIt}DoubleItPlaintextPrincipalPort"
+ createdFromAPI="true">
+ <jaxws:properties>
+ <entry key="ws-security.callback-handler"
+
value="org.apache.cxf.systest.ws.wssec10.client.UTPasswordCallback"/>
+ </jaxws:properties>
+ </jaxws:client>
+
</beans>
Modified:
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/server/server.xml
URL:
http://svn.apache.org/viewvc/cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/server/server.xml?rev=1461639&r1=1461638&r2=1461639&view=diff
==============================================================================
---
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/server/server.xml
(original)
+++
cxf/branches/wss4j2.0-port/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/ut/server/server.xml
Wed Mar 27 15:20:30 2013
@@ -64,7 +64,7 @@
<sec:include>.*_WITH_NULL_.*</sec:include>
<sec:exclude>.*_DH_anon_.*</sec:exclude>
</sec:cipherSuitesFilter>
- <sec:clientAuthentication want="true" required="true"/>
+ <sec:clientAuthentication want="true" required="false"/>
</httpj:tlsServerParameters>
</httpj:engine>
</httpj:engine-factory>
@@ -301,4 +301,35 @@
</jaxws:endpoint>
+ <bean id="subjectValidator"
class="org.apache.cxf.systest.ws.ut.server.CustomUTValidator" />
+
+ <bean id="authzInterceptor"
+
class="org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor">
+ <property name="methodRolesMap">
+ <map>
+ <entry key="doubleIt" value="manager"/>
+ </map>
+ </property>
+ </bean>
+
+ <jaxws:endpoint
+ id="PlaintextPrincipal"
+
address="https://localhost:${testutil.ports.Server}/DoubleItUTPlaintextPrincipal"
+ serviceName="s:DoubleItService"
+ endpointName="s:DoubleItPlaintextPrincipalPort"
+ xmlns:s="http://www.example.org/contract/DoubleIt"
+ implementor="org.apache.cxf.systest.ws.common.DoubleItPortTypeImpl"
+ wsdlLocation="org/apache/cxf/systest/ws/ut/DoubleItUt.wsdl"
+ depends-on="tls-settings">
+
+ <jaxws:properties>
+ <entry key="ws-security.callback-handler"
+
value="org.apache.cxf.systest.ws.wssec10.client.UTPasswordCallback"/>
+ <entry key="ws-security.ut.validator" value-ref="subjectValidator"/>
+ </jaxws:properties>
+ <jaxws:inInterceptors>
+ <ref bean="authzInterceptor"/>
+ </jaxws:inInterceptors>
+ </jaxws:endpoint>
+
</beans>