/// <summary> /// This will return the current back office identity if the IPrincipal is the correct type /// </summary> /// <param name="user"></param> /// <returns></returns> internal static UmbracoBackOfficeIdentity GetUmbracoIdentity(this IPrincipal user) { //If it's already a UmbracoBackOfficeIdentity if (user.Identity is UmbracoBackOfficeIdentity backOfficeIdentity) { return(backOfficeIdentity); } //Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that if (user is ClaimsPrincipal claimsPrincipal) { backOfficeIdentity = claimsPrincipal.Identities.OfType <UmbracoBackOfficeIdentity>().FirstOrDefault(); if (backOfficeIdentity != null) { return(backOfficeIdentity); } } //Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session if (user.Identity is ClaimsIdentity claimsIdentity && claimsIdentity.IsAuthenticated && claimsIdentity.HasClaim(x => x.Type == Constants.Security.SessionIdClaimType)) { try { return(UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity)); } catch (InvalidOperationException) { } } return(null); }
/// <summary> /// Used for cloning /// </summary> /// <param name="identity"></param> private UmbracoBackOfficeIdentity(UmbracoBackOfficeIdentity identity) : base(identity) { if (identity.Actor != null) { _currentIssuer = identity.AuthenticationType; AddExistingClaims(identity); Actor = identity.Clone(); } UserData = identity.UserData; AddUserDataClaims(); }
/// <summary> /// This will check the ticket to see if it is valid, if it is it will set the current thread's user and culture /// </summary> /// <param name="http"></param> /// <param name="ticket"></param> /// <param name="renewTicket">If true will attempt to renew the ticket</param> public static bool AuthenticateCurrentRequest(this HttpContextBase http, FormsAuthenticationTicket ticket, bool renewTicket) { if (http == null) { throw new ArgumentNullException("http"); } //if there was a ticket, it's not expired, - it should not be renewed or its renewable if (ticket != null && ticket.Expired == false && (renewTicket == false || http.RenewUmbracoAuthTicket())) { try { //create the Umbraco user identity var identity = new UmbracoBackOfficeIdentity(ticket); //set the principal object var principal = new GenericPrincipal(identity, identity.Roles); //It is actually not good enough to set this on the current app Context and the thread, it also needs // to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually // an underlying fault of asp.net not propogating the User correctly. if (HttpContext.Current != null) { HttpContext.Current.User = principal; } http.User = principal; Thread.CurrentPrincipal = principal; //This is a back office request, we will also set the culture/ui culture Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(identity.Culture); return(true); } catch (Exception ex) { if (ex is FormatException || ex is JsonReaderException) { //this will occur if the cookie data is invalid http.UmbracoLogout(); } else { throw; } } } return(false); }
/// <summary> /// This will check the ticket to see if it is valid, if it is it will set the current thread's user and culture /// </summary> /// <param name="http"></param> /// <param name="ticket"></param> /// <param name="renewTicket">If true will attempt to renew the ticket</param> public static bool AuthenticateCurrentRequest(this HttpContextBase http, FormsAuthenticationTicket ticket, bool renewTicket) { if (http == null) throw new ArgumentNullException("http"); //if there was a ticket, it's not expired, - it should not be renewed or its renewable if (ticket != null && ticket.Expired == false && (renewTicket == false || http.RenewUmbracoAuthTicket())) { try { //create the Umbraco user identity var identity = new UmbracoBackOfficeIdentity(ticket); //set the principal object var principal = new GenericPrincipal(identity, identity.Roles); //It is actually not good enough to set this on the current app Context and the thread, it also needs // to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually // an underlying fault of asp.net not propogating the User correctly. if (HttpContext.Current != null) { HttpContext.Current.User = principal; } http.User = principal; Thread.CurrentPrincipal = principal; //This is a back office request, we will also set the culture/ui culture Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(identity.Culture); return true; } catch (Exception ex) { if (ex is FormatException || ex is JsonReaderException) { //this will occur if the cookie data is invalid http.UmbracoLogout(); } else { throw; } } } return false; }
/// <summary> /// Create a ClaimsIdentity from a user /// </summary> /// <param name="manager"/><param name="user"/><param name="authenticationType"/> /// <returns/> public override async Task <ClaimsIdentity> CreateAsync(UserManager <BackOfficeIdentityUser, int> manager, BackOfficeIdentityUser user, string authenticationType) { var baseIdentity = await base.CreateAsync(manager, user, authenticationType); var umbracoIdentity = new UmbracoBackOfficeIdentity(baseIdentity, //set a new session id new UserData(Guid.NewGuid().ToString("N")) { Id = user.Id, Username = user.UserName, RealName = user.Name, AllowedApplications = user.AllowedSections, Culture = user.Culture, Roles = user.Roles.Select(x => x.RoleId).ToArray(), StartContentNode = user.StartContentId, StartMediaNode = user.StartMediaId }); return(umbracoIdentity); }
/// <summary> /// Create a ClaimsIdentity from a user /// </summary> /// <param name="manager"/><param name="user"/><param name="authenticationType"/> /// <returns/> public override async Task <ClaimsIdentity> CreateAsync(UserManager <T, int> manager, T user, string authenticationType) { var baseIdentity = await base.CreateAsync(manager, user, authenticationType); var umbracoIdentity = new UmbracoBackOfficeIdentity(baseIdentity, //set a new session id new UserData { Id = user.Id, Username = user.UserName, RealName = user.Name, AllowedApplications = user.AllowedSections, Culture = user.Culture, Roles = user.Roles.Select(x => x.RoleId).ToArray(), StartContentNodes = user.CalculatedContentStartNodeIds, StartMediaNodes = user.CalculatedMediaStartNodeIds, SessionId = user.SecurityStamp }); return(umbracoIdentity); }
/// <summary> /// Create a ClaimsIdentity from a user /// </summary> /// <param name="manager"/><param name="user"/><param name="authenticationType"/> /// <returns/> public override async Task <ClaimsIdentity> CreateAsync(UserManager <T, int> manager, T user, string authenticationType) { var baseIdentity = await base.CreateAsync(manager, user, authenticationType); var umbracoIdentity = new UmbracoBackOfficeIdentity(baseIdentity, //NOTE - there is no session id assigned here, this is just creating the identity, a session id will be generated when the cookie is written new UserData { Id = user.Id, Username = user.UserName, RealName = user.Name, AllowedApplications = user.AllowedSections, Culture = user.Culture, Roles = user.Roles.Select(x => x.RoleId).ToArray(), StartContentNodes = user.CalculatedContentStartNodeIds, StartMediaNodes = user.CalculatedMediaStartNodeIds, SecurityStamp = user.SecurityStamp }); return(umbracoIdentity); }
/// <summary> /// This will return the current back office identity. /// </summary> /// <param name="http"></param> /// <param name="authenticateRequestIfNotFound"> /// If set to true and a back office identity is not found and not authenticated, this will attempt to authenticate the /// request just as is done in the Umbraco module and then set the current identity if it is valid. /// Just like in the UmbracoModule, if this is true then the user's culture will be assigned to the request. /// </param> /// <returns> /// Returns the current back office identity if an admin is authenticated otherwise null /// </returns> public static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContextBase http, bool authenticateRequestIfNotFound) { if (http == null) { throw new ArgumentNullException("http"); } if (http.User == null) { return(null); //there's no user at all so no identity } //If it's already a UmbracoBackOfficeIdentity var backOfficeIdentity = http.User.Identity as UmbracoBackOfficeIdentity; if (backOfficeIdentity != null) { return(backOfficeIdentity); } //Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session var claimsIdentity = http.User.Identity as ClaimsIdentity; if (claimsIdentity != null && claimsIdentity.IsAuthenticated) { try { return(UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity)); } catch (InvalidOperationException ex) { //This will occur if the required claim types are missing which would mean something strange is going on LogHelper.Error(typeof(AuthenticationExtensions), "The current identity cannot be converted to " + typeof(UmbracoBackOfficeIdentity), ex); } } if (authenticateRequestIfNotFound == false) { return(null); } //even if authenticateRequestIfNotFound is true we cannot continue if the request is actually authenticated // which would mean something strange is going on that it is not an umbraco identity. if (http.User.Identity.IsAuthenticated) { return(null); } //So the user is not authed but we've been asked to do the auth if authenticateRequestIfNotFound = true, // which might occur in old webforms style things or for routes that aren't included as a back office request. // in this case, we are just reverting to authing using the cookie. // TODO: Even though this is in theory legacy, we have legacy bits laying around and we'd need to do the auth based on // how the Module will eventually do it (by calling in to any registered authenticators). var ticket = http.GetUmbracoAuthTicket(); if (http.AuthenticateCurrentRequest(ticket, true)) { //now we 'should have an umbraco identity return(http.User.Identity as UmbracoBackOfficeIdentity); } return(null); }