Impersonating in Apache/JNA

Oct 19, 2010 at 5:40 AM


I'm using Waffle for performing Window User Authentication using Waffle on Tomcat with NegotiateAuthenticator and it works fine. I have a web service which receives a call and in Java I can see GenericPrincipal with the user identity.

The next step for us is to propagate the user token onto a web service call so as to impersonate the calling user to another web service. I read this post ( and it says that this can be done and there is API for that. I do see IWindowsSecurityContext implementation which has impersonate() method but I cannot not invoke it because there is no instance of IWindowsSecurityContext available after the user has been authenticated and GenericPrinciple has been set into the context.

All I have after authentication is a GenericWindowsPrincipal object. The NegotiateAuthenticator did have a IWindowsSecurityContext in its hand in the authenticate() method, but once it exited I don't have access to it as it extracts some properties and stores them in GenericWindowsPrincipal without back-references.

Is there a way to get IWindowsSecurityContext from the thread on which the authenticated request is executing? If this is not possible without modifying the source code, would it work if I add a property to NegotiateAuthenticator to impersonate the user and use the context inside of the authenticate() method to perform impersonation?

Any help or an example of impersonation using waffle would be greatly appreciated.



Oct 19, 2010 at 12:43 PM

The idea is that we would implement this in Waffle as a feature. You need access to the security context after the logon to do impersonation, and this context is disposed of. By the time it reached your code, it doesn't exist.

Tomcat valves, such as the NegotiateAuthenticator, don't wrap the entire request., at least not easily When you do impersonatation it's very important to revert when the request terminates (successfully or on error). Therefore the NegotiateAuthenticator is a poor choice to get started. Switch to the NegotiateSecurityFilter.

In the code of NegotiateSecurityFilter you have this:

try {
 NegotiateRequestWrapper requestWrapper = new NegotiateRequestWrapper(request, windowsPrincipal);	
 chain.doFilter(requestWrapper, response);
} finally {

You can call windowsIdentity.impersonate() in the try block, which gives you an impersonation context, then revert it in the finally block. The filter chain's doFilter is what actually serves the request. 
That's the basic idea. This impersonates on the current Windows thread. But more work probably needs to be done to figure out how Java threads relate to Windows threads, which is the part I know nothing about.
Oct 20, 2010 at 1:14 AM

Thanks for a quick reply. I understand the mistake - I was also wondering how I would go about disposing of the impersonation context. And thanks for confirming that this is possible - I'll try to modify the filter to impersonate on calls and see how that goes. I'll deal with threads later - one thing at a time.

BTW, thanks for the library - works like magic, and tutorial is very easy to follow, it just works. The only thing that did not work is logging - could not manage to raise the logging level for Waffle in Tomcat.

Oct 20, 2010 at 5:42 AM


I've tried your suggestion with using the filter and impersonating inside of the filter. In order to test that, I'm doing a very simple HTTP request from inside of the filter's code into the same application to see if the credentials would be recognized after impersonation. So when I first time enter the filter, it asks for username/password, but the second request should have an authenticated/impersonated token so it should just return and log the right user in the logs. The code looks like this:"logged in user: " + windowsIdentity.getFqn() + 
						" (" + windowsIdentity.getSidString() + ")");
				if (request.getRequestURI().endsWith("amf")) {
					IWindowsImpersonationContext impContext = null;
					try {"Impersonating");
						impContext = windowsIdentity.impersonate();"Impersonated");
						URL url = new URL("http://localhost:8400/frep/index.html");
						URLConnection con = url.openConnection();
						InputStream inp = con.getInputStream();
						BufferedReader reader = new BufferedReader(new InputStreamReader(inp));"Result: " + reader.readLine());
					} catch (Throwable e) {
						_log.error("Exception opening connection to frep", e);
					} finally {
						if (impContext != null) {


I am running within LiveCycle DS (BlazeDS) so that's why the initial request is into "amf". The second request simply asks for a file on the same Tomcat server, under the same filter, so thats's why I condition impersonation based on the request. The request to the same filter allows me to see whether impersonation works and whether the passed in token is the right one.


What I get is a Java crash:

#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000000000000, pid=7964, tid=8368


This is the partial stack:

Stack: [0x0000000040750000,0x0000000040850000],  sp=0x000000004084ec68,  free space=3fb0000000000000000kJava frames: (J=compiled Java code, j=interpreted, Vv=VM code)j;Ljava/lang/String;Ljava/lang/String;)J+0j<init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V+29j;Lsun/net/www/HeaderParser;Ljava/lang/String;)Z+30j;)Lsun/net/www/protocol/http/AuthenticationInfo;+670j;+685j


Do you understand what could be missing in the credentials set by impersonation? This code works fine if I comment out impersonation, or if I login with the currently logged in user (I presume impersonation does not happen in that case).

Prior to crash, the log looks like this:

15:25:15,642  INFO NegotiateSecurityFilter:72 - POST /frep/messagebroker/amf, contentlength: 244
15:25:15,648  INFO NegotiateSecurityFilter:164 - authorization required
15:25:19,592  INFO NegotiateSecurityFilter:72 - POST /frep/messagebroker/amf, contentlength: 0
15:25:19,597  INFO NegotiateSecurityFilterProvider:75 - security package: Negotiate, connection id:
15:25:19,598  INFO NegotiateSecurityFilterProvider:83 - token buffer: 40 byte(s)
15:25:19,803  INFO NegotiateSecurityFilterProvider:93 - continue required: true
15:25:19,806  INFO NegotiateSecurityFilter:72 - POST /frep/messagebroker/amf, contentlength: 244
15:25:19,806  INFO NegotiateSecurityFilterProvider:75 - security package: Negotiate, connection id:
15:25:19,807  INFO NegotiateSecurityFilterProvider:83 - token buffer: 224 byte(s)
15:25:19,814  INFO NegotiateSecurityFilterProvider:93 - continue required: false
15:25:19,894  INFO NegotiateSecurityFilter:107 - logged in user: USR-DMIKHALKIN\frepTest (S-1-5-21-606910573-1714210556-1371439277-1009)
15:25:19,895  INFO NegotiateSecurityFilter:114 - Impersonating
15:25:19,896  INFO NegotiateSecurityFilter:116 - Impersonated
15:25:19,917  INFO NegotiateSecurityFilter:72 - GET /frep/index.html, contentlength: -1
15:25:19,917  INFO NegotiateSecurityFilter:164 - authorization required



Oct 20, 2010 at 11:56 AM


just letting you know that the crash was due to dll conflict and some unsafe code in JDK.

The conflict is due to the fact that security.dll which JDK uses is just a map of entry points that point into secur32.dll which Waffle loads for its security operations. Due to some reason, the same process refuses to load security.dll if secur32.dll is loaded.

The code in JDK loads security.dll dynamically but does not check the errors codes or return results, hence the crash. But essentially, security.dll and secur32 should be the same (or I presume so). 

I've hex-edited JDK to load secur32 instead, and after that the crash stopped. However, impersonation does not work either:

21:50:04,800  INFO NegotiateSecurityFilter:107 - logged in user: USR-DMIKHALKIN\frepTest (S-1-5-21-606910573-1714210556-1371439277-1009)
21:50:04,800  INFO NegotiateSecurityFilter:114 - Impersonating
21:50:04,800  INFO NegotiateSecurityFilter:116 - Impersonated
21:50:04,803  INFO NegotiateSecurityFilter:72 - GET /frep/index.html, contentlength: -1
21:50:04,803  INFO NegotiateSecurityFilter:164 - authorization required
21:50:04,804 ERROR NegotiateSecurityFilter:123 - Exception opening connection to frep Server returned HTTP response code: 401 for URL: http://localhost:8400/frep/index.html
	at waffle.servlet.NegotiateSecurityFilter.doFilter(
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(
	at org.apache.catalina.core.StandardWrapperValve.invoke(
	at org.apache.catalina.core.StandardContextValve.invoke(
	at org.apache.catalina.core.StandardHostValve.invoke(
	at org.apache.catalina.valves.ErrorReportValve.invoke(
	at org.apache.catalina.core.StandardEngineValve.invoke(
	at org.apache.catalina.connector.CoyoteAdapter.service(
	at org.apache.coyote.http11.Http11Processor.process(
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(

Any ideas? I'm that close...



Oct 20, 2010 at 12:22 PM

So that URLConnection claims to be able to do NTLM? Stub out the code, run a process as the user being impersonated and make sure it works first. Then we need to examine the HTTP conversation and check whether the NTLM tickets passed belong the impersonated user (I am not sure how to do that with an unsuccessful authentication). 

Try something simpler than an HTTP request maybe. Call some Windows methods, eg. getCurrentUser (I think it's in Advapi32Util or Kernel32Util in JNA) to make sure impersonation did work.

Mar 14, 2011 at 4:57 PM

Hi there


I'm trying to do impersonation using Waffle in Spring. I've set the value 'impersonate' to 'true', and in the log, I can observe that waffle.servlet.NegotiateSecurityFilter sets impersonate to true.


But.. when the request hits my doGet -method, the call appears not be impersonated! Secur32Util.getUserNameEx(Secur32.EXTENDED_NAME_FORMAT.NameSamCompatible) returns the local user name, and not the user name from the client.


Shouldn't this work, or what should the "impersonate=true" actually do?


Hope you can help - thanks in advance!



Mar 14, 2011 at 6:24 PM

@kvols: you are using a 1.4 build, right? The next step is to attach a debugger.

Mar 15, 2011 at 1:44 PM

Thank you for your reply!

Yes, we're using 1.4 beta and Tomcat 6.

We have done some debugging, and we have actually made it work, but we had to do a few changes in the Waffle code to make it happen. My colleague is collecting the changes in a doc for you as I write, and we'll send the changes as soon as we've put it together with some documentation.

Kind regards,

Apr 11, 2011 at 4:28 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Apr 11, 2011 at 4:29 AM

I took a long hard look at this and created I think all the problems you were having had to do with Spring and how it manages contexts. All that tells me is that we need to make something special for spring-enabled applications (a spring provider). Someone more vested in spring than me should take a look :)