128 lines
5.3 KiB
C#
128 lines
5.3 KiB
C#
using System.Threading.Tasks;
|
|
using Microsoft.Owin.Security;
|
|
using Microsoft.Owin.Security.Cookies;
|
|
using Microsoft.Owin.Security.Infrastructure;
|
|
using Umbraco.Core;
|
|
using Umbraco.Core.Security;
|
|
|
|
namespace Umbraco.Web.Security
|
|
{
|
|
/// <summary>
|
|
/// If a flag is set on the context to force renew the ticket, this will do it
|
|
/// </summary>
|
|
internal class ForceRenewalCookieAuthenticationHandler : AuthenticationHandler<CookieAuthenticationOptions>
|
|
{
|
|
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
|
|
|
public ForceRenewalCookieAuthenticationHandler(IUmbracoContextAccessor umbracoContextAccessor)
|
|
{
|
|
_umbracoContextAccessor = umbracoContextAccessor;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This handler doesn't actually do any auth so we return null;
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
|
|
{
|
|
return Task.FromResult((AuthenticationTicket)null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the ticket from the request
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private AuthenticationTicket GetTicket()
|
|
{
|
|
var cookie = Options.CookieManager.GetRequestCookie(Context, Options.CookieName);
|
|
if (string.IsNullOrWhiteSpace(cookie))
|
|
{
|
|
return null;
|
|
}
|
|
var ticket = Options.TicketDataFormat.Unprotect(cookie);
|
|
if (ticket == null)
|
|
{
|
|
return null;
|
|
}
|
|
return ticket;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This will check if the token exists in the request to force renewal
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected override Task ApplyResponseGrantAsync()
|
|
{
|
|
if (_umbracoContextAccessor.UmbracoContext == null || Context.Request.Uri.IsClientSideRequest())
|
|
{
|
|
return Task.FromResult(0);
|
|
}
|
|
|
|
//Now we need to check if we should force renew this based on a flag in the context and whether this is a request that is not normally renewed by OWIN...
|
|
// which means that it is not a normal URL that is authenticated.
|
|
|
|
var normalAuthUrl = ((BackOfficeCookieManager) Options.CookieManager)
|
|
.ShouldAuthenticateRequest(Context, _umbracoContextAccessor.UmbracoContext.OriginalRequestUrl,
|
|
//Pass in false, we want to know if this is a normal auth'd page
|
|
checkForceAuthTokens: false);
|
|
//This is auth'd normally, so OWIN will naturally take care of the cookie renewal
|
|
if (normalAuthUrl) return Task.FromResult(0);
|
|
|
|
var httpCtx = Context.TryGetHttpContext();
|
|
//check for the special flag in either the owin or http context
|
|
var shouldRenew = Context.Get<bool?>(Constants.Security.ForceReAuthFlag) != null || (httpCtx.Success && httpCtx.Result.Items[Constants.Security.ForceReAuthFlag] != null);
|
|
|
|
if (shouldRenew)
|
|
{
|
|
var signin = Helper.LookupSignIn(Options.AuthenticationType);
|
|
var shouldSignin = signin != null;
|
|
var signout = Helper.LookupSignOut(Options.AuthenticationType, Options.AuthenticationMode);
|
|
var shouldSignout = signout != null;
|
|
|
|
//we don't care about the sign in/sign out scenario, only renewal
|
|
if (shouldSignin == false && shouldSignout == false)
|
|
{
|
|
//get the ticket
|
|
var ticket = GetTicket();
|
|
if (ticket != null)
|
|
{
|
|
var currentUtc = Options.SystemClock.UtcNow;
|
|
var issuedUtc = ticket.Properties.IssuedUtc;
|
|
var expiresUtc = ticket.Properties.ExpiresUtc;
|
|
|
|
if (expiresUtc.HasValue && issuedUtc.HasValue)
|
|
{
|
|
var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
|
|
var timeRemaining = expiresUtc.Value.Subtract(currentUtc);
|
|
|
|
//if it's time to renew, then do it
|
|
if (timeRemaining < timeElapsed)
|
|
{
|
|
//renew the date/times
|
|
ticket.Properties.IssuedUtc = currentUtc;
|
|
var timeSpan = expiresUtc.Value.Subtract(issuedUtc.Value);
|
|
ticket.Properties.ExpiresUtc = currentUtc.Add(timeSpan);
|
|
|
|
//now save back all the required cookie details
|
|
var cookieValue = Options.TicketDataFormat.Protect(ticket);
|
|
|
|
var cookieOptions = ((UmbracoBackOfficeCookieAuthOptions)Options).CreateRequestCookieOptions(Context, ticket);
|
|
|
|
Options.CookieManager.AppendResponseCookie(
|
|
Context,
|
|
Options.CookieName,
|
|
cookieValue,
|
|
cookieOptions);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Task.FromResult(0);
|
|
}
|
|
}
|
|
}
|