Hi David I did a minor update to WSS4JInInterceptor to ensure that the 'best' principal is wrapped as a SecurityContext principal, when possible. This update does not change the fact all Principals are still available on the message for subsequent interceptors to check, it simply attempts not to set a Principal representing the encryption key which was used to encrypt UT as the 'main' Principal.
Hope Colm and others will be ok with this update. Can you please checkout 2.3.4-SNAPSHOT and verify it fixes the problem ? Thanks, Sergey On Tue, Apr 5, 2011 at 12:01 PM, David Zhang <[email protected]> wrote: > Hello Sergey, > > i think i found the cause of the problem. JBoss 6.0.0.Final comes with CXF > 2.3.1. However, i checked out the 2.3.3 tag and did a little bug fix. > > What do you think of it? Please tell me, if you will make a fix for 2.3.x, > then i would like to download the update. > > Please look at > org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.doResults() > > At the end of the method is a for-loop over the wssEngineResults. If > withCallbacks is false then the UsernameToken should be put in the message. > The Problem is, the first Principal found is not the UsernameTokenPrincipal > but the DerivedKeyPrincipal. This triggers creation of a security context > and breakes the for-loop. The second wssEngineResult would have been the > UsernameTokenPrincipal. > > I believe this is the reason why i receive the error message: > Security Token is not available on the current message > > Here is the patch i use. It seems to work for me. > > David > > protected void doResults(SoapMessage msg, String actor, SOAPMessage doc, > Vector wsResult, > boolean utWithCallbacks) throws SOAPException, XMLStreamException, > WSSecurityException { > /* > * All ok up to this point. Now construct and setup the security > result > * structure. The service may fetch this and check it. > */ > List<Object> results = > CastUtils.cast((List)msg.get(WSHandlerConstants.RECV_RESULTS)); > if (results == null) { > results = new Vector<Object>(); > msg.put(WSHandlerConstants.RECV_RESULTS, results); > } > WSHandlerResult rResult = new WSHandlerResult(actor, wsResult); > results.add(0, rResult); > > SOAPBody body = doc.getSOAPBody(); > > XMLStreamReader reader = StaxUtils.createXMLStreamReader(new > DOMSource(body)); > // advance just past body > int evt = reader.next(); > int i = 0; > while (reader.hasNext() && i < 1 > && (evt != XMLStreamConstants.END_ELEMENT || evt != > XMLStreamConstants.START_ELEMENT)) { > reader.next(); > i++; > } > msg.setContent(XMLStreamReader.class, reader); > String pwType = (String)getProperty(msg, "passwordType"); > if ("PasswordDigest".equals(pwType)) { > //CXF-2150 - we need to check the UsernameTokens > for (WSSecurityEngineResult o : CastUtils.cast(wsResult, > WSSecurityEngineResult.class)) { > Integer actInt = > (Integer)o.get(WSSecurityEngineResult.TAG_ACTION); > if (actInt == WSConstants.UT) { > WSUsernameTokenPrincipal princ > = > (WSUsernameTokenPrincipal)o.get(WSSecurityEngineResult.TAG_PRINCIPAL); > if (!princ.isPasswordDigest()) { > LOG.warning("Non-digest UsernameToken found, but > digest required"); > throw new > WSSecurityException(WSSecurityException.INVALID_SECURITY); > } > } > } > } > > if (!utWithCallbacks) { > for (WSSecurityEngineResult o : CastUtils.cast(wsResult, > WSSecurityEngineResult.class)) { > final Principal p = > (Principal)o.get(WSSecurityEngineResult.TAG_PRINCIPAL); > if (p instanceof WSUsernameTokenPrincipal) { > msg.put(PRINCIPAL_RESULT, p); > WSS4JTokenConverter.convertToken(msg, p); > SecurityContext sc = msg.get(SecurityContext.class); > if (sc == null || sc.getUserPrincipal() == null) { > msg.put(SecurityContext.class, > createSecurityContext(p)); > } > break; > } > } > } else { > for (WSSecurityEngineResult o : CastUtils.cast(wsResult, > WSSecurityEngineResult.class)) { > final Principal p = > (Principal)o.get(WSSecurityEngineResult.TAG_PRINCIPAL); > if (p != null) { > msg.put(PRINCIPAL_RESULT, p); > if (!utWithCallbacks) { > WSS4JTokenConverter.convertToken(msg, p); > } > SecurityContext sc = msg.get(SecurityContext.class); > if (sc == null || sc.getUserPrincipal() == null) { > msg.put(SecurityContext.class, > createSecurityContext(p)); > break; > } > } > } > } > } > > -----Ursprüngliche Nachricht----- > From: Sergey Beryozkin > Sent: Monday, April 04, 2011 1:50 PM > To: [email protected] > Cc: David Zhang > Subject: Re: UsernameToken JBoss Integration > > Sorry, that one is indeed needed for the encryption itself to succeed. > Can you try, for the sake of the test, send unencrypted UTs ? > > I don't recall if I had the test for the case when the body was also > encrypted, would have to check. > In meantime, you may want to try the following: > > - if UT passwords are not encrypted then simply register a CXF interceptor, > after WSS4JInInterceptor, extract a WSS4J token and use it to create the > Subject and then replace the existing SecurityContext on the message with > the new one - if you decide to follow this route then I can provide more > info on how existing CXF SecurityContext impls can be reused > - if it is not a WSDL-first case then register an > AbstractUsernameTokenAuthenticatingInterceptor implementation instead of > WSS4InInterceptor but configure it as usual, just do not provide a UT > callback > > Let us know how it goes > > Sergey > > On Mon, Apr 4, 2011 at 12:33 PM, David Zhang <[email protected]> wrote: > > > Hello, > > > > i still cannot get the AuthenticationInterceptor to work. > > > > The password callback is needed to retrieve the password for the private > > key. Otherwise the server cannot decrypt the SOAP Request. > > > > However, when the AuthenticationInterceptor is called in the pre-invoke > > Phase, the security token is null. > > see AbstractSecurityContextInInterceptor.handleMessage() > > > > Any ideas? > > > > David > > > > From: [email protected] > > Sent: Friday, April 01, 2011 7:38 AM > > To: [email protected] > > Subject: Re: UsernameToken JBoss Integration > > > > Hello Sergey, > > > > if i remove the password callback, i get another error message: > > General security error (WSSecurityEngine: Callback supplied no password > > for: myAlias) > > > > The keystore.properties file contains only the password for the keystore, > > not for the private key inside the keystore. Also i can not find a way to > > create a private key without password by the java keytool. > > > > Is there another way to provide the password besides the password > callback? > > Is there maybe a property in the keystore.properties file? I cannot find > a > > suitable property in this list: > > http://cxf.apache.org/docs/ws-securitypolicy.html > > > > This is the content of the keystore.properties. The ${}-parts are > replaced > > by maven with actual values: > > > > > > > > > org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin > > org.apache.ws.security.crypto.merlin.keystore.type=jks > > > org.apache.ws.security.crypto.merlin.keystore.password=${keystore.password} > > org.apache.ws.security.crypto.merlin.keystore.alias=${certificate.alias} > > org.apache.ws.security.crypto.merlin.file=${keystore.path} > > > > > > > > Thank you > > David > > > > -----Ursprüngliche Nachricht----- > > From: Sergey Beryozkin > > Sent: Thursday, March 31, 2011 10:21 PM > > To: [email protected] > > Subject: Re: UsernameToken JBoss Integration > > > > Hi - > > > > You don't need a password callback in this case. > > > > Cheers, Sergey > > > > On Thu, Mar 31, 2011 at 7:42 PM, David Zhang <[email protected]> > wrote: > > > > > Hi Sergey, > > > > > > thank you very much for taking the time to help me. > > > I have set the property you mentioned. Look, this is my configuration: > > > > > > > > > <jaxws:endpoint id="SecureServiceBean" > > > > > > address="/example-ejb/SecureService" > > > > > > implementor="com.example.SecureServiceBean"> > > > > > > <jaxws:invoker> > > > > > > <bean class="org.jboss.wsf.stack.cxf.InvokerEJB3" /> > > > > > > </jaxws:invoker> > > > > > > <jaxws:inInterceptors> > > > > > > > > > <bean class="com.example.AuthenticationInterceptor1"/> > > > > > > </jaxws:inInterceptors> > > > > > > <jaxws:properties> > > > > > > <entry key="ws-security.ut.no-callbacks" value="true" /> > > > > > > <!--<entry key="ws-security.validate.token" value="false" />--> > > > > > > <entry key="ws-security.signature.properties" > value="keystore.properties" > > > /> > > > > > > <entry key="ws-security.encryption.properties" > > value="keystore.properties" > > > /> > > > > > > <entry key="ws-security.callback-handler" > > > value="com.example.PasswordCallback" /> > > > > > > </jaxws:properties> > > > > > > </jaxws:endpoint> > > > > > > Where com.example.AuthenticationInterceptor1 extends > > > AbstractUsernameTokenInInterceptor. > > > This results in: > > > 12:01:12,770 ERROR > > > > > > [org.apache.cxf.interceptor.security.AbstractSecurityContextInInterceptor] > > > Security Token is not available on the current message > > > > > > Thanks > > > David > > > > > > > > > -----Ursprüngliche Nachricht----- > > > From: Sergey Beryozkin > > > Sent: Thursday, March 31, 2011 11:06 AM > > > To: [email protected] > > > Subject: Re: UsernameToken JBoss Integration > > > > > > Hi > > > > > > Please check this section: > > > > > > > > > > > > http://cxf.apache.org/docs/security.html#Security-WSSecurityUsernameTokenandCustomAuthentication > > > > > > In 2.3.x you have to set a "ws-security.ut.no-callbacks" property and > > this > > > will ensure AbstractUserNameTokenInterceptor can be used. > > > > > > Setting this property results in WSS4JInInterceptor duplicating WSS4J > > > specific UT into CXF specific UsernameToken which is what > > > AbstractUserNameTokenInterceptor is checking. > > > > > > Cheers, Sergey > > > > > > On Thu, Mar 31, 2011 at 8:42 AM, David Zhang <[email protected]> > > wrote: > > > > > > > > > > > Hello, > > > > > > > > > > > > > > > > i have a web service with symmetric binding and self-signed server > > > > certificate. > > > > > > > > I implemented a password callbackhandler for the password to the > > private > > > > key of the server. > > > > > > > > Now i want to add authentication with username token. So i added a > > > > supporting token to the ws security policy. > > > > > > > > > > > > > > > > To this point everything works fine. The server gets an encrypted > > request > > > > with a username token. > > > > > > > > My concern is that i do not want to do the authentication in my > > > > application. I want to integrate the username token with JBoss > > Security. > > > > > > > > > > > > > > > > So i followed these instructions: > > > > > > > > > > http://community.jboss.org/wiki/JBossWS-StackCXFUserGuide#Authentication_and_authorization > > > > > > > > However, it did not work. I used a debugger to check and i saw the > > > > authentication interceptor was created when my app was deployed but > it > > > was > > > > never called on a client request. > > > > > > > > > > > > > > > > Later i found this: > > > > > > > > > > http://svn.apache.org/repos/asf/cxf/tags/cxf-2.3.3/systests/ws-specs/src/test/java/org/apache/cxf/systest/ws/wssec10/server/SimpleSubjectCreatingInterceptor.java > > > > > > > > I implemented an interceptor following that example. I put a > breakpoint > > > on > > > > the createSubject method. It was never called. > > > > > > > > > > > > > > > > Then i followed this example: > > > > > > > > > > http://svn.apache.org/repos/asf/cxf/tags/cxf-2.3.3/systests/ws-specs/src/test/java/org/apache/cxf/systest/ws/wssec10/server/SimpleUsernameTokenInterceptor.java > > > > > > > > At least i know this interceptor was called. But it produced an error > > > > before the createSubject method was called. The error says: Security > > > Token > > > > is not available on the current message > > > > > > > > > > > > > > > > But this can not be true. Because then i removed the interceptor > > removed > > > > the property ws-security.ut.no-callbacks and on the next request my > > > password > > > > callbackhandler was called with the username i set on the client. > > > > > > > > > > > > > > > > Please, can anybody explain me what i am doing wrong? > > > > > > > > > > > > > > > > Thanks > > > > > > > > David > > > > > > > > > > > > > > > > > > > -- > > > Sergey Beryozkin > > > > > > Application Integration Division of Talend <http://www.talend.com> > > > http://sberyozkin.blogspot.com > > > > > > > > > > -- > > Sergey Beryozkin > > > > Application Integration Division of Talend <http://www.talend.com> > > http://sberyozkin.blogspot.com > > > > > > -- > Sergey Beryozkin > > Application Integration Division of Talend <http://www.talend.com> > http://sberyozkin.blogspot.com > -- Sergey Beryozkin Application Integration Division of Talend <http://www.talend.com> http://sberyozkin.blogspot.com
