1

I am working on true SSO in Java application running on Windows 10. My application already has Kerberos auth using Java's GSSAPI (but it obviously does not work on any modern Windows, especially with strict security policies and domain users), so I would like to replace current authorization system with Waffle with minimal implications to overall app design - which I think should be possible if I can get KerberosTicket instance somehow. I am struggling writing this functionality, so far I managed to request some token, but I don't really know what this token is, it does not match Kerberos ticket format. Here is my (actually more like found online code):

public byte[] getServiceTicketSSPI() {
    final String securityPackage = "Kerberos";
    final String targetName = "<disclosed>";
    IWindowsCredentialsHandle clientCredentials = null;
    WindowsSecurityContextImpl clientContext = null;
    final String currentUser = WindowsAccountImpl.getCurrentUsername();
    try {
        clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);                               
        clientCredentials.initialize();
        // initial client security context
        clientContext = new WindowsSecurityContextImpl();
        clientContext.setPrincipalName(currentUser);
        clientContext.setCredentialsHandle(clientCredentials);
        clientContext.setSecurityPackage(securityPackage);
        final Sspi.SecBufferDesc continueToken = null;
        do {
            if(debug)
                System.out.println("Using target name: " + targetName);
            clientContext.initialize(clientContext.getHandle(), continueToken, targetName);
        } while(clientContext.isContinue());

        return clientContext.getToken();
    } finally {
        if (clientContext != null)
            clientContext.dispose();
        if (clientCredentials != null)
            clientCredentials.dispose();
    }
}

To be fair I am not even sure if SSPI allows me to actually see real ticket. Am I even going in right direction with this snippet? I will be really happy so see any clues as to what should I do. It would be perfect to have KerberosTicket instance in the end.

Chlorek
  • 138
  • 7
  • Your function is returning a token, not a ticket – FlyingSheep Jul 06 '18 at 12:53
  • Similar to your situation, we have an existing JGSS client and JGSS based Server. We have been able to extend the client to optionally use SSPI via Waffle instead of JGSS with code similar to yours above. The SSPI / Waffle code produces Kerberos tokens that are accepted by the pure JGSS backend, and is able to validate tokens returned from the JGSS Server. i.e. the SSPI and GSS clients are (in our case) interchangeable. So as far as I can see, your snippet is heading in the right direction. – FlyingSheep Jul 06 '18 at 13:01
  • If the token produced by your code is much smaller than that produced by GSS, maybe you have the SPN (targetName) wrong; at least that was the first mistake we made. – FlyingSheep Jul 06 '18 at 13:04

1 Answers1

0

Below are the steps to do Single Sign On using Waffle for standalone Java Client without using server.

Create client credentials Get service ticket using initializeSecurityContext of WindowsSecurityContextImpl. Get WindowsIdentity using accessSecurityContext of WindowsAuthProviderImpl Original link https://exceptionshub.com/getting-kerberos-service-ticket-using-waffle-in-java.html

For client-server sso, you should follow https://code.dblock.org/2010/04/08/pure-java-waffle.html The code below depicts the standalone java sso using kerberos.

import com.sun.jna.platform.win32.Sspi;
import waffle.windows.auth.IWindowsCredentialsHandle;
import waffle.windows.auth.IWindowsIdentity;
import waffle.windows.auth.IWindowsSecurityContext;
import waffle.windows.auth.impl.WindowsAccountImpl;
import waffle.windows.auth.impl.WindowsAuthProviderImpl;
import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
import waffle.windows.auth.impl.WindowsSecurityContextImpl;

public class KerberosSingleSignOn {
  public static void main() {
    try {
      System.out.println(getWindowsIdentity().getFqn());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static IWindowsIdentity getWindowsIdentity() throws Exception {
    try {
      byte[] kerberosToken = getServiceTicketSSPI();
      WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
      IWindowsSecurityContext securityContext = provider
        .acceptSecurityToken("client-connection", kerberosToken, "Kerberos");
      return securityContext.getIdentity();
    }
    catch (Exception e) {
      throw new Exception("Failed to process kerberos token");
    }
  }

  public static byte[] getServiceTicketSSPI() throws Exception {
    final String securityPackage = "Kerberos";
    IWindowsCredentialsHandle clientCredentials = null;
    WindowsSecurityContextImpl clientContext = null;
    final String currentUser = WindowsAccountImpl.getCurrentUsername();
    try {
      clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
      clientCredentials.initialize();
      // initial client security context
      clientContext = new WindowsSecurityContextImpl();
      clientContext.setCredentialsHandle(clientCredentials.getHandle());
      /*OR 
       clientContext.setCredentialsHandle(clientCredentials);
       */
      clientContext.setSecurityPackage(securityPackage);
      final Sspi.SecBufferDesc continueToken = null;
      do {
        System.out.println("Using current username: " + currentUser);
        clientContext.initialize(clientContext.getHandle(), continueToken, currentUser);
      }
      while (clientContext.isContinue());

      return clientContext.getToken();
    }
    catch (Exception e) {
      throw new Exception("Failed to process kerberos token");
    }
    finally {
      if (clientContext != null)
        clientContext.dispose();
      if (clientCredentials != null)
        clientCredentials.dispose();
    }
  }
}
  • I get `com.sun.jna.platform.win32.Win32Exception: The token supplied to the function is invalid` exception – agad Feb 22 '22 at 11:45