In that post, as in the past I've always pointed people in the Right Direction and let them fill in the blanks themselves. This week I had to actually go get it working and given all the effort it took me I have a sneaking suspicion that most people listen to my suggested solution, nodded, said they understood and then skipped the Kerberos bit altogether.
First the requirements:
- a Windows domain
- a server in the domain with an IIS web server and a Web Gate installed/configured
- a workstation in the domain (call this one workstation1)
- workstation NOT in the domain (call this one workstation2)
Seems simple, right? It's not.
The way IWA works is through the HTTP authentication method called Negotiate documented in RFC 4559. Basically your client says "GET /foo" and the server says "401. Gimme a Kerberos token" and optionally some text or HTML. Your browser repeats the first request and includes a Keberos token. The spec includes details of what the flow looks like on the wire.
In the olden days if your browser didn't know how to handle the Negotiate authentication method it would just show the HTML page that the web server sent back. Things have changed though - browsers tend to hide the real HTTP error pages and instead show "friendly" error pages. I also discovered that IE, at least in my test environment, pops a login box up on the screen to collect the credentials.
So what we need is a way to silently detect whether the web browser can authenticate to the web server or not. Once we have that putting together the OAM bits is just a matter of following the normal steps.
What didn't work...
I tried a bunch of ways to do that detection before finding one that worked. I am listing them here not to torture you, but to describe why they didn't work to save you the time and trouble of testing them out on your own.
Ways that didn't work:
- using IIS' 401 error page
- using XmlHttpRequest and XDomainRequest
- using Flash
XmlHttpRequest is the standard way that AJAX web apps make HTTP requests to the server via JavaScript. XDomainRequest is an IE 8+ proprietary extension that's basically the same thing as XmlHttpRequest but has different security restrictions; more info can be found on MS' site. Both of these exhibited the same behavior as the browser itself, exactly as the W3C spec says they should.
I tried Flash because it's almost always available on platforms that would support Kerberos and because it plugs into the browser and is initialized on browser startup. Unfortunately the URLRequest object in Flash doesn't provide low enough level control to avoid the pop-up box.
What DID work?
The only thing I could get to actually work without breaking my requirements was a Java Applet.
If you let it Java's URLConnection class handles the Kerberos authentication for you. All you need to do is wrap a try/catch block around the call and fire it off. If you get back content then the HTTP transaction succeeded. This is what the Applet's code looks like:
URL url = new URL("http://testmachine.testdomain.com/IWAProtected/");Make /IWAProtected/ protected by IIS' Integrated Windows Authentication, put that code into an Applet and add the Applet to an HTML page elsewhere on your site and you'll be able to tell whether the user is logged into the domain or not.
URLConnection urlConn = url.openConnection();
urlConn.setAllowUserInteraction(false);
urlConn.setUseCaches(false);
DataInputStream dis = new DataInputStream(urlConn.getInputStream());
data = new String();
String s;
while ((s = dis.readLine()) != null) {
System.out.println("Read data" + s);
data += s + "\n";
}
dis.close();
Pulling the bits together
Once you have an applet that can detect that the user is logged into the domain all that remains is to put the pieces together. There are a bunch of ways to get across the finish line depending on how you want it to work, the simplest of which is to make an HTML login page your "default". You add the applet to that page, let the applet detect that IWA is available to the user. If the applet determines that IWA isn't going to work for the user they just fill out the normal HTML form and log in. If the applet determines that IWA will work for the user you use JavaScript to kick the user into the Kerberos authentication process.
I'll leave some of the details up to you, but those are the broad strokes.
Hope this helps!
I tried this approach out and ran into a few issues -
ReplyDelete1) I'm using JRE 1.6.0_20, and the "urlConn.setAllowUserInteraction(false);" part just seems to be disregarded. On a machine where I am not logged on to the corporate domain, the JRE throws up an authentication dialog!
2) Also, if I turn off the IWA capability in my browser (when logged on to the domain), the applet still reports that IWA will work for me. Based on this, if I kick off the Kerberos authentication process, the browser will just try to collect credentials via the basic popup.
Any thoughts?
otrams.. i'm having the same issue with #1 where the authentication dialog keeps popping up regarless of "urlConn.setAllowUserInteraction(false);"
ReplyDeleteAny solution found?
If the Java Applet finds that it can do the transaction then the machine must be in the domain (or something magical is happening!). Short of having the applet change IE's config setting you can't really help that the user has twiddled the checkbox. And to do THAT you'd have to sign the applet, so the user would wind up getting a dialog box anyway.
ReplyDeleteSo sadly I don't think there's a perfect answer.