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

Reply via email to