using System; using Microsoft.Owin.Security; using Umbraco.Core.Security; namespace Umbraco.Web.Security { /// /// Custom secure format that ensures the Identity in the ticket is and not just a ClaimsIdentity /// internal class UmbracoSecureDataFormat : ISecureDataFormat { private readonly int _loginTimeoutMinutes; private readonly ISecureDataFormat _ticketDataFormat; public UmbracoSecureDataFormat(int loginTimeoutMinutes, ISecureDataFormat ticketDataFormat) { _loginTimeoutMinutes = loginTimeoutMinutes; _ticketDataFormat = ticketDataFormat ?? throw new ArgumentNullException(nameof(ticketDataFormat)); } public string Protect(AuthenticationTicket data) { var backofficeIdentity = (UmbracoBackOfficeIdentity)data.Identity; //create a new ticket based on the passed in tickets details, however, we'll adjust the expires utc based on the specified timeout mins var ticket = new AuthenticationTicket(backofficeIdentity, new AuthenticationProperties(data.Properties.Dictionary) { IssuedUtc = data.Properties.IssuedUtc, ExpiresUtc = data.Properties.ExpiresUtc ?? DateTimeOffset.UtcNow.AddMinutes(_loginTimeoutMinutes), AllowRefresh = data.Properties.AllowRefresh, IsPersistent = data.Properties.IsPersistent, RedirectUri = data.Properties.RedirectUri }); return _ticketDataFormat.Protect(ticket); } /// /// Un-protects the cookie /// /// /// public AuthenticationTicket Unprotect(string protectedText) { AuthenticationTicket decrypt; try { decrypt = _ticketDataFormat.Unprotect(protectedText); if (decrypt == null) return null; } catch (Exception) { return null; } UmbracoBackOfficeIdentity identity; try { identity = UmbracoBackOfficeIdentity.FromClaimsIdentity(decrypt.Identity); } catch (Exception) { //if it cannot be created return null, will be due to serialization errors in user data most likely due to corrupt cookies or cookies //for previous versions of Umbraco return null; } //return the ticket with a UmbracoBackOfficeIdentity var ticket = new AuthenticationTicket(identity, decrypt.Properties); return ticket; } } }