using System; using Microsoft.Owin.Security; using Umbraco.Core.BackOffice; 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; } if (!UmbracoBackOfficeIdentity.FromClaimsIdentity(decrypt.Identity, out var identity)) return null; //return the ticket with a UmbracoBackOfficeIdentity var ticket = new AuthenticationTicket(identity, decrypt.Properties); return ticket; } } }