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...
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.
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 “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.
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? :-)
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.
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.
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.
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:
I know that all of these solutions sound bad to you because it involves either:
Now, before you dismiss my words, let me describe to you how I see your current problems map to what I have described above.
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.
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.
So, enough of the gloom and doom. What are possible solutions to this? I can think of the following:
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.