I ran into an issue with ADFS (Active Directory Federation Services) recently that had me scratching my head a bit. Let’s set the record straight from the outset here… I thoroughly dislike ADFS and I am not a pro when it comes to managing it. So I often have to do a lot of research and digging whenever I have to do any kind of administrative work with it.
ADFS and SAML have their own dialect of IT speak… and versatile as I am I have found administering and deploying ADFS to have a rather steep learning curve. So my apologies in advance is this article isn’t as accurate or precise as it should be.
In the scenario that occasioned this article, ADFS is being used to integrate with a third-party hosted web application and while successful authentication works fairly well, there has been some real headache around unsuccessful authentication attempts.
The organization had employees with Active Directory user accounts and IT wanted to allow those employees to login to the externally hosted web application using their AD accounts. This is a very typical use-case for ADFS. The application provided a basic login page with a button that said something along the lines of “Login as Employee.” The button was actually a link to a SAML ADFS page hosted on the organizations ADFS server which would respond with a popup login prompt asking for the employee’s AD credentials.
The system worked just fine when an employee was able to successfully authenticate.
If an employee entered the wrong password or their account was locked or any number of other things would occur to make their login attempt unsuccessful, the system would of course not allow them entrance and it would simply kick them back to the login page… however that is where things started to go a bit wrong.
When a user who failed to authenticate the first go around hit the “login as employee” button again, the system would not offer the login prompt, but instead would simply appear to refresh the login page. After one unsuccessful attempt, there was no apparent way to get the login prompt to pop-up again.
I did quickly find a rather crude workaround. The employee could clear out all of their web browser history or could use an incognito window (chrome) or inPrivate Browsing window (Internet Explorer). Doing either of the above would allow the employee to visit the page and get the login prompt again. However the average user often required guidance from IT at this point and most people don’t actually want to wipe their browser clean all the time. So it was a major headache all around.
On the backend ADFS server I looked in Event Viewer and noticed something interesting. A failed login event was generated in the ADFS log when I failed to login the first time via the login prompt. The EXACT same login failure event was subsequently generated every time afterwards as soon as I hit the “Login as Employee” button. Which means the system was reusing the bad credentials I had previously entered every time I hit that login button rather than presenting me with the prompt. Interesting…
Where was it getting those credentials? The crude workaround was part of the answer… it was some kind of browser cookie or cache file… I was assuming this was a function/design of the third-party web application I was integrating with… it was not… it is actually a function of ADFS 2.0 and its partly defined in the web.config file.
By default, the ADFS system will have the user’s browser keep a cookie for 30 days. Said cookie will allow them to more or less stay logged-in. So even if the user completely reboots their machine, when they open the browser back up and navigate to the third-party site, they won’t have to enter credentials again. As a security person this grates at me horribly… That aside though, the functionality just plain seems to be broken because even if the user FAILS to login properly, the system STILL generates a cookie and they will never be able to get into the bloody site short of an incog window or using a different computer or clearing browser history/cookies/cache etc.
So the fix (sort of)… Here is what I did after some research…
1. Login to your ADFS server as a user with Local Administrative privilege.
2. ADFS is honestly just a glorified web application and to fix this you need to modify its web config file. That can be found here:
3. Open that file up with an elevated instance of notepad (right-click on notepad –> run as admin –> open the file by browsing to it with notepad)
4. Find the following line:
<persistIdentityProviderInformation enabled="true" lifetimeInDays="30" />
5. Change it to this:
<persistIdentityProviderInformation enabled="false" />
6. Save the file.
What does this do? It basically means that the aforementioned “credentials cookie” is tied to their browser session state. So, as long as the browser is open they have a session cookie.
As you probably realize, this does NOT completely solve the issue. If the person fails to login to the application on the first attempt, they will still get shunted back to the page with the “Login as Employee” button and the same behavior will ensue.
It is better though… Rather than having them clear out their browser cache and history (which BTW, still didn’t always work…) they can now simply close their browser completely and reopen.
I believe there is a way to alleviate or fix this errant behavior altogether by adjusting various token lifetimes. Unfortunately you will have to read a small book on the matter in order to figure it out which is exactly what this kind and much more patient gentleman wrote here:
My 2-cents… If it requires a tech blogger to literally write 5,000+ words in order to explain what should be a simple configuration change… it’s poor product design. Microsoft needs to take ADFS
back to the drawing board and chuck it in the trashcan and start from scratch on a better SSO/Shared Identification solution.
I haven’t had a chance to fully digest the entire linked article above but that is my next task if I am going to get this Web App’s authentication working the way I want it. The solution I have given in this article was thankfully quick and easy to implement and will at least be a piece of duck tape until I can come up with a better fix.
If you want more information on what can be controlled via the Web.Config file take a look at the link in the reference section below.
Cheers and wish me luck.