Question

I am using Waffle for an SSO solution in my web-app.

Everything works fine but I would like to modify some functionality slightly:

Currently, if a user is not connected to the domain the SSO fails and opens a little authorization dialog:

enter image description here

The windows authorization requires the user name formatted like Domain\Username but most of my users will not know to add the domain in front of their username. So I would like to provide a default domain name if one is not specified.

I found a waffle function that I can override which will give me access to the decoded authentication token, I added a println to the waffle function and it shows the username in plain text (either with or without the domain depending on what is typed in the dialog):

public IWindowsSecurityContext acceptSecurityToken(String connectionId, byte[] token, String securityPackage) {

    // I can see the passed username in the logs with this
    System.out.println(new String(token));

    // I don't understand any of the JNA stuff below this comment:
    IWindowsCredentialsHandle serverCredential = new WindowsCredentialsHandleImpl(
            null, Sspi.SECPKG_CRED_INBOUND, securityPackage);
    serverCredential.initialize();

    SecBufferDesc pbServerToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
    SecBufferDesc pbClientToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, token);

    NativeLongByReference pfClientContextAttr = new NativeLongByReference();

    CtxtHandle continueContext = _continueContexts.get(connectionId);

    CtxtHandle phNewServerContext = new CtxtHandle();
    int rc = Secur32.INSTANCE.AcceptSecurityContext(serverCredential.getHandle(), 
            continueContext, pbClientToken, new NativeLong(Sspi.ISC_REQ_CONNECTION), 
            new NativeLong(Sspi.SECURITY_NATIVE_DREP), phNewServerContext, 
            pbServerToken, pfClientContextAttr, null);

    WindowsSecurityContextImpl sc = new WindowsSecurityContextImpl();
    sc.setCredentialsHandle(serverCredential.getHandle());
    sc.setSecurityPackage(securityPackage);
    sc.setSecurityContext(phNewServerContext);

    switch (rc)
    {
        case W32Errors.SEC_E_OK:
            // the security context received from the client was accepted
            _continueContexts.remove(connectionId);
            //  if an output token was generated by the function, it must be sent to the client process
            if (pbServerToken != null 
                    && pbServerToken.pBuffers != null
                    && pbServerToken.cBuffers.intValue() == 1 
                    && pbServerToken.pBuffers[0].cbBuffer.intValue() > 0) {
                sc.setToken(pbServerToken.getBytes());
            }
            sc.setContinue(false);
            break;
        case W32Errors.SEC_I_CONTINUE_NEEDED:
            // the server must send the output token to the client and wait for a returned token
            _continueContexts.put(connectionId, phNewServerContext);
            sc.setToken(pbServerToken.getBytes());
            sc.setContinue(true);
            break;
        default:
            sc.dispose();
            WindowsSecurityContextImpl.dispose(continueContext);
            _continueContexts.remove(connectionId);
            throw new Win32Exception(rc);
    }

    return sc;
}

That whole function is from the Waffle API I only added the println at the beginning.

The passed username prints in plain text inside this token between a bunch of random byte chars (ÉsR=ÍtÍö?æ¸+Û-).

I am admittedly in very far over my head with JNA and java in general but I thought that because I can see the username here there must be a way to prepend the domain name to the username part of this token? I could be wrong.

My other idea was to add the domain to the pbClientToken that is created from the raw byte[] token this method is passed.

The pbClientToken is a JNA Structure object derivative. It has the Stucture method writeField which looked promising but I can't seem to figure out what field I should write. The Structure.getFields method doesn't seem to be available from pbClientToken.

I was hoping that this was a simple problem for someone more familiar with byte[] processing or JNA.

Was it helpful?

Solution

You cannot do this. What happens behind this dialog is a call to LogonUser on the user's machine, which gives you a ticket, which is then sent to the server. Unfortunately the server is not in the same domain, so even if you manage to extract the username it's completely useless.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top