using System; using System.Web; using System.Web.Security; using Newtonsoft.Json; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; namespace Umbraco.Core.Security { internal static class FormsAuthenticationTicketExtensions { public static UmbracoBackOfficeIdentity CreateUmbracoIdentity(this FormsAuthenticationTicket ticket) { try { //create the Umbraco user identity return new UmbracoBackOfficeIdentity(ticket); } catch (Exception ex) { //This might occur if we cannot decrypt the value in which case we'll just ignore it, it will // be handled by the base pages LogHelper.Error(typeof(FormsAuthenticationTicketExtensions), "An error occurred decrypting the user's ticket", ex); return null; } } } /// /// Extensions to create and renew and remove authentication tickets for the Umbraco back office /// internal static class AuthenticationExtensions { //public static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContextBase http) //{ // return http.User.Identity as UmbracoBackOfficeIdentity; //} //internal static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContext http) //{ // return new HttpContextWrapper(http).GetCurrentIdentity(); //} /// /// This clears the authentication cookie /// public static void UmbracoLogout(this HttpContextBase http) { Logout(http, UmbracoSettings.AuthCookieName); } internal static void UmbracoLogout(this HttpContext http) { new HttpContextWrapper(http).UmbracoLogout(); } /// /// Creates the umbraco authentication ticket /// /// /// public static void CreateUmbracoAuthTicket(this HttpContextBase http, UserData userdata) { CreateAuthTicket( http, userdata, //This is one full day... this is how Umbraco has always created this cookie, it is setup to always //expire one day from issue and it never gets updated. 1440, "/", UmbracoSettings.AuthCookieName, UmbracoSettings.AuthCookieDomain); } internal static void CreateUmbracoAuthTicket(this HttpContext http, UserData userdata) { new HttpContextWrapper(http).CreateUmbracoAuthTicket(userdata); } /// /// Gets the umbraco auth ticket /// /// /// public static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContextBase http) { return GetAuthTicket(http, UmbracoSettings.AuthCookieName); } internal static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContext http) { return new HttpContextWrapper(http).GetUmbracoAuthTicket(); } /// /// This clears the authentication cookie /// /// /// private static void Logout(this HttpContextBase http, string cookieName) { //clear the preview cookie too var cookies = new[] { cookieName, Constants.Web.PreviewCookieName }; foreach (var c in cookies) { //remove from the request http.Request.Cookies.Remove(c); //expire from the response var formsCookie = http.Response.Cookies[c]; if (formsCookie != null) { //this will expire immediately and be removed from the browser formsCookie.Expires = DateTime.Now.AddYears(-1); } else { //ensure there's def an expired cookie http.Response.Cookies.Add(new HttpCookie(c) { Expires = DateTime.Now.AddYears(-1) }); } } } /// /// In v6 this is a custom cookie, in v7 this is a real formsauth cookie. /// /// /// /// private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName) { var formsCookie = http.Request.Cookies[cookieName]; if (formsCookie == null) { return null; } try { //get the cookie value var cookieVal = formsCookie.Value.DecryptWithMachineKey(); //here we need to see if the cookie val can be serialized into UserData, if not it means it's probably an old cookie var deserialized = JsonConvert.DeserializeObject(cookieVal); //in v6, we're not using real FormsAuth but our own custom cookie and then we just return a custom FormsAuth ticket // for this request. return new FormsAuthenticationTicket( 4, deserialized.RealName, DateTime.Now, DateTime.Now.AddMinutes(GlobalSettings.TimeOutInMinutes), false, cookieVal, "/"); } catch (Exception) { //occurs when decryption fails http.Logout(cookieName); return null; } } /// /// Creates a custom umbraco auth cookie with the data specified /// /// The HTTP. /// The user data. /// The minutes persisted. /// The cookie path. /// Name of the cookie. /// The cookie domain. private static void CreateAuthTicket(this HttpContextBase http, UserData userData, int minutesPersisted, string cookiePath, string cookieName, string cookieDomain) { var cookie = new HttpCookie(cookieName); if (GlobalSettings.UseSSL) cookie.Secure = true; //ensure http only, this should only be able to be accessed via the server cookie.HttpOnly = true; cookie.Path = cookiePath; cookie.Domain = cookieDomain; cookie.Expires = DateTime.Now.AddMinutes(minutesPersisted); //serialize the user data var json = JsonConvert.SerializeObject(userData); //encrypt it var encTicket = json.EncryptWithMachineKey(); //set the cookie value cookie.Value = encTicket; http.Response.Cookies.Set(cookie); } } }