I am developing an iterative migration from a legacy ASP.NET forms app to an MVC 4 app.
This migration is happening in stages, one section at a time, so it is necessary to run both the legacy and the new MVC application simultaneously. For some sections, the user is directed to the new application, and for sections that have yet to be migrated, the user is directed back to (or remains on) the legacy application.
On the server, the applications are structured like this:
LEGACY (.NET 2.0 forms app)--
|--Api (new MVC 4 WebAPI)
|--V2 (new MVC 4)
So a call to foo
page on legacy is /foo.aspx
and on V2 it's /V2/foo
.
Everything is in C#, but please note that the legacy app is running on .NET 2.0 and the V2 app is running on .NET 4.5. I am not sure if this matters, but thought it would be important to note.
I can not successfully share the user/authentication state between applications. Obviously, if the user logged in on the legacy app, I need to grab their auth cookie (or take similar action) on the V2 app when a V2 page is called up so that the user does not get prompted again to log in.
I have set identical authentication
and machinekey
elements in both web.config files:
<authentication mode="Forms">
<forms cookieless="UseCookies" defaultUrl="~/someUrl" loginUrl="/" path="/" protection="All" timeout="240" enableCrossAppRedirects ="true" domain="someDomain.com" requireSSL="false" />
</authentication>
<machineKey validationKey="DE78CF63226. . .788658D142AB881" decryptionKey="0B97E8BA4C4EB4B4C524. . .54E4622E14168D2D5C84461FA2" validation="SHA1" decryption="AES" />
I have tried this code in the Global.asax of the V2 application:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (authCookie == null)
{
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
if (authTicket == null)
{
return;
}
string[] roles = authTicket.UserData.Split(new char[] { '|' });
var id = new FormsIdentity(authTicket);
var principal = new GenericPrincipal(id, roles);
//Thread.CurrentPrincipal = principal;
Context.User = principal;
}
But I have no idea whether or not it works because the legacy app is not in the same solution as my V2 app and therefore when I debug the V2 app, I don't have a way to log in via the Legacy app and simulate the actual user experience of hopping between legacy and V2.
I have also just tried adding this to my HomeController
in hopes that the identical machine keys would work some magic for me:
ViewBag.UserName = User.Identity.Name;
Obviously, I then bind ViewBag.UserName
to an html element in the view, but this doesn't seem to work either.
Set the machineKey compatibilityMode="Framework20SP2" on the parent app.
.net 4.5 can't read auth tokens from 4.0 (or below)
http://technet.microsoft.com/en-us/subscriptions/index/system.web.configuration.machinekeycompatibilitymode
http://blogs.msdn.com/b/webdev/archive/2012/10/23/cryptographic-improvements-in-asp-net-4-5-pt-2.aspx
The signing and encryption algorithms for forms auth switched between .NET 2.0 and 4.0; so in your 4.0 config try
<appSettings>
<add key="aspnet:UseLegacyFormsAuthenticationTicketCompatibility" value="true" />
<add key="aspnet:UseLegacyEncryption" value="true" />
<add key="aspnet:UseLegacyMachineKeyEncryption" value="true" />
</appSettings>
Note that now you have a persistent auth method hitting your webapi endpoints you are vulnerable to CSRF and you will need to protect against it. Mike Wasson has a walkthrough on asp.net
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With