TL/DR: I am experiencing an HTTP-302 redirect loop when trying to share an authentication cookie between an ASP.NET WebForms site and an ASP.NET MVC web site that are served on separate sub-domains.
Details
a.website.com
- The existing WebForms site. Works fine.
b.website.com
- The new MVC site I'm trying to integrate using the shared cookie.
- User reaches b.website.com and is not yet authenticated. They are redirected to a.website.com/Login.aspx.
- User enters their username/password.
- The user is redirected to the original desired page on b.website.com.
- b.website.com receives the authentication cookie in the request, but for some reason fails to see the user as authenticated. It sends them back to a.website.com/Login.aspx.
- a.website.com sees the cookie and realizes the user is authenticated, and redirects the user back to b.website.com.
Steps 4 and 5 repeat until the browser breaks the loop.
Setup
The setup follows the MSDN documentation for Configuring Forms Authentication Across Applications precisely: the two sites share machine key settings and Forms authentication settings. Both sites reside on the same server and IIS instance. Both sites force SSL. In the web.config file, the Membership and RoleManager settings are identical.
For a.website.com, which hosts the login page:
<httpCookies httpOnlyCookies="true" requireSSL="true" />
<authentication mode="Forms">
<forms name="COOKIE_NAME"
domain=".website.com"
loginUrl="login.aspx"
defaultUrl="login.aspx"
requireSSL="true"
cookieless="UseCookies"
protection="All"
enableCrossAppRedirects="true"
path="/"/>
</authentication>
<machineKey
validationKey="((validation key))"
decryptionKey="((decryption key))"
validation="SHA1"
decryption="AES" />
b.website.com is of course pretty similar, except the login URL for unauthorized users directs them to the login on site "a".
<httpCookies httpOnlyCookies="true" requireSSL="true" />
<authentication mode="Forms">
<forms name="COOKIE_NAME"
domain=".website.com"
loginUrl="https://a.website.com/login.aspx"
defaultUrl="login.aspx"
requireSSL="true"
cookieless="UseCookies"
protection="All"
enableCrossAppRedirects="true"
path="/"/>
</authentication>
<machineKey validationKey="((validation key))"
decryptionKey="((decryption key))"
validation="SHA1"
decryption="AES" />
Troubleshooting
This setup works as expected on my development machine and our test server (albeit with no domain
setting and loginUrl
set accordingly) where both web sites are running from the same domain, just different port numbers. For example, in local development, site "a" might run from https://development:44301/
and site "b" might run from https://development:44302/
. However, on the production machine--where they are actually on different subdomains--I experience the redirect loop.
Using the browser web developer tools, I can see that the authorization cookie is being sent to b.website.com after the login redirect. Also on b.website.com, if I remove the [Authorize]
attribute decorating the controller, the pages load as expected. I'm reasonably sure the issue is limited to how the MVC site is handling the authentication cookie in the limited subdomain scenario.
It sounds like the same issue was reported on SO here and here, but those users had not set enableCrossAppRedirects="true"
. That setting (which is enabled in my code) seems to be required for subdomain redirects, as I've already tried. This SO article details the setting a bit more and indicates the redirect should be done via SSL, which I am also doing.
What am I missing? How can I better debug the authentication failure that apparently occurs when site "b" receives but does not acknowledge the cookie?