ksjoberg
Jul 17, 2014
visibility 9690
star star star star star star
(4 votes)

Troubleshooting a problem with POST-requests in an environment with mixed NTLM and Forms authentication

In most Intranet solutions there’s a desire to make the users of the Intranet be able to use the Intranet without logging in. This can be done in many ways, but this blog post takes one particular solution and takes a closer look at it.
The partner had created a special FormsAuthentication module to replace the standard ASP.NET FormsAuthentication module. Using some reflection it piggybacked on the OnEnter and OnLeave private method implementations in that module to copy the normal FormsAuthentication behavior that redirects the user to a login page if the authentication ticket is not among the user’s cookies.

As a part of the setup of this module, two virtual paths had been created whose requests were captured by a special module. One of those paths was reconfigured using a web.config location element to add a authentication element that specified that that path expects the user to authenticate using Windows authentication.

The two paths were /WindowsLogin (configured with Windows authentication) and /Authenticate (configured using Forms authentication).

When the user was decided to be unauthenticated, the normal behavior of the Forms authentication module is to redirect the user to the login page. In this case it was configured to be /WindowsLogin (see loginUrl in the documentation). When that Url was successfully executed, the server side code would issue a forms authentication ticket with the credentials the user (or web browser) supplied. In the Intranet zone, Internet Explorer attempts an NTLM/Negotiate based authentication automatically, so no login is required. On failure, the normal forms authentication screen would present via a redirect to /Authenticate.

The solution mostly worked, but there were some problems in critical areas of the web site. Notably, postback-requests would occasionally render as non-postbacks. This is particularly bad when that postback contain information the user has spent much time creating. Typical case would be the user creating a new page or editing an existing page. After about one minute from the moment the page was downloaded, the save action would simply reload the page.

After some troubleshooting we concluded that the problem occurred because Internet Explorer believed that all pages on the intranet was protected with NTLM/Negotiate. It basically means that at each new connection made, ​​the client is required to authenticate itself. HTTP Keep-alives allows a web browser to establish a single connection and then reuse it until the connection is closed. The idle timeout of keep alives in this environment was one minute.

It is done by a (simplified below) four step process:

  1. The browser sends a request for the protected resource, eg / episerver.
  2. The server responds 401 Unauthorized and provides a "NTLM challenge" to the browser.
  3. The browser computes a response to the server's given challenge and sends the response along with a new request for the protected resource.
  4. The server answers confirms the answer to the authentication and if it went well the server responds with 200 OK and process requests in full.

In step 1, the browser omits to send the POST data (the data entered in form fields on the page), as it is certain that the server will reply "401 Unauthenticated" and ignore the POST data so it would be pointless to send it. In step 3, the browser includes the POST data.

Since the server and the browser has different ideas of ​​what resources are protected with NTLM/Negotiate, this creates a conflict. The browser a expects a 401 response to resources protected by NTLM where the connection is not yet authenticated, but the server satisfies itself with the Forms Authentication ticket in the set of cookies sent by the client. This allows the server to act on a POST request without receiving the POST data (as it is omitted in step 1 of NTLM authentication), and then we will get the effect we saw - the "reloaded page" with emptied of form data.

The solution was to add the NTLM / Negotiate protected resources in a virtual directory, eg /AuthenticationSubSystem/WindowsLogin, so that the browser think it's just the resources in that directory that requires NTLM/Negotiate authentication. The other resources are handled by the browser as usual. Previously the NTLM protected resources resided directly in the root which made the browser assume that other resources under the root and its subdirectories are protected with NTLM.

Jul 17, 2014

Comments

error Please login to comment.
Latest blogs
Composition Over Inheritance: Why Your Content Contract Is Not a Base Class

Inside the structural conformance pattern in SaaS CMS — from server-side inheritance to pipeline governance. A contract in Optimizely SaaS CMS is...

Vipin Banka | Sep 19, 2026

Optimizely Opti ID Integration: Why the API Key Was Missing from the DXP Management Portal

While working on an Optimizely CMS 12 Opti ID integration recently, we ran into an issue that initially appeared to be related to SSO authenticatio...

Madhu | Sep 18, 2026 |

Extending a Contract: What You Can Override

Contracts share fields across content types — but not every field setting can be overridden. Push the same contract onto several components, and CM...

Chirag Khanna | Sep 18, 2026 |

Building a Blazor Server UI Inside the Optimizely CMS 13 Admin Shell

What I learned shipping a Blazor Server UI inside Optimizely CMS 13 — Razor components in a NuGet package, the Blazor hub next to MapContent(),...

Stanisław Szołkowski | Sep 17, 2026 |