The following question concerning SSO and ISAPI was posted in the ISAPI-DEV newsgroup. This sort of question for SSO happens all the time, but the answer is pretty much the same - use Kerberos (either within Windows or some other Kerberos system), or roll your own version of "Kerberos" without all the security foresight of the Kerberos architects. Hey, I chose to reply to this at 3am in the morning, and I have answered this before in a couple of different ways, so this is going to be a blog entry now that I may edit over time to improve the story...

Question:

I am building a SSO framework included in enterprise solutions for schools, our clients. Sorry about making this into a lengthy post. I chose to describe entire solution here since this solution requires small bits and pieces working together and fixing one breaks others (sound familiar?). Thank you for your patience in advance. Please read below and provide your thoughts, if any.

ENVIRONMENT

In this environment we have multiple Microsoft web applications such as Share Point server, Great Plains server and several other applications, which include homegrown systems as well as third-party web applications hosted on Sun and Microsoft platforms. All these applications hosted in DMZ. All applications are hosted in the same internet DNS domain so cookies can be shared across web application … if required.

Initiating browser client may be on: 1) the internal network logged on domain, 2) the internal network logged on locally the machine (not authenticated by domain controller), 3) a remotely located user connecting via VPN, 4) the internet.

Initiating browser can be: 1) IE (preferred), 2) non-IE

Lastly, we have no control over how firewalls, proxy servers, and NATs are installed and configured at customer site. I would like a universal solution that works at HTTP protocol level across all platform given that some type of filter process is installed/configured on the servers.

CURRENT SOLUTION

Current “XAPI” ISAPI filter is installed on all web application participating in SSO framework. XAPI watches for incoming authentication headers and SSOCookie.

If request contains basic-auth header and no SSOCookie then a Set-Cookie headers for SSOCookie is added to the returning response. SSOCookie value is identical to that of basic-auth header, mere copy of basic-auth header stired in the cookie.

If request contains auth header other than basic-auth then XAPI ISAPI filter acts transparent. Nothing is tweaked irrespective of SSOCookie is presence.

If request contains SSOCookie and does not contain auth header then XAPI ISAPI filter constructs an authentication header using SSOCookie, which is a basic-auth header.

A user is prompted for login when she connects to first application. This results in authenticating user and setting of SSOCookie in the browser. Any subsequent requests to any of the participating web application with XAPI ISAPI filter use SSOCookie to construct auth header on-the-fly.

So far so good! … we are now past MTBF in this design …. so it is time for things to fall apart ….

Users inside the domain would like to get benefits of Integrated Windows Authentication. Sure, why not! We turn on Integrated Windows Authentication as well as Basic Authentication.

Issue A: In this scenario consider user outside on the internet and firewall allows Integrated Windows Authentication. When external user authenticates using Negotiate/NTLM (Integrated Windows Authentication) on the first server with XAPI ISAPI filter. XAPI does not set SSOCookie since protocol chosen by the browser is Negotiate in response to WWW-Authenticate header contents. User then goes to an applications hosted on other server with XAPI installed and the user has to authenticate again.

Issue B: In this scenario consider user who are inside the firewall but locally logged in on the machine (not authenticated by domain controller). This is a typically a students connecting using on-campus network using their laptops. Laptops are not part of the domain. Same as above Issue-A happens.

Summary: SSO for non-domain users (external users and internal local machine users) fails when Integrated Windows Authentication and Basic Authentication are both enabled on all application.

QUESTIONS

Is there a way to force external users to Basic Authentication for non-domain users? (I see pigs flying)

Other way: Query Domain Controller or Kerberos server with host-ip, specified in the request header, to check if that host is currently in session on the domain.

Is there a way to find if a host IP is currently part of Kerberos session?

Lastly, am I asking the right question? :-)

Answer:

Ok, please do not take what I'm about to say the wrong way. I know that you are just trying to implement a solution, but your current situation (fixing one thing breaks another) suggest a lack of understanding of the fundamental problem in your authentication and authorization setup. That's why when you "fix" one manifestation of the fundamental problem, you fail to fix the real problem, so something else naturally breaks. You are dealing with security, so all the details must be correct or else it fails. Thus, I think that if you understood the fundamental problem, you should be able to see the solution categories and how to implement it.

Now, I am not going to comment on the particular protocol your XAPI Filter implements nor of the issues it faces because they are merely instantiations of the underlying problem, and since your proposed solutions do not address the real problem, you really do not want to spend time on them.

In the Abstract...

Let's start with the words Single Sign On. Abstractly, it means that for an arbitrary set of machines, if a user "signs on" with one of the machines, the other machines will consider the user "signed on" with them, until the user "signs off".

Next, let's look at what "sign on" means. It first suggests some authentication protocol is used to transfer a positive verification of user identity. Now, the wrinkle you introduce is that you want to allow multiple authentication protocols to authentication to any given machine, and the resulting verified identity needs to be magically delegatable to any other machine and remain verified for any other authentication protocol.

Authentication "Fiefdoms"

So, what you are really cobbling together is a series of authentication fiefdoms where users can transparently move about inside the fiefdom (assuming delegation properties), but when users access servers that cross an authentication fiefdom's boundaries, you have problems.

The problems come from the fact that to "translate" a verified identity between two authentication protocols, the translator is essentially able to perform a man-in-the-middle attack against the authentication protocol -- and most protocols defeat such attacks.

Also, no public authentication protocol supports the notion of a "trusted" identity translator between multiple authentication protocols. What all this means is that if you want security, you must stick with one authentication protocol internally amongst all of the servers supporting single sign on.

Using the medieval fiefdom analogy - suppose you are a serf, and your only means of identification is a badge with your name and the stamped seal of your lord. This seal is obviously recognized by everyone within this lord's fiefdom.

Now suppose you need to cross into a neighboring fiefdom to do some field harvesting work, but that fiefdom uses their lord's signature (not stamp) as validifier. Your stamped seal is no good, so the border guard is going to stop you right then and there.

Alas, neither fiefdom will trust each other's border guards to do the right thing (after all, you can send criminals and other miscreants from your fiefdom into the neighboring fiefdom, and no one likes that). So, a common solution is for one lord to rule over both fiefdoms and establish a common mark that acts to validate your identity.

There can only be one... Kerberos.

Ideally, you want to use Kerberos everywhere because it has a lot of nice properties that natively support Single Sign On. However, I realize that homogeneous systems is difficult in reality, especially resource-constrained environments like schools, but you must realize that compromise from using Kerberos means one of two things:

  1. If you care about security, you must implement a custom protocol used by all servers and the protocol is going to be very Kerberos-like -- to the point that you must wonder why don't you use off-the-shelf Kerberos that is well tested by security folks instead of using your custom and mostly unproven protocol
  2. If you do not care about security, you can implement something much looser that "works" but is once again untested and known to be weak against security attacks

I know that all of these solutions sound bad to you because it involves either:

  1. Cost more money
  2. Cost more labor
  3. Give up security

Now, before you dismiss my words, let me describe to you how I see your current problems  map to what I have described above.

IssueA:

The user originally authenticates using Integrated authentication, and this protocol does not send the user's password to the server at all, and the server cannot retrieve the password in any way. This is a security benefit of the protocol, but it is also a problem for XAPI Filter because the web server is no longer able to do a man-in-the-middle attack to translate credentials to a form that XAPI Filter can use throughout the rest of the servers.

Your solution of forcing Basic authentication to non-domain users is essentially extending the "fiefdom" of the Basic authentication protocol over particular servers, to avoid that Integrated->XAPI breaking point.

IssueB:

The non domain users cannot make the browser auto-authenticate to the servers using basic authentication because that is basically a security flaw -- browser just spewing the user's credentials in the clear to any server asking for it.

Your solution of trying to figure out if a host IP is part of a Kerberos session does not make sense because Kerberos is not a session-based protocol. It is a ticket-based protocol, meaning that users present a ticket to a resource as proof of authorized usage. The presence of the ticket is sufficient evidence of what you call "Kerberos session", but once again, web applications are not privy to this detail because secure design dictates that authentication happens BEFORE applications are run.

Solutions?

So, enough of the gloom and doom. What are possible solutions to this? I can think of the following:

  1. Pure Kerberos solution. Two basic ways to do this
    1. Standard Windows domain setup -- Windows Server 2003 Active Directory, all SSO servers are a part of the domain, and all users are in the domain (I'm not saying the laptops need to be in the domain -- just the user accounts which the laptops claim to authenticate need to be in the domain). The SSO servers can use any authentication protocol to authenticate, then use WS03's Protocol Transitioning to translate that into a Kerberos Ticket in the backend, and everything uses Kerberos internally. Just about all the pieces are off the shelf and you only need to implement the Kerberos ticketing agent that runs on non-domain machines (like laptops) which authenticates to your school's KDC on the AD -- but universities like MIT have already implemented this, so you may not need to do much work.
    2. Something similar to how MIT/Carnegie Melon works -- run your own Kerberos KDC that knows about all SSO servers and user principles, and force student/faculty's machines to run the Kerberos ticketing agent to obtain their Kerberos ticket in order to use the SSO servers. This also requires all your services to be retrofitted to be "kerberized" (i.e. accept Kerberos as authentication protocol).
  2. Pure custom auth solution (you happen to be using XAPI ISAPI Filter). You will need all your services to be retrofitted to understand XAPI, and you will need to write your own bridge between a XAPI user principle and a Active Directory principle (you need some directory service to provide user credential verification). The great thing with this approach is that you feel so empowered at solving your problem, and you can implement as much as you want. The bad thing, of course, is that you need to write this custom code, and it is basically custom, unproven code.

Any other choice is basically solution #3 -- either something that does not work, or you give up security for something else -- like Basic Authentication and pass username/password everywhere. No more delegation problems, but also terribly insecure.

//David