Nota: Este artículo fue publicado originalmente en 2008 about Community Server. The authentication and cookie troubleshooting principles described here apply to any ASP.NET web application, including modern ASP.NET Core apps. The guide has been expanded with current best practices.

One of the most frustrating issues in web application authentication is when the login process appears to succeed — credentials are validated, no error messages are shown — but the user is immediately redirected back to the home page or login page as if they never logged in. This problem is not unique to Community Server; it affects any web application that relies on cookies for session or authentication state. The root cause is almost always that the authentication cookie is not being stored or sent back by the browser.

Understanding the Authentication Flow

Before troubleshooting, it helps to understand what happens during a successful login in an ASP.NET application (including Community Server):

1. User submits credentials (username + password)
2. Server validates credentials against the membership provider
3. Server issues an authentication cookie (FormsAuthentication ticket)
4. Server sends HTTP 302 redirect to the destination page
   └── Set-Cookie: .ASPXAUTH=<encrypted-ticket>; path=/; HttpOnly
5. Browser stores the cookie
6. Browser follows the redirect and includes the cookie in the request
   └── Cookie: .ASPXAUTH=<encrypted-ticket>
7. Server reads the cookie, decrypts the ticket, and identifies the user
8. User sees the authenticated page

If anything breaks at steps 4-6, the user will appear authenticated momentarily but then lose their session. The login “succeeded” (step 2 passed), but the cookie was never stored or returned.

The most common cause is a mismatch between the cookie’s domain attribute and the URL the user is browsing.

How It Happens

If your site is accessible at both www.example.com and example.com, but the authentication cookie is set with domain=www.example.com, then:

  • Browsing www.example.com — Cookie is sent. Login works.
  • Browsing example.com — Cookie is not sent (different domain). Login appears to fail.

Diagnosis

Check the cookie in browser developer tools (F12 > Application > Cookies) after logging in:

  • Look at the Domain column for the .ASPXAUTH cookie.
  • Compare it to the URL in the address bar.

In web.config:

<authentication mode="Forms">
  <forms loginUrl="/login"
         name=".ASPXAUTH"
         domain=".example.com"
         path="/"
         timeout="30"
         protection="All"
         requireSSL="false" />
</authentication>

The leading dot in .example.com makes the cookie valid for example.com, www.example.com, and any other subdomain.

In Community Server, you may also need to update the communityserver.config or SiteUrls.config to ensure all URL references use a consistent domain.

Fix: Redirect to a Canonical Domain

A better long-term solution is to enforce a canonical domain via URL rewrite:

<!-- IIS URL Rewrite rule to force www -->
<rule name="Redirect to www" stopProcessing="true">
  <match url="(.*)" />
  <conditions>
    <add input="{HTTP_HOST}" pattern="^example\.com$" />
  </conditions>
  <action type="Redirect" url="https://www.example.com/{R:1}" redirectType="Permanent" />
</rule>

If the authentication cookie has the Secure flag set, the browser will only send it over HTTPS connections.

How It Happens

  • The requireSSL="true" attribute is set in web.config, or the application code sets Cookie.Secure = true.
  • The user logs in over HTTPS (cookie is set and stored).
  • A link or redirect sends them to an HTTP page.
  • The browser does not include the cookie on the HTTP request.
  • The server treats them as unauthenticated.

Diagnosis

<!-- Check web.config for this setting -->
<forms requireSSL="true" ... />

Or inspect the cookie in browser dev tools and look for the Secure attribute.

Fix

Option A (Recommended): Enforce HTTPS on the entire site. This is the correct approach for modern web applications:

<!-- Force HTTPS redirect in IIS -->
<rule name="HTTPS Redirect" stopProcessing="true">
  <match url="(.*)" />
  <conditions>
    <add input="{HTTPS}" pattern="off" />
  </conditions>
  <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>

Also add the HSTS header:

<customHeaders>
  <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />
</customHeaders>

Option B: If you cannot enforce HTTPS everywhere, set requireSSL="false" — but understand this exposes the authentication cookie to network interception on HTTP requests.

Modern browsers have increasingly strict cookie policies.

Starting with Chrome 80 (February 2020), cookies without an explicit SameSite attribute default to SameSite=Lax. This means:

  • The cookie is not sent on cross-site POST requests.
  • The cookie is not sent in cross-origin iframes.
  • The cookie is sent on top-level navigations (clicking a link).

If your login form is on a different domain or subdomain than the main application, or if the login happens inside an iframe, SameSite=Lax will block the cookie.

Fix: Set SameSite Explicitly

In ASP.NET 4.7.2+:

// In Global.asax or an HTTP module
protected void Application_EndRequest(object sender, EventArgs e)
{
    var cookies = Response.Cookies;
    for (int i = 0; i < cookies.Count; i++)
    {
        var cookie = cookies[i];
        if (cookie.Name == FormsAuthentication.FormsCookieName)
        {
            cookie.SameSite = SameSiteMode.Lax;
        }
    }
}

In ASP.NET Core:

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.Cookie.SameSite = SameSiteMode.Lax;
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.HttpOnly = true;
    });

Browser Privacy Settings

Some browsers or browser extensions (e.g., Privacy Badger, uBlock Origin) block cookies aggressively. Users with “Block all cookies” or “Block third-party cookies” settings may not be able to log in.

Diagnosis: Test in a private/incognito window with extensions disabled. If login works there, the issue is browser settings or extensions.

Cause 4: Session State Configuración Issues

In some applications, authentication is tied to session state rather than (or in addition to) the Forms Authentication cookie. If the session is lost, the user appears logged out.

In-Process Session (Default)

In-process session (InProc) stores session data in the web server’s memory. It is lost when:

  • The application pool recycles.
  • IIS restarts.
  • The worker process crashes.
<!-- web.config: default in-process session -->
<sessionState mode="InProc" timeout="20" />

Fix: Use a Persistent Session Store

For production environments, use SQL Server or Redis for session storage:

<!-- SQL Server session state -->
<sessionState mode="SQLServer"
              sqlConnectionString="data source=SQLServer;Initial Catalog=ASPState;Integrated Security=True"
              timeout="30" />
<!-- State Server (out-of-process on the same or another server) -->
<sessionState mode="StateServer"
              stateConnectionString="tcpip=127.0.0.1:42424"
              timeout="30" />

Ensure the session cookie (ASP.NET_SessionId) has the same domain and path settings as the authentication cookie:

<sessionState cookieless="UseCookies"
              cookieName="ASP.NET_SessionId"
              timeout="30" />

Cause 5: machineKey Mismatch in Web Farms

If your site runs on multiple web servers behind a load balancer, all servers must share the same machineKey for encrypting and validating authentication cookies.

How It Happens

  1. The user logs in and their request hits Server A, which encrypts the authentication cookie using its machine key.
  2. The next request hits Server B, which tries to decrypt the cookie using its own (different) machine key.
  3. Decryption fails. Server B treats the user as unauthenticated.

Fix: Set an Explicit machineKey

Generate a machine key and add it to every server’s web.config (or the machine-level web.config):

<system.web>
  <machineKey
    validationKey="ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01234567"
    decryptionKey="ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01"
    validation="SHA1"
    decryption="AES" />
</system.web>

Importante: Generate unique keys for your application. Never use example values from documentation. You can generate keys using IIS Manager (Machine Key feature) or PowerShell:

# Generate a random machineKey in PowerShell
$validationKey = -join ((1..64) | ForEach-Object { '{0:X2}' -f (Get-Random -Minimum 0 -Maximum 256) })
$decryptionKey = -join ((1..24) | ForEach-Object { '{0:X2}' -f (Get-Random -Minimum 0 -Maximum 256) })
Write-Host "validationKey: $validationKey"
Write-Host "decryptionKey: $decryptionKey"

ASP.NET Core Data Protection Keys

In ASP.NET Core, the equivalent is the Data Protection system. For web farms, you must share the key ring:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\shared-server\keys\"))
    .SetApplicationName("MyApp");

Or use Azure Blob Storage, Redis, or a database for key storage.

If the authentication cookie’s path attribute does not match the URL structure of your application, the browser may not send the cookie.

Example

<!-- Cookie set with path="/app" -->
<forms path="/app" ... />

A request to /dashboard will not include the cookie because /dashboard is not under /app.

Fix

Set the cookie path to / unless you have a specific reason to restrict it:

<forms path="/" ... />

Cause 7: Time Synchronization Issues

Authentication cookies contain an expiration timestamp. If the server clock and the client clock are significantly out of sync, the browser may treat the cookie as already expired.

  • If the server’s clock is ahead of the client, the cookie may appear to expire in the past from the client’s perspective.
  • If the server’s clock is behind, the cookie’s issued-at time may be in the future, which some browsers reject.

Fix

Ensure all servers use NTP to synchronize their clocks. See NTP Server: How to test client connectivity from a Windows client for details.

Diagnostic Checklist

When troubleshooting “login succeeds but session is lost,” work through this checklist:

CheckHow to Verify
1. Is the cookie being set?Browser DevTools > Network > Response Headers > look for Set-Cookie
2. Is the cookie being stored?Browser DevTools > Application > Cookies > check for .ASPXAUTH
3. Is the cookie being sent back?Browser DevTools > Network > Request Headers > look for Cookie header
4. Does the cookie domain match?Compare cookie domain attribute to the URL in the address bar
5. Is the Secure flag set on an HTTP page?Check cookie attributes in DevTools
6. Is SameSite blocking the cookie?Check cookie SameSite attribute; test in Chrome with chrome://flags
7. Are machineKeys consistent?Compare web.config across all servers in the farm
8. Is session state configured?Check <sessionState> in web.config
9. Are server clocks in sync?Run w32tm /query /status (Windows) or timedatectl (Linux)
10. Do browser extensions block cookies?Test in private/incognito mode with extensions disabled

Reproducing the Original Issue

The original problem described in 2008 was:

Login worked in Internet Explorer 7 but not in Google Chrome.

This was likely caused by one of the following:

  1. Cookie domain handling differences. Early Chrome had stricter cookie domain matching than IE7.
  2. P3P (Platform for Privacy Preferences) policy. IE required a P3P header to accept third-party cookies. Chrome ignored P3P entirely but had its own cookie restrictions.
  3. Cookie path or expiry parsing. Different browsers interpreted ambiguous cookie attributes differently in the early days.

The fix in 2008 would have been to ensure the cookie domain was set correctly and the Set-Cookie header was well-formed. Today, the same principles apply, but with the addition of SameSite, Secure, and HTTPS requirements.

Resumen

When login succeeds but the session is not maintained, the problem is almost always with the authentication cookie — it is either not being stored by the browser or not being sent back on subsequent requests. Systematically check the cookie domain, SSL/Secure flag, SameSite attribute, browser settings, machineKey synchronization (in web farms), and session state configuration. Use browser developer tools to inspect the Set-Cookie response header and the Cookie request header to pinpoint exactly where the chain breaks.

Artículos Relacionados