Can I change the FormsAuthentication cookie name in asp.net dynamically? - asp.net-mvc

I want to set FormsAuthentication cookie name dynammically, for example a guid. how can i do that. I can already change it to whatever I want in web.config. I just can't do it in code and dynamically.Please help.
<authentication mode="Forms">
<forms name="myName" loginUrl="~/Account/Login" defaultUrl="~/Admin/admin" cookieless="UseCookies" slidingExpiration="true" timeout="40320"/>
</authentication>
The reason that I want to do this is, i have several instances of my application on the same host and i do not want them to overwrite each other's cookies.

I have been struggling with Cookies with quite a few days. It has been an awesome learning experience.
So wanted to share the possible ways I found & discovered: There are several HACKs to modify Forms Authentication Cookie name:
You can automate the modification of cookie name under Authenticaiton secion of Web.Config file in Application_Start event in Global.asax. Thanks to Ron for sharing this. But I could not guarantee that the user whose identity would be used to run application domain have enough privileges to modify the file on disk or not. Hence I needed an improvised solution, so I devised following.
Thanks to ILSpy for letting me see inside the FormsAuthentication class, and many thanks to Reflection to let me modify the private field of a class. I used following code to modify the cookie name on run-time with following small piece of code and this worked like a charm !!!
protected void Application_Start(Object sender, EventArgs e)
{
// This will enforce that FormsAuthentication class is loaded from configuration settings for the application.
FormsAuthentication.Initialize();
// The new cookie name whatever you need can go here, I needed some value from my application setting to be prefixed so I used it.
string newCookieName = string.Format("{0}.ASPXAUTH", ConfigurationManager.AppSettings["SomeSettingThatIsUniquetoSite"]);
// Modifying underlying baking field that points to FormsAuthentication.FormsCookieName
Type type = typeof(FormsAuthentication);
System.Reflection.FieldInfo field = type.GetField("_FormsName", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
field.SetValue(null, newCookieName);
}
Suggestions, loopholes are requested as this is my first answer on this forum.

You can't do this in code; the property FormsAuthentication.FormsCookieName is readonly. I would use the following configuration in web.config:
<authentication mode="Forms">
<forms configSource="forms.config" />
</authentication>
Then give each instance of the application its own forms.config:
<forms name="CookieNameForThisInstance" />

Related

asp.net session expiry not redirecting page with forms authentication

in my MVC 3 application on login it executes the following:
System.Web.Security.FormsAuthentication.SetAuthCookie(userName, false);
My web.config has the following:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
After that I set a few session variables. Problem is that if I leave a page for long enough for the session to expire, then click on a page then instead of redirecting me to the login screen, it is raising an exception in the controller with the null reference of the session variable.
public ActionResult Fixit(int Id, int cardId)
{
var model = new FixitVM();
model.PointsMaxValue = (int)Session["MAXPoints"];
}
Is this expected behavior? I would have thought the redirect to the login page would happen before this code fired.
Is there some configuration I can set to make the redirect happen before it tries to evaluate this code?
Authentication and session are managed by two different cookies. It's possible that the session cookie has expired while the authentication cookie is still good.

“A potentially dangerous Request.Form value was detected from the client”

How do I disable this page validation entirely and for good in ASP.NET MVC 3?
I have looked through the error message and the other questions with the same title. None of the suggested solutions help:
I do have a
<httpRuntime requestValidationMode="2.0" />
in the <system.web> section in Web.config.
I also do have a validateRequest="false" attribute on the <pages>...</pages> element.
But I am still getting the error. What else can I try?
Add the following line of code:
GlobalFilters.Filters.Add(new ValidateInputAttribute(false));
to the Application_Start() method.
Add [AllowHtml] to the action, parameter, or property.
EDIT: If you want to allow it anywhere, add new ValidateInputAttribute(false)] to GlobalFilters.Filters.

strong-typed profile values in ASP.NET membership (MVC)

I've been using ASP.NET MVC with membership-based login for several years and everything is working fine (it's now MVC3, but membership didn't change since the first version which was MVC1). Now I need to add a value into the profile (just one value, of very seldom use - so it doesn't warrant custom membership provider or custom tables)
I got it working through profile.SetPropertyValue("myprop"), but I would really want to get profile.myprop to work. Is it possible?
I saw some advise to have a custom class MyProfile : ProfileBase and have myprop as a property of that class. For some reason, casting ProfileBase.Create(currentUser.UserName) to MyProfile gives me an error (illegal cast).
Is there an example somewhere of ASP MVC application with Profile, similar to this Old Post by ScottGu?
Joel Spolsky had a great answer to this question on this post. You're basically on the right track.
If you're getting the illegal cast error, its most likely due to a problem in the config file. Make sure this is included; more specifically the <profile defaultProvider="SqlProvider" inherits="YourNamespace.AccountProfile"> section.
<profile defaultProvider="SqlProvider" inherits="YourNamespace.AccountProfile">
<providers>
<clear />
<add name="SqlProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="sqlServerMembership" />
</providers>
</profile>

Different LoginUrl for different URL's with ASP.NET MVC and Forms Authentication

I have a ASP.NET MVC project, and I would like to have a different LoginUrl for different areas of the website. Depending on the area of the site, different types of credentials are entered.
http://host.com/widget/home should redirect the user to http://host.com/widget/logon.
http://host.com/admin/home should redirect the user to http://host.com/admin/logon.
So far, the best solution I have come up with, is to have Forms Auth loginUrl="~/Account/Logon" in the web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880"/>
</authentication>
In the controller for Account:
public ActionResult LogOn()
{
//redirect depending on the returnUrl?
string returnUrl = ControllerContext.Controller.ValueProvider["ReturnUrl"].AttemptedValue;
if (returnUrl.StartsWith("/widget"))
{
return Redirect(string.Format("/widget/Logon?ReturnUrl={0}", returnUrl));
}
if (returnUrl.StartsWith("/admin"))
{
return Redirect(string.Format("/admin/Logon?ReturnUrl={0}", returnUrl));
}
return View();
}
Is there a better way to do this?
I asked and answered this in my stackoverflow question How to redirect to a dynamic login URL in ASP.NET MVC.
I know that you can have separate web.config files in sub-folders of a website, so that if you had actual .aspx pages within an admin/ folder, and a web.config in that folder, you could specify the authentication url in that folder separately.
I'm not sure if that works with ASP.NET MVC routes as you're probably not going to have physical files in those sub-folders, but it's worth a try.
Add Authenticate attribute to your actions.
Then in global.asax add Application_AuthenticateRequest then look at the sender and redirect there where you want the action to login.

SessionID keeps changing in ASP.NET MVC why?

I am trying to keep track of something and using the SessionID as they key to that object
However the SessionID every 2-3 reqiests changes shouldn't it remain the same?
HttpContext.Session.SessionID
Is the code I am using.
I've seen that happen even without MVC. If I remember correctly, ASP.NET keeps assigning new session ids until you place something into the Session variable.
You should initialize the Session object within Global.asax.cs.
void Session_Start(object sender, EventArgs e)
{
HttpContext.Current.Session.Add("__MyAppSession", string.Empty);
}
This way the session will not change unless your browser window is closed.
I am working on a .NET MVC cart application and I added
Session["myVar"] = "1234";
to the Page_Load method found in the Default.aspx.cs code. I also added
<%= this.Session.SessionID %>
to the Site.Master footer. I then rebuilt my app and browsed the various pages of my app and the footer displays the same session id for all pages as expected!
If you look the seession ID cookie is not even sent to the browser unless it's used on the server.
So when a page roundtrips there is no current session ID cookie, so a new session ID is created, hence it is random.
This is logical, why bother tying up the app to a session if the session is not in use?
I would look into using TempData to keep track of something.
Try with adding machine key into your web.config:
Online key generator: http://aspnetresources.com/tools/keycreator.aspx
It seems that server resets machine key for client and generates new one with new session id, every few minutes, which is much lower than it should. Don't know if that's bug or feature:)
Also, you can increase your session state timeout, which is i think 20min by default.
I was having the same problem using ASP.NET Web Forms. I just had to add a global.asax file to the solution and the fixed it for me.
Summing up answers from #jrojo and #Maxam above, with what I am using.
I am using AWS DynamoDB as the session store (out of scope of the question a little, but gives sample).
Add package via NUGET:
Install-Package AWS.SessionProvider
Update Web.config to have keys in appSettings:
<add key="AWSAccessKey" value="XXX" />
<add key="AWSSecretKey" value="YYY" />
And session provider to system.web:
<sessionState timeout="20"
mode="Custom"
customProvider="DynamoDBSessionStoreProvider">
<providers>
<add name="DynamoDBSessionStoreProvider"
type="Amazon.SessionProvider.DynamoDBSessionStateStore, AWS.SessionProvider"
AWSProfilesLocation=".aws/credentials"
Table="ASP.NET_SessionState"
Region="us-east-1"
/>
</providers>
</sessionState>
Add anything to session in global.asax on session start:
void Session_Start(object sender, EventArgs e) {
HttpContext.Current.Session.Add("somethingToForceSessionIdToStick", string.Empty);
}
Verify by adding this to razor of any page. Refresh that page, then open an ignito window and see a different session:
#HttpContext.Current.Session.SessionID
BobsYourUncle
please see if you have set the cookie samesite attribute to strict.
remove cookieSameSite="Strict" and check.

Resources