Authenticate UsernameToken via JAAS-SecurityDomain
lars.k Jul 12, 2011 12:19 PMHi,
my scenario is the following:
A .NET-Client calling a Java web service via a customBinding with WS-Security (UsernameToken, encrypted, signed, with Timestamp)
An Ejb-Webservice hosted on a JBoss AS 6 with configured with JBossWS CXF Stack
The service has a SecurityDomain with a UsersRolesLoginModule (which will later be substituted with a LDAP module).
The Username and password included in the UsernameToken need to be checked inside this SecurityDomain.
Here is the service:
@Stateless @WebService( name = "CoreService", targetNamespace = "http://www.myservice.de", serviceName = "ws", portName = "CoreService" ) @SOAPBinding( parameterStyle = ParameterStyle.WRAPPED, style = Style.DOCUMENT, use = Use.LITERAL ) @SecurityDomain( value = "MyRealm" ) @BindingType( javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING ) @WebContext( contextRoot = "/myservice/ws", urlPattern = "/CoreService" ) public class CoreService { ...
My first question: Do I need the WebContext-Annotation? The errors are the same with or without it so I can't really tell.
The CXF-config looks like this:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns='http://www.springframework.org/schema/beans' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:beans='http://www.springframework.org/schema/beans' xmlns:jaxws='http://cxf.apache.org/jaxws' xmlns:util='http://www.springframework.org/schema/util' xsi:schemaLocation='http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd'> <bean id="Sign_Response" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"> <constructor-arg> <map> <entry key="action" value="Signature UsernameToken Encrypt Timestamp"/> <entry key="user" value="myservicekey"/> <entry key="signaturePropFile" value="META-INF/plc-security.properties"/> <entry key="encryptionPropFile" value="META-INF/plc-security.properties"/> <entry key="encryptionUser" value="useReqSigCert"/> <entry key="signatureKeyIdentifier" value="DirectReference"/> <entry key="passwordCallbackClass" value="de.lmis.plc.core.rule.KeystorePasswordCallback"/> <entry key="signatureParts" value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body"/> <entry key="encryptionParts" value="{Element}{http://www.w3.org/2000/09/xmldsig#}Signature;{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body"/> <entry key="encryptionKeyTransportAlgorithm" value="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/> <entry key="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/> </map> </constructor-arg> </bean> <bean id="SecurityContextIn" class="org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingInterceptor"> <constructor-arg> <map> <entry key="action" value="Signature UsernameToken Encrypt Timestamp"/> <entry key="signaturePropFile" value="META-INF/plc-security.properties"/> <entry key="decryptionPropFile" value="META-INF/plc-security.properties"/> <entry key="passwordCallbackClass" value="de.myservice.KeystorePasswordCallback"/> </map> </constructor-arg> </bean> <jaxws:endpoint id='CoreService' address='http://localhost:8080/myservice/ws/CoreService' implementor='de.core.facade.CoreService'> <jaxws:properties> <beans:entry key="ws-security.ut.no-callbacks" value="true" /> </jaxws:properties> <jaxws:invoker> <bean class='org.jboss.wsf.stack.cxf.InvokerEJB3'/> </jaxws:invoker> <jaxws:inInterceptors> <ref bean="SecurityContextIn"/> </jaxws:inInterceptors> <jaxws:outInterceptors> <ref bean="Sign_Response"/> </jaxws:outInterceptors> </jaxws:endpoint> </beans>
The outInterceptor-config could not yet be tested, because the inInterceptor is not working.
Following the CXF-Stack User Guide I used the SubjectCreatingInterceptor where it is said that "Authentication and authorization will simply be delegated to the security domain configured for the endpoint." But it is not.
The UsernameToken is decrypted correctly, but it is not passed to the Securitydomain.
Here is an excerpt from the server-log:
17:11:58,401 DEBUG [org.apache.xml.security.utils.DigesterOutputStream] Pre-digested input: 17:11:58,401 DEBUG [org.apache.xml.security.utils.DigesterOutputStream] <o:UsernameToken xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" u:Id="uuid-0c7a4729-8a51-414b-ab05-b0039958f099-23"><o:Username>admin</o:Username><o:Password>password</o:Password></o:UsernameToken> 17:11:58,401 DEBUG [org.apache.xml.security.signature.Reference] Verification successful for URI "#uuid-0c7a4729-8a51-414b-ab05-b0039958f099-23" 17:11:58,402 DEBUG [org.apache.xml.security.signature.Manifest] The Reference has Type 17:11:58,402 DEBUG [org.apache.ws.security.TIME] Verify: total= 212, prepare-cert= 77, verify= 135 17:11:58,402 DEBUG [org.apache.xml.security.utils.ElementProxy] setElement("Transform", "null") 17:11:58,403 DEBUG [org.apache.xml.security.utils.ElementProxy] setElement("Transform", "null") 17:11:58,404 DEBUG [org.apache.xml.security.utils.ElementProxy] setElement("Transform", "null") 17:11:58,409 DEBUG [org.apache.ws.security.TIME] processHeader: total 686, prepare 19, handle 667 17:11:58,430 DEBUG [org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor-Time] Receive request: total= 2226 request preparation= 1511 request processing= 706 header, cert verify, timestamp= 9 17:11:58,430 DEBUG [org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor] WSS4JInInterceptor: exit handleMessage() 17:11:58,430 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor@4610c772 17:11:58,439 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Adding interceptor org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor$UltimateReceiverMustUnderstandInterceptor@3efa8cd6 to phase invoke 17:11:58,452 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Chain org.apache.cxf.phase.PhaseInterceptorChain@3ae7ec25 was modified. Current flow: receive [PolicyInInterceptor, EndpointAssociationInterceptor, AttachmentInInterceptor] pre-stream [CertConstraintsInterceptor] post-stream [StaxInInterceptor] read [ReadHeadersInterceptor, SoapActionInInterceptor, StartBodyInterceptor] pre-protocol [EnableOneWayDecoupledFaultInterceptor, SubjectCreatingInterceptor, MustUnderstandInterceptor] post-protocol [CheckFaultInterceptor, JAXBAttachmentSchemaValidationHack] unmarshal [URIMappingInterceptor, DocLiteralInInterceptor, SoapHeaderInterceptor] pre-logical [OneWayProcessorInterceptor] post-logical [WrapperClassInInterceptor] pre-invoke [SwAInInterceptor, HolderInInterceptor, SimpleAuthorizingInterceptor] invoke [ServiceInvokerInterceptor, UltimateReceiverMustUnderstandInterceptor] post-invoke [OutgoingChainInterceptor] 17:11:58,453 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor@49546e3a 17:11:58,453 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.jaxb.attachment.JAXBAttachmentSchemaValidationHack@257ef391 17:11:58,454 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.interceptor.URIMappingInterceptor@7796314d 17:11:58,455 DEBUG [org.apache.cxf.interceptor.URIMappingInterceptor] Invoking HTTP method POST 17:11:58,455 DEBUG [org.apache.cxf.interceptor.URIMappingInterceptor] URIMappingInterceptor can only handle HTTP GET, not HTTP POST 17:11:58,455 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.interceptor.DocLiteralInInterceptor@4588aeca 17:11:58,569 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.SoapHeaderInterceptor@108b7370 17:11:58,569 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.interceptor.OneWayProcessorInterceptor@3bd21ad9 17:11:58,570 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.WrapperClassInInterceptor@5ee0bb3d 17:11:58,586 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.SwAInInterceptor@1d74f93e 17:11:58,591 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.HolderInInterceptor@7424d274 17:11:58,592 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor@794a9ba6 17:11:58,592 DEBUG [org.apache.cxf.phase.PhaseInterceptorChain] Invoking handleMessage on interceptor org.apache.cxf.interceptor.ServiceInvokerInterceptor@5efabb19 17:11:58,824 TRACE [org.jboss.security.auth.login.XMLLoginConfigImpl] Begin getAppConfigurationEntry(MyRealm), size=12 17:11:58,824 TRACE [org.jboss.security.auth.login.XMLLoginConfigImpl] End getAppConfigurationEntry(MyRealm), authInfo=AppConfigurationEntry[]: [0] LoginModule Class: org.jboss.security.auth.spi.UsersRolesLoginModule ControlFlag: Anmeldemodul-Steuerflag: required Options: name=usersProperties, value=props/users.properties name=rolesProperties, value=props/roles.properties 17:11:58,839 TRACE [org.jboss.security.auth.spi.UsersRolesLoginModule] initialize 17:11:58,840 TRACE [org.jboss.security.auth.spi.UsersRolesLoginModule] Security domain: MyRealm 17:11:58,863 TRACE [org.jboss.security.auth.spi.UsersRolesLoginModule] Properties file=vfs:/D:/XXX/java/jboss-6.0.0.Final/server/default/conf/props/users.properties, defaults=null 17:11:58,866 DEBUG [org.jboss.security.auth.spi.UsersRolesLoginModule] Loaded properties, users=[admin, ...] 17:11:58,869 TRACE [org.jboss.security.auth.spi.UsersRolesLoginModule] Properties file=vfs:/D:/XXX/java/jboss-6.0.0.Final/server/default/conf/props/roles.properties, defaults=null 17:11:58,870 DEBUG [org.jboss.security.auth.spi.UsersRolesLoginModule] Loaded properties, users=[admin, ...] 17:11:58,870 TRACE [org.jboss.security.auth.spi.UsersRolesLoginModule] login 17:11:58,878 TRACE [org.jboss.security.auth.spi.UsersRolesLoginModule] Authenticating as unauthenticatedIdentity=null 17:11:58,878 DEBUG [org.jboss.security.auth.spi.UsersRolesLoginModule] Bad password for username=null 17:11:58,891 TRACE [org.jboss.security.auth.spi.UsersRolesLoginModule] abort : Invalid User 17:11:58,899 ERROR [org.jboss.webservices.integration.invocation.InvocationHandlerEJB3] Method invocation failed with exception: Invalid User:
In the beginning you can see the UsernameToken, which is decyrpted just fine.
Then the Ejb gets invoked and the Loginmodule is loaded it tries to use the unauthenticatedIdentity (which is null, because I did not specify one so no user has unauthenticated access).
Of course the authentication then fails for username=null.
One thing that bothers me is that the SubjectCreatingInterceptor is invoked in the pre-protocol-phase, long before the Loginmodule is even created.
Can this be right?
If you need any additional information (code, server-log, config-files, ...) just ask.
Many thanks,
Lars