Reputation: 4158
I have an MVC app which I'm having trouble ex[posing a custom principal to my views. It has the following classes that help me manage auth cookies.
public class AuthenticationManager
{
public void SetAuthCookie(UserViewModel user)
{
var serializeModel = new CustomPrincipalSerializeModel
{
Id = user.UserId,
Email = user.Email,
Name = user.Name
};
var serializer = new JavaScriptSerializer();
var customPrincipal = customPrincipalMapper.Convert(serializeModel);
var httpContext = ContextHelper.GetHttpContextBase();
httpContext.User = customPrincipal;
var userData = serializer.Serialize(serializeModel);
var authTicket = new FormsAuthenticationTicket(1, serializeModel.Email, DateTime.Now, DateTime.Now.AddYears(5), false, userData);
var encTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
httpContext.Response.Cookies.Add(authCookie);
}
}
public static class ContextHelper
{
public static HttpContextBase GetHttpContextBase()
{
return new HttpContextWrapper(HttpContext.Current);
}
}
I also have the following BaseViewPage
classes which allow me to expose the current user to my views:
public abstract class BaseViewPage : WebViewPage
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
FWIW, this requires <pages pageBaseType="Giftster.Web.Views.BaseViewPage">
to be in my View's Web.config file.
Immediately, after the httpContext.User = customPrincipal;
line runs in AuthenticationManager.SetAuthCookie()
, the type of object which ContextHelper.GetHttpContextBase().User
returns is a CustomPrincipal
. If I refresh the page, however, and put a break point in BaseViewPage
, base.User as CustomPrincipal
(and ContextHelper.GetHttpContextBase().User as CustomPrincipal
for that matter) equals null. base.User
is not null, though: It is of type GenericPrincipal
, so there is either a casting issue or a problem with storing/retrieving the correct type.
Why is base.User
in my BaseViewPage
not of type CustomPrincipal
?
Thanks in advance.
Upvotes: 0
Views: 192
Reputation:
You need to create your CustomPrincipal
from the cookie in each request and add it to the current context. Add the following to the Global.asax.cs
file
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
// Get the authentication cookie
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
// If the cookie can't be found, don't issue the ticket
if (authCookie == null)
{
return;
}
// Extract the forms authentication cookie
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
// Deserialise user data
JavaScriptSerializer serializer = new JavaScriptSerializer();
CustomPrincipalSerializeModel data = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);
// Create principal
CustomPrincipal principal = new CustomPrincipal(authTicket.Name);
// Set the properties of CustomPrincipal
principal.Email = data.Email;
.... // etc
// Assign to current context
HttpContext.Current.User = principal;
}
Note also the following line is not required in you SetAuthCookie()
method
httpContext.User = customPrincipal;
You might also consider adding the following to a BaseController
(from which all other controllers derive) so the CustomPrincipal
properties can be accessed easily in each controller method
public new CustomPrincipalSerializeModel User
{
get { return (CustomPrincipal)HttpContext.User; }
}
Upvotes: 1