Timeless
Timeless

Reputation: 7547

mvc3 change authentication value

I have stored authentication info inside the User.Identity.Name once the user log in to the system. using this method

FormsAuthentication.SetAuthCookie(Id + " | " + Name + " | " + Language + " | " + Culture + " | " + Email + " | " + Role+ " | " + TimeOffset+ " | " + Rights, RememberMe);

Now I want to change the some value inside User.Identity.Name when user change some configutation setting, eg Language

But after calling the FormsAuthentication.SetAuthCookie(), the value inside the User.Identity.Name does not change anymore

string identity = HttpContext.Current.User.Identity.Name; // modify current value
FormsAuthentication.SetAuthCookie(identity, false); // assign new value

How can I change this value?

Upvotes: 1

Views: 539

Answers (1)

moribvndvs
moribvndvs

Reputation: 42497

SetAuthCookie updates the cookie containing the FormsAuth ticket with the updated value, but it does not set the User of the current context. You can change the user of the current context by creating a new IPrincipal and IIdentity. It's as simple as getting the current HttpContext and setting the User property.

You'd normally do this in an IHttpModule or Global.asax.cs in the PostAuthenticateRequest event, because at this point FormsAuth will already have authenticated the user's ticket and set the identity. After this event, the new IPrincipal you created will be available to the application for the remainder of the request.

protected void Application_PostAuthenticateRequest(object sender, EventArgs args)
{
    var application = (HttpApplication)sender;
    var context = application.Context;

    if (context.User != null || !context.User.Identity.IsAuthenticated) return; // user not authenticated, so you don't need to do anything else

    // Here, you'd process the existing context.User.Identity.Name and split out the values you need. that part is up to you. in my example here, I'll just show you creating a new principal
    var oldUserName = context.User.Identity.Name;
    context.User = new GenericPrincipal(new GenericIdentity(oldUserName, "Forms"), new string[0]); 
}

As an aside, I don't recommend packing values in the identity name, but rather the ticket's UserData property. In that case, you can check if the context.User.Identity is FormsIdentity and access Ticket.UserData:

protected void Application_PostAuthenticateRequest(object sender, EventArgs args)
{
    var application = (HttpApplication)sender;
    var context = application.Context;

    if (context.User != null || !context.User.Identity.IsAuthenticated) return; // user not authenticated, so you don't need to do anything else

    var formsIdentity = context.User.Identity as FormsIdentity;

    if (formsIdentity == null) return; // not a forms identity, so we can't do any further processing

    var ticket = formsIdentity.Ticket;

    // now you can access ticket.UserData
    // to add your own values to UserData, you'll have to create the ticket manually when you first log the user in

    var values = ticket.UserData.Split('|');

    // etc.
    // I'll pretend the second element values is a comma-delimited list of roles for the user, just to illustrate my point
    var roles = values[1].Split(',');


    context.User = new GenericPrincipal(new GenericIdentity(ticket.Name, "Forms"), roles); 
}

Here is some more info on creating FormsAuth tickets with custom values in UserData.

Upvotes: 1

Related Questions