Hi all,

I'm wrestling with a problem getting my CXF implementation working with a 
WCF-based web service that's using wsHttpBindings and SPNEGO/Kerberos 
authentication.​​  I've tried several approaches that fail at different points 
for different reasons that I'm trying to untangle, but the one below seems 
closest (the "{...}" strings are deliberately-removed content for this post):​

        ​
System.setProperty("java.security.auth.login.config", 
"C:\\temp\\apache-cxf-3.3.0\\login.conf");
        System.setProperty("java.security.krb5.conf", 
"C:\\temp\\apache-cxf-3.3.0\\krb5.ini");
        // System.setProperty("sun.security.krb5.debug", "true");​

​URL wsdl = new 
URL("http://{...}/WebServices​​/AgentInventoryService.svc?wsdl";);
        QName serviceName
                = new QName("{...}/AgentInventory", "AgentInventoryService");
        AgentInventoryService service = new AgentInventoryService(wsdl, 
serviceName);
        IAgentInventoryService iAgentInventoryService = 
service.getWSHttpBindingIAgentInventoryService();
        Client client = ClientProxy.getClient(iAgentInventoryService);

        client.getRequestContext().put("ws-security.kerberos.jaas.context", 
"CXFClient");
        client.getRequestContext().put("ws-security.kerberos.spn", 
"krbtgt/{...}");
        client.getRequestContext().put("ws-security.callback-handler",
                new NamePasswordCallbackHandler("{...}", "{...}"));
        client.getRequestContext().put("ws-security.spnego.client.action", new 
XRMSpnegoClientAction());

        HTTPConduit httpConduit = (HTTPConduit) client.getConduit();

        AuthorizationPolicy authorization = new AuthorizationPolicy();
        authorization.setUserName("{...}");
        authorization.setPassword("{...}");
        authorization.setAuthorizationType(HttpAuthHeader.AUTH_TYPE_NEGOTIATE);
        authorization.setAuthorization("CXFClient");

        httpConduit.setAuthorization(authorization);

        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        httpClientPolicy.setConnectionTimeout(36000);
        httpClientPolicy.setAllowChunking(false);
        httpClientPolicy.setReceiveTimeout(32000);

        httpConduit.setClient(httpClientPolicy);

        iAgentInventoryService.getAgentUserByAgentId("1");


The XRMSpnegoClientAction is custom, lifted from a post I found somewhere, and 
is this:


class XRMSpnegoClientAction implements SpnegoClientAction {
    private static final Logger LOG = 
LoggerFactory.getLogger(DefaultSpnegoClientAction.class);
    private String serviceName;
    private GSSContext secContext;
    private boolean mutualAuth;
    private boolean isUsernameServiceNameForm;

    public void setMutualAuth(boolean mutualAuthentication) {
        this.mutualAuth = mutualAuthentication;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public byte[] run() {
        try {
            GSSManager gssManager = GSSManager.getInstance();
            Oid oid = new Oid("1.3.6.1.5.5.2");

            GSSName gssService = gssManager.createName(serviceName, 
GSSName.NT_USER_NAME);
            secContext = gssManager.createContext(gssService, oid, null, 
GSSContext.DEFAULT_LIFETIME);

            secContext.requestMutualAuth(mutualAuth);
            secContext.requestCredDeleg(Boolean.FALSE);

            byte[] token = new byte[0];
            return secContext.initSecContext(token, 0, token.length);
        } catch (GSSException e) {
            e.printStackTrace();
        }

        return null;
    }

    public GSSContext getContext() {
        return this.secContext;
    }

    public void setUserNameServiceForm(boolean isUsernameServiceNameForm) {
        this.isUsernameServiceNameForm = isUsernameServiceNameForm;
    }
}


Sadly, I'm not entirely clear on what this is doing, but without it I get 
Kerberos errors about the server not being found.  With it, I seem to pass the 
pre-auth, but then some other authentication fails when I get down to the 
actual iAgentInventoryService.getAgentUserByAgentId("1") call.


It looks like my HttpConduit and AuthorizationPolicy that I think I'm attaching 
to the Client aren't being used, so maybe I'm attaching them wrong...?


This may jog the memory of some folks who've been on here for many years, as I 
wrestled with the same problem in a different way back then, and posted here 
for help.  Colm was able to bring me a good way toward the goal, but we 
couldn't get over the final hurdle, and I had to let it go.  I'm back at it 
now, hoping the latest release would get me over previous hurdles.


Last note:  I have confirmed successful Kerberos ticket negotiation with this 
code:


        System.setProperty("java.security.auth.login.config", 
"C:\\temp\\apache-cxf-3.3.0\\login.conf");
        System.setProperty("java.security.krb5.conf", 
"C:\\temp\\apache-cxf-3.3.0\\krb5.ini");
        // System.setProperty("sun.security.krb5.debug", "true");

        LoginContext lc = new LoginContext("CXFClient", new 
NamePasswordCallbackHandler("{...}", "{...}"));
        lc.login();

        Subject subject = lc.getSubject();
        Set<Principal> principals = subject.getPrincipals();
        Set<Object> credentials = subject.getPrivateCredentials();
        System.out.println("OK: " + principals);
        System.out.println("OK: " + credentials);

Is there anything obviously wrong with what I'm doing here, or is there a 
better approach that I might try for this type of integration?  It's been a 
long and painful week trying to make this work. ;)


Thanks,

Mark



Reply via email to