Hi Colm, I don’t see any obvious errors, but I’ll step through and describe what I’m seeing. You asked for the issueToken(…) call, which is down beneath the “-----“ break below if you want to skip to it, but I’m going to step through a few earlier steps and show a few things first, just in case there’s anything in there that’s helpful.
So the call to issue(…) creates this XML request successfully in AbstractSTSClient: https://gist.github.com/anonymous/adaad47ef5643686dade. AbstractSTSClient then makes a call to CXF’s ClientImpl.invoke(…), and ClientImpl’s doInvoke ultimately is passed this: * ClientCallback - null * BindingOperationInfo - [BindingOperationInfo: {http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl}RequestSecurityToken] * params - One DOMSource object, with a single node: [wst:RequestSecurityToken: null] * context (below*) * Exchange - null ( * context: {ResponseContext={}, RequestContext={ws-security.sts.client=org.apache.cxf.ws.security.trust.STSClient@423b8ab3, ws-security.spnego.client.action=com.nexidia.neat.test.Tester$XRMSpnegoClientAction@530f0fbd, ws-security.callback-handler=org.apache.cxf.interceptor.security.NamePasswordCallbackHandler@1d26be5, ws-security.kerberos.spn=RestrictedKrbHost/nxesideploy4, SOAPAction=http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT, ws-security.kerberos.jaas.context=spnego-client}} ) It sets up everything without complaint, then gets to the point where it calls chain.doIntercept(message) with this message: {org.apache.cxf.invocation.context={ResponseContext={}, RequestContext={ws-security.sts.client=org.apache.cxf.ws.security.trust.STSClient@423b8ab3, ws-security.spnego.client.action=com.nexidia.neat.test.Tester$XRMSpnegoClientAction@530f0fbd, ws-security.callback-handler=org.apache.cxf.interceptor.security.NamePasswordCallbackHandler@1d26be5, ws-security.kerberos.spn=RestrictedKrbHost/nxesideploy4, SOAPAction=http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT, ws-security.kerberos.jaas.context=spnego-client}}, ws-security.spnego.client.action=com.nexidia.neat.test.Tester$XRMSpnegoClientAction@530f0fbd, org.apache.cxf.service.model.MessageInfo=[MessageInfo INPUT: {http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl}RequestSecurityTokenMsg], ws-security.callback-handler=org.apache.cxf.interceptor.security.NamePasswordCallbackHandler@1d26be5, ws-security.kerberos.spn=RestrictedKrbHost/nxesideploy4, org.apache.cxf.client=true, org.apache.cxf.message.inbound=false, ws-security.kerberos.jaas.context=spnego-client, org.apache.cxf.binding.soap.SoapVersion=org.apache.cxf.binding.soap.Soap12@16d9e492, ws-security.sts.client=org.apache.cxf.ws.security.trust.STSClient@423b8ab3, SOAPAction=http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT, org.apache.cxf.service.model.BindingMessageInfo=org.apache.cxf.service.model.BindingMessageInfo@3b2d38f6, Content-Type=application/soap+xml, org.apache.cxf.transport.Conduit=conduit: class org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit368491732target: http://nxesideploy4/NxIA/WebServices/AgentInventoryService.svc} PhaseInterceptor gets it next, and it iterates over its interceptors: PolicyOutInterceptor intercepts without complaint, then MapAggregatorImpl, SoapHeaderOutFilterInterceptor, SecurityVerificationOutInterceptor, SoapPreProtocolOutInterceptor, MessageSenderInterceptor, and then it hits SpnegoContextTokenOutInterceptor, where it gets caught. ----- In SpnegoContextTokenOutInterceptor.issueToken(…), then, SpnegoTokenContext in the wss4j library successfully authenticates to the TGT, gets the token successfully, and then says it’s successfully retrieved a service ticket before control goes back to SpnegoContextTokenOutInterceptor. That guy then hits the “initiating ws-trust exchange”-commented part of the code, where it sets up the client successfully, and then it makes this call: SecurityToken tok = client.requestSecurityToken(s, Base64.encode(spnegoToken.getToken())); All of the params there look good (the token’s there, and s looks right), but the call to requestSecurityToken then brings us full circle back to the AbstractSTSClient.issue(…) call, and that’s where we’re stuck. Here’s my test code source, if it helps: https://gist.github.com/anonymous/0e9907d427148c5f5478. Thanks again for your help with this! All best, Mark On Jan 27, 2015, at 7:19 AM, Colm O hEigeartaigh <[email protected]<mailto:[email protected]>> wrote: Hi Mark, The SpnegoContextTokenOutInterceptor is never reaching the point where tok is non-null, b/c it’s trying to get tokenID from the message first and is failing there. I did set a breakpoint at the line where it’s trying to get the token ID from the message (line 59 in 2.7.14), though, and was able to create a new SecurityToken with a dummy ID, and then execute your test code against that with no problem. After running it, I pulled the token ID and token from both the Exchange and the TokenStore without issue. If the tokenID is null, then it tries to get a new token. So something is clearly going wrong with this. Could you try debugging through the call to "issueToken" and see where the error is being thrown? Colm. On the security policy, I’m not sure how to tell … can you point me in the right direction? Thanks for the help! Mark On Jan 26, 2015, at 6:41 AM, Colm O hEigeartaigh <[email protected]<mailto:[email protected]>> wrote: Can you see in the SpnegoContextTokenOutInterceptor via a debugger whether it is actually storing the message ID successfully? message.getExchange().put(SecurityConstants.TOKEN_ID, tok.getId()); NegotiationUtils.getTokenStore(message).add(tok); If it is then it might be a problem with the security policy. I've seen something similar with WS-MEX before. Can you post the exact security policy here? Colm. On Fri, Jan 23, 2015 at 6:31 PM, Mark Durant <[email protected]<mailto:[email protected]>> wrote: Hi all, I’ve been trying to create and test a CXF client that’s consuming a web service secured with SPNEGO/Kerberos authentication on a Windows 2008 server. I’m neither a Windows nor a security guru by any stretch of the imagination, but mainly following Groovy Tom’s advice at http://groovyjava-tom.blogspot.com/2012/01/cxf-and-ms-crm-2011.html, I believe I’ve gotten very close to making this work. I’ve hit a snag near the end, though, that I’m hoping someone here can provide me some insight into. I’ve created the web service client from the WSDL using CXF without issue, and my test code is essentially wrapping the basics there with what I found in the blog post. Here’s the code: System.setProperty("java.security.auth.login.config", "/home/developer/apache-cxf-2.7.14/login.conf"); System.setProperty("java.security.krb5.conf", "/home/developer/apache-cxf-2.7.14/krb5.conf"); System.setProperty("sun.security.krb5.debug", "true"); AgentInventoryService service = new AgentInventoryService(); IAgentInventoryService port = service.getWSHttpBindingIAgentInventoryService(); Client client = ClientProxy.getClient(port); client.getRequestContext().put("ws-security.kerberos.jaas.context", "spnego-client"); client.getRequestContext().put("ws-security.kerberos.spn", "RestrictedKrbHost/nxesideploy4"); client.getRequestContext().put("ws-security.spnego.client.action", new XRMSpnegoClientAction()); Bus bus = ((EndpointImpl) client.getEndpoint()).getBus(); PolicyInterceptorProviderRegistry pipr = bus.getExtension(PolicyInterceptorProviderRegistry.class); pipr.register(new XRMAuthPolicyProvider()); CallbackHandler callbackHandler = new NamePasswordCallbackHandler(kuser, kpass); client.getRequestContext().put("ws-security.callback-handler", callbackHandler); STSClient sts = new STSClient(bus); sts.setFeatures(Arrays.asList(new Feature() { @Override public void initialize(Server server, Bus bus) { } @Override public void initialize(Client client, Bus bus) { bus.getProperties().put("soap.no.validate.parts", true); } @Override public void initialize(InterceptorProvider interceptorProvider, Bus bus) { } @Override public void initialize(Bus bus) { } })); client.getRequestContext().put("ws-security.sts.client", sts); AgentUser agentUser = new AgentUser(); agentUser.setAgentId("007-DEF"); agentUser.setFirstName("Mark"); agentUser.setLastName("Durant"); Integer result = port.save(agentUser); System.out.println("result = " + result); I’ve tested my krb5.conf with kinit, and it’s working fine. With Kerberos debugging on, I can see that that part of the application is working, too. After getting that token, though, the library seems to gets caught in a loop, continually reaching out to the domain controller for a new token. The looping starts in SpnegoContextTokenOutInterceptor's handleMessage(SoapMessage) call: It tries to get the " ws-security.token.id" from the message, but it's not there; so seeing that it has a null token, it requests a security token from the STSClient, and that request gets caught up in the same interceptor where the ws-security.token.id is null, and it just keeps rolling from there under I get a StackOverflow error. Here’s the stack trace: Jan 23, 2015 12:46:23 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging WARNING: Interceptor for { http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl}SecurityTokenService#{http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl}RequestSecurityToken has thrown exception, unwinding now org.apache.cxf.interceptor.Fault: General security error (An error occurred in trying to obtain a TGT: java.lang.StackOverflowError at java.net.PlainDatagramSocketImpl.receive0(Native Method) at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:145) at java.net.DatagramSocket.receive(DatagramSocket.java:786) at sun.security.krb5.internal.UDPClient.receive(NetClient.java:207) at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:386) at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:339) at java.security.AccessController.doPrivileged(Native Method) at sun.security.krb5.KdcComm.send(KdcComm.java:323) at sun.security.krb5.KdcComm.send(KdcComm.java:219) at sun.security.krb5.KdcComm.send(KdcComm.java:191) at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:319) at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364) at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:721) at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:580) at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at javax.security.auth.login.LoginContext.invoke(LoginContext.java:784) at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203) at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698) at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:695) at javax.security.auth.login.LoginContext.login(LoginContext.java:594) at org.apache.ws.security.spnego.SpnegoTokenContext.retrieveServiceTicket(SpnegoTokenContext.java:121) at org.apache.ws.security.spnego.SpnegoTokenContext.retrieveServiceTicket(SpnegoTokenContext.java:89) at org.apache.ws.security.spnego.SpnegoTokenContext.retrieveServiceTicket(SpnegoTokenContext.java:70) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.issueToken(SpnegoContextTokenOutInterceptor.java:114) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.handleMessage(SpnegoContextTokenOutInterceptor.java:73) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.handleMessage(SpnegoContextTokenOutInterceptor.java:46) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:572) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:481) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335) at org.apache.cxf.ws.security.trust.AbstractSTSClient.issue(AbstractSTSClient.java:855) at org.apache.cxf.ws.security.trust.STSClient.requestSecurityToken(STSClient.java:62) at org.apache.cxf.ws.security.trust.STSClient.requestSecurityToken(STSClient.java:56) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.issueToken(SpnegoContextTokenOutInterceptor.java:134) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.handleMessage(SpnegoContextTokenOutInterceptor.java:73) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.handleMessage(SpnegoContextTokenOutInterceptor.java:46) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:572) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:481) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335) at org.apache.cxf.ws.security.trust.AbstractSTSClient.issue(AbstractSTSClient.java:855) at org.apache.cxf.ws.security.trust.STSClient.requestSecurityToken(STSClient.java:62) at org.apache.cxf.ws.security.trust.STSClient.requestSecurityToken(STSClient.java:56) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.issueToken(SpnegoContextTokenOutInterceptor.java:134) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.handleMessage(SpnegoContextTokenOutInterceptor.java:73) at org.apache.cxf.ws.security.policy.interceptors.SpnegoContextTokenOutInterceptor.handleMessage(SpnegoContextTokenOutInterceptor.java:46) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) That repeats until the application dies. This is all done with CXF 2.7.14. I tried it with 3.0.3 originally, and hit the same problem, but backed down to 2.7 since that was where the blog post was successful. If there’s anything else I can provide that might give a hint about what’s happening, please let me know. Thanks, Mark -- Colm O hEigeartaigh Talend Community Coder http://coders.talend.com -- Colm O hEigeartaigh Talend Community Coder http://coders.talend.com<http://coders.talend.com/>
