This page looks best with JavaScript enabled

Waffle : Windows Single Sign On

 ·  β˜• 3 min read  ·  ✍️ Dinesh

Last week, I was working on an application where I had to do LDAP authentication. My cmpany has been using a very old jar file that had the required code for authenticating and authorizing users. There were two problems for me.

  1. I had to revisit the documentation on LDAP setting in Jboss 4 and figure how to do the set up. Making changes in login-config.xml etc.

  2. My new application is using Spring-boot, which comes with built in tomcat libraries. I had to either find some documentation on Timcat with Spring boot 4 or build the app as war and deploy in Jboss 7 and not Jboss 4, which means going over documentation and tutorial.

What is waffle?

While trying to figure out a lazy way of doing things, I ran into Waffle project. WAFFLE is a native Windows Authentication Framework consisting of two C# and Java libraries that perform functions related to Windows authentication, supporting Negotiate, NTLM and Kerberos. Waffle also includes libraries that enable drop-in Windows Single Sign On for popular Java web servers, when running on Windows. While Waffle makes it ridiculously easy to do Windows Authentication in Java, on Windows, Waffle does not work on *nix. In Short, if a user logs into his company computer, he would be authenticating over LDAP to make sure that he is authorized to use the computer. Waffle gives you an opportunity to make use of the exixsting infrastrutuce and help you authenticate and authorzie the user.

Set Up::

To use waffle in java, we just need to add the maven dependency:

<properties>
<waffle.version>1.5</waffle.version>
</properties>`

<dependency>

<groupId>com.github.dblock.waffle</groupId>

<artifactId>waffle-jna</artifactId>

<version>${waffle.version}</version>

</dependency>

<dependency>
 <groupId> net.java.dev.jna</<wbr />groupId>
 <artifactId> platform</<wbr />artifactId>
 <version>3.5.2</version>
 </dependency>  

Create a new instance of waffle.windows.auth.impl.WindowsAuthProviderImpl.

Here are a couple of scenario that you can do without any nasty setup in Java, Jboss, Tomcat etc.

Scenario 1: Logon a user and get his domain and local groups

This calls Win32-LogonUser, checks the user token and extracts all local domain information.

IWindowsAuthProvider prov = new WindowsAuthProviderImpl()
IWindowsIdentity identity = prov.logonUser("userName", "pwd")
System.out.println("User identity: " + identity.getFqn())
for(IWindowsAccount group : identity.getGroups()) {
System.out.println(" " + group.getFqn() + " (" + group.getSidString() + ")")
}

Output::


User identity: acnna\darora
acnna\\None (S-1-5-21-42300245183-42300245183-3597729351-513)
Everyone (S-1-1-0)
acnna\\HomeUsers (S-1-5-21-42300245183-42300245183-3597729351-2418)
BUILTIN\Administrators (S-1-5-32-544)
BUILTIN\Users (S-1-5-32-545)
NT AUTHORITY\NETWORK (S-1-5-2)

Scenario 2: Active directory: get the list of trusted domains

IWindowsAuthProvider prov = new WindowsAuthProviderImpl()
IWindowsDomain[] domains = prov.getDomains()
for(IWindowsDomain domain : domains) {
System.out.println(domain.getFqn() + ": " + domain.getTrustDirectionString())
}

Output::

Scenario 3:: Is computer active on a domain?


IWindowsAuthProvider prov = new WindowsAuthProviderImpl()
IWindowsComputer computer = prov.getCurrentComputer()
System.out.println(computer.getComputerName())
System.out.println(computer.getJoinStatus())
System.out.println(computer.getMemberOf())

For systems that run both with and without active directory you need to programmatically figure out whether a computer is joined to a domain or a workgroup. If it’s joined to a domain or a workgroup you want to know what domain the computer is joined to.

Scenario 4: Negotiate Single Sign on

This lets both client and server side to negotatite the sign on protocol. The code below, gets the token which can be shared between client and server and be used to lookup its domains.


String securityPackage = "Negotiate"
// client credentials handle
IWindowsCredentialsHandle clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage)
clientCredentials.initialize()
// initial client security context
WindowsSecurityContextImpl clientContext = new WindowsSecurityContextImpl()
clientContext.setPrincipalName(Advapi32Util.getUserName())
clientContext.setCredentialsHandle(clientCredentials.getHandle())
clientContext.setSecurityPackage(securityPackage)
clientContext.initialize()
// accept on the server
WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl()
IWindowsSecurityContext serverContext = null
do
{
if (serverContext != null) {
// initialize on the client
SecBufferDesc continueToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, serverContext.getToken())
clientContext.initialize(clientContext.getHandle(), continueToken)
}
// accept the token on the server
serverContext = provider.acceptSecurityToken(clientContext.getToken(), securityPackage)
} while (clientContext.getContinue() || serverContext.getContinue()) `

System.out.println(serverContext.getIdentity().getFqn())

for (IWindowsAccount group : serverContext.getIdentity().getGroups()) {

System.out.println(&#8221  &#8221  + group.getFqn())

}

serverContext.dispose()

clientContext.dispose()

clientCredentials.dispose()

~Ciao

Share on
Support the author with

Dinesh Arora
WRITTEN BY
Dinesh
Developer