Is it possible to update FormsAuthentication cookie value? - asp.net-mvc

I have to set FormsAuthentication cookie value (FormsAuthentication.SetAuthCookie(UserDesignation, false)) at the time of login.
Now I need to provide designation change option. So when user change their designation, I need to update the FormsAuthentication cookie value from old designation to new designation.
Is it possible to do that?
If yes means, how can I do this?

You can modify the cookie data as shown below, but it is preferable as per me to keep the role in a separate cookie and authenticate it using the FormsAuthentication cookie
HttpCookie cookie = FormsAuthentication.GetAuthCookie(Username, true);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
var newticket = new FormsAuthenticationTicket(ticket.Version,
ticket.Name,
ticket.IssueDate,
ticket.Expiration,
true, //persistent
"user data,designation",
ticket.CookiePath);
cookie.Value = FormsAuthentication.Encrypt(newticket);
cookie.Expires = newticket.Expiration.AddHours(2);
HttpContext.Current.Response.Cookies.Set(cookie);

Related

OpenID Connect ASP NET MVC AAD

I implemented a sample app using OpenID Connect standard with ASP NET MVC website. My goal was to outsource storing sensitive data to Azure so i used Azure Active Directory. Since it's impossible to add custom properties to users in Azure i store non sensitive user Claims in our private db. I managed to get this claims and "add" them to the cookie like this:
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
RedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = context =>
{
var objectId = context.AuthenticationTicket.Identity.Claims.First(x => x.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier");
var claims = GetUserClaims(objectId.Value);
foreach (var item in claims)
{
context.AuthenticationTicket.Identity.AddClaim(new System.Security.Claims.Claim(item.Key, item.Value));
}
return Task.FromResult(0);
}
}
This way I added required claims to the cookie so those claims persist in my User object until user sign-out which is fine but there is one Claim which can change during the session ( basically user can change it on one page ). The problem is I can't find how to "change" this Claim in the cookie so it will persist. Ideally I would like to somehow force
AuthorizationCodeReceived
function to be called again. Is it possible ? Or is there another way where I can swap the value stored in the cookie ?
So far my only solution is to log-out user when he change this value so it will force him to sign-out again and my callback for AuthorizationCodeReceived will be called again, but it's not a very user-friendly way.
You can call HttpContext.GetOwinContext().Authentication.SignIn() after you add a claim in identity object to persist the new claim in cookie.

Can a forms authentication cookie .ASPXAUTH be used to assign a user to a MVC 5 OWIN application's context?

Can a .ASPXAUTH forms authentication cookie be used in an MVC 5 OWIN-based application to create a user in the HttpContext.User property?
Both applications share the same machineKey and the domain/server are the same. The .ASPXAUTH cookie is also available in the MVC 5 application's OwinContext.Request.Cookies collection.
In MVC 5 OWIN-based project:
You should think about several things.
That's how it works for me:
Do all things described in this article (see also github project)
Dont forget set up "compatibilityMode" for machineKey tag in web.config in BOTH projects
for example <machineKey compatibilityMode="Framework20SP1" validationKey="..."/>
validationKey, decryptionKey, validation and description should be the same in both sites.
Then I had rewrite methods Protect
public string Protect(AuthenticationTicket data)
{
var ticket = new FormsAuthenticationTicket(
2, data.Identity.Name,
DateTime.Now, DateTime.Now.AddMinutes(2880), true, "");
var ret = FormsAuthentication.Encrypt(ticket);
return ret;
}
because the ticked described by Alex Yang was "dead" (expired), and Unprotect
public AuthenticationTicket Unprotect(string protectedText)
{
var ticket = FormsAuthentication.Decrypt(protectedText);
var mngr = HttpContext.Current.GetOwinContext()
.GetUserManager<AppUserManager>();
var user = mngr.FindByName(ticket.Name);
var identity = mngr.CreateIdentity(
user, DefaultAuthenticationTypes.ApplicationCookie);
return new AuthenticationTicket(identity, new AuthenticationProperties());
}
because OnValidateIdentity didnt work properly for me and Alex Yang created for output new FormsAuthenticationIdentity, but i needed ClaimsIdentity.
If you want to use version by Alex Yang, dont forget add method used in OnValidateIdentity that he had forgot to describe :) Add it to your AppUser class
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
UserManager<AppUser> manager)
{
// Note the authenticationType must match the one
// defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity =
await manager.CreateIdentityAsync(this,
DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
After i done that, in both sites .ASPXAUTH cookie was accepted/generated right.

Restrict Auth & Session Cookies to a Subdomain in ASP.NET MVC5

I have a multi-tenanted application with several clients, who are distinguished by subdomain:
client1.mydomain.com
client2.mydomain.com
etc
I'm using forms authentication and the ASP.NET Auth & Session cookies on the client are set for the subdomain, e.g. client1.mydomain.com. This means that if I browse to client2.mydomain.com then I'm not logged in and the browser doesn't post the client1 cookies. Which is as it should be.
However something that has been picked up by our security testing is that you can take the cookie values from client1 and use the values to create cookies for client2 (we've done this in firebug). ASP.NET accepts these cookies and thinks you're authorised on client2.
How can I configure ASP.NET so that this doesn't happen?
The forms element in web.config allows you to set domain but I can't use this as I've a multi-tenanted app. I'm setting the cookie with
FormsAuthentication.SetAuthCookie(userName, false);
but I don't see a why to limit this to subdomain.
You should add the domain name to the user data of the cookie. To do this you have to switch to another cookie api:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
... other parameters ..., domain );
HttpCookie cookie = new HttpCookie( FormsAuthentication.FormsCookieName );
cookie.Value = FormsAuthentication.Encrypt( ticket );
Response.SetCookie( cookie );
Then, in your global application class have an event handler that fires after the identity is established for the request. In the handler, verify that the domain name in the cookie is equal to a domain of the current request:
public void Application_PostAuthorizeRequest( object sender, EventArgs e )
{
HttpApplication app = sender as HttpApplication;
HttpContext ctx = app.Context;
if ( ctx.User.Identity.IsAuthenticated )
{
// current domain
string currentDomain = ctx.Request.Url.... // get the domain
// domain from cookie
FormsIdentity id = (FormsIdentity)ctx.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string cookieDomain = ticket.UserData;
if ( currentDomain != cookieDomain )
throw new Exception( "break the execution of the current request" );
...
This check will validate if the cookie was issued for the current domain or rather someone tries to reuse cookies between different domains.

Persistent cookie not acting very persistent

I have implemented a custom membership provider and now I wish to provide my users with the option to let the website remember them, so they do not have to log in every single time they visit.
I've set my cookie to persistent, but it is not acting very persistent. When I close the browser and open it again after logging in the website requires that I log in again.
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
model.UserName,
DateTime.Now,
(model.RememberMe == true ? DateTime.Now.AddDays(7) : DateTime.Now.AddMinutes(60)),
model.RememberMe,
userData);
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
Response.Cookies.Add(cookie);
return RedirectToAction("Index", "Home");
model.RememberMe is in this case a boolean with the value of true, proven by the Visual Studio debugger.
Am I doing something blatantly wrong here?
In the end it turned out that I had to specify the expiration for the cookie aswell, as pointed out by Slicksim's comment from Feb 7 '13.

OpenId ASP MVC Authentication with long expiry

Stackoverflow uses OpenId as many other websites. However, I rarely need to provide my OpenId to Stackoverflow while with other OpenId enabled websites, I have to do it once a day or week.
This suggests to me that the expiry of the session is with the website and not the OpenId provider.
Looking at the DotNetOpenId code in ASP MVC, I can see that after a successful authentication by the OpenId provider FormsAuthentication.SetAuthCookie is called with the identifier and a boolean parameter to determine if the cookie should be persisted.
How can I force this cookie to expire, say in 2020 instead of whatever the default value is.
From MSDN - Explained: Forms Authentication in ASP.NET 2.0:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
"userName",
DateTime.Now,
new DateTime(2020, 01, 01), // value of time out property
false, // Value of IsPersistent property
String.Empty,
FormsAuthentication.FormsCookiePath);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie authCookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
encryptedTicket);
authCookie.Secure = true;
Response.Cookies.Add(authCookie);
You can use FormsAuthentication.RenewTicketIfOld() to update the ticket. This method would check if the current ticket has expired and if not, to extend its expiration. You can call this method on every request to your site, which will "slide" th expiration further in future as the user keeps using your site.

Resources