Files
Umbraco-CMS/src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs
2024-04-04 11:25:13 +02:00

100 lines
3.4 KiB
C#

// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Globalization;
using System.Security.Claims;
using System.Security.Principal;
using Umbraco.Cms.Core;
namespace Umbraco.Extensions;
public static class ClaimsPrincipalExtensions
{
public static bool IsBackOfficeAuthenticationType(this ClaimsIdentity? claimsIdentity)
{
if (claimsIdentity is null)
{
return false;
}
return claimsIdentity.IsAuthenticated &&
claimsIdentity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType;
}
/// <summary>
/// This will return the current back office identity if the IPrincipal is the correct type and authenticated.
/// </summary>
/// <param name="principal"></param>
/// <returns></returns>
public static ClaimsIdentity? GetUmbracoIdentity(this IPrincipal principal)
{
// If it's already a UmbracoBackOfficeIdentity
if (principal.Identity is ClaimsIdentity claimsIdentity
&& claimsIdentity.IsBackOfficeAuthenticationType()
&& claimsIdentity.VerifyBackOfficeIdentity(out ClaimsIdentity? backOfficeIdentity))
{
return backOfficeIdentity;
}
// Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that
// We can have assigned more identities if it is a preview request.
if (principal is ClaimsPrincipal claimsPrincipal)
{
ClaimsIdentity? identity =
claimsPrincipal.Identities.FirstOrDefault(x => x.IsBackOfficeAuthenticationType());
if (identity is not null)
{
claimsIdentity = identity;
if (claimsIdentity.VerifyBackOfficeIdentity(out backOfficeIdentity))
{
return backOfficeIdentity;
}
}
}
// Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd
if (principal.Identity is ClaimsIdentity claimsIdentity2
&& claimsIdentity2.VerifyBackOfficeIdentity(out backOfficeIdentity))
{
return backOfficeIdentity;
}
return null;
}
/// <summary>
/// Returns the remaining seconds on an auth ticket for the user based on the claim applied to the user durnig
/// authentication
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public static double GetRemainingAuthSeconds(this IPrincipal user) =>
user.GetRemainingAuthSeconds(DateTimeOffset.UtcNow);
/// <summary>
/// Returns the remaining seconds on an auth ticket for the user based on the claim applied to the user durnig
/// authentication
/// </summary>
/// <param name="user"></param>
/// <param name="now"></param>
/// <returns></returns>
public static double GetRemainingAuthSeconds(this IPrincipal user, DateTimeOffset now)
{
if (user is not ClaimsPrincipal claimsPrincipal)
{
return 0;
}
var ticketExpires = claimsPrincipal.FindFirst(Constants.Security.TicketExpiresClaimType)?.Value;
if (ticketExpires.IsNullOrWhiteSpace())
{
return 0;
}
var utcExpired = DateTimeOffset.Parse(ticketExpires!, null, DateTimeStyles.RoundtripKind);
var secondsRemaining = utcExpired.Subtract(now).TotalSeconds;
return secondsRemaining;
}
}