I am trying to using Waffle 1.5 to implement single sign on for a service (not a web service) using pure java and waffle-jna.
I'm running this on Windows Server 2008R2 with ActiveDirectory configured to use Kerberos.
I looked at the method codetestAcceptSecurityToken() in WindowsAuthProviderTests.java for clues on how to do this.
What it looks like is that I need to send enough information to reconstruct the clientContext on the server side.
Sending the principal name and the token should be enough. However, I cannot get it to work.
Below is my code for the client and server.
Client Code:// Get the identity and credentials of the current user.
String spn = "HOST/
xyz.domain.com:8999";
IWindowsSecurityContext clientContext = WindowsSecurityContextImpl.getCurrent("Negotiate", spn);
String principalName = clientContext.getPrincipalName();
byte[] token = clientContext.getToken();
// Send principalName and token to remote server for SSO authentication...
Server Code:
============
// Have received principalName and token from client...
// Reconstruct client context.
String securityPackage = "Negotiate";
String spn = "HOST/
xyz.domain.com:8999";
IWindowsCredentialsHandle credHandle = new WindowsCredentialsHandleImpl(
principalName,
Sspi.SECPKG_CRED_OUTBOUND,
securityPackage
);
credHandle.initialize();
WindowsSecurityContextImpl clientContext = new WindowsSecurityContextImpl();
clientContext.setPrincipalName(principalName);
clientContext.setCredentialsHandle(credHandle.getHandle());
clientContext.setSecurityPackage(securityPackage);
clientContext.initialize(null, new SecBufferDesc(Sspi.SECBUFFER_TOKEN, credential.getToken()), spn);
// Create the Auth Provider
WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
IWindowsSecurityContext serverContext = null;
String connectionId = principalName + Thread.currentThread().getId();
do {
serverContext = provider.acceptSecurityToken(connectionId, clientContext.getToken(), securityPackage);
if (serverContext != null && serverContext.isContinue()) {
SecBufferDesc continueToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, serverContext.getToken());
clientContext.initialize(clientContext.getHandle(), continueToken, spn);
}
} while (clientContext.isContinue() || serverContext.isContinue());
When I run this code, the sever goes through the do/while loop ok the first time. At the end, clientContext.isContinue() is true and serverContext.isContinue() is true.
On the next pass through the loop, the call to provider.acceptSecurityToken() calls Secur32.INSTANCE.acceptSecurityToken(), which returns 0. At the end of the loop, clientContext.isContinue() is false but serverContext.isContinue() is still true. So it goes around the loop again.
Then on the third call to provider.acceptSecurityToken it throws a Win32Exception with rc = -
2146893048 which is SEC_E_INVALID_TOKEN.
Can somebody please tell me what I'm doing wrong?