Merge pull request #9833 from umbraco/9622-remove-backofficeidentity

Netcore: Remove UmbracoBackOfficeIdentity
This commit is contained in:
Bjarke Berg
2021-02-23 11:29:23 +01:00
committed by GitHub
20 changed files with 432 additions and 364 deletions

View File

@@ -2,8 +2,11 @@
// See LICENSE for more details.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using Umbraco.Cms.Core;
namespace Umbraco.Extensions
{
@@ -72,5 +75,271 @@ namespace Umbraco.Extensions
return identity.FindFirst(claimType)?.Value;
}
/// <summary>
/// Returns the required claim types for a back office identity
/// </summary>
/// <remarks>
/// This does not include the role claim type or allowed apps type since that is a collection and in theory could be empty
/// </remarks>
public static IEnumerable<string> RequiredBackOfficeClaimTypes => new[]
{
ClaimTypes.NameIdentifier, //id
ClaimTypes.Name, //username
ClaimTypes.GivenName,
// Constants.Security.StartContentNodeIdClaimType, These seem to be able to be null...
// Constants.Security.StartMediaNodeIdClaimType,
ClaimTypes.Locality,
Constants.Security.SecurityStampClaimType
};
/// <summary>
/// Verify that a ClaimsIdentity has all the required claim types
/// </summary>
/// <param name="identity"></param>
/// <param name="verifiedIdentity">Verified identity wrapped in a ClaimsIdentity with BackOfficeAuthentication type</param>
/// <returns>True if ClaimsIdentity</returns>
public static bool VerifyBackOfficeIdentity(this ClaimsIdentity identity, out ClaimsIdentity verifiedIdentity)
{
// Validate that all required claims exist
foreach (var claimType in RequiredBackOfficeClaimTypes)
{
if (identity.HasClaim(x => x.Type == claimType) == false ||
identity.HasClaim(x => x.Type == claimType && x.Value.IsNullOrWhiteSpace()))
{
verifiedIdentity = null;
return false;
}
}
verifiedIdentity = new ClaimsIdentity(identity.Claims, Constants.Security.BackOfficeAuthenticationType);
return true;
}
/// <summary>
/// Add the required claims to be a BackOffice ClaimsIdentity
/// </summary>
/// <param name="identity">this</param>
/// <param name="userId">The users Id</param>
/// <param name="username">Username</param>
/// <param name="realName">Real name</param>
/// <param name="startContentNodes">Start content nodes</param>
/// <param name="startMediaNodes">Start media nodes</param>
/// <param name="culture">The locality of the user</param>
/// <param name="securityStamp">Security stamp</param>
/// <param name="allowedApps">Allowed apps</param>
/// <param name="roles">Roles</param>
public static void AddRequiredClaims(this ClaimsIdentity identity, string userId, string username,
string realName, IEnumerable<int> startContentNodes, IEnumerable<int> startMediaNodes, string culture,
string securityStamp, IEnumerable<string> allowedApps, IEnumerable<string> roles)
{
//This is the id that 'identity' uses to check for the user id
if (identity.HasClaim(x => x.Type == ClaimTypes.NameIdentifier) == false)
{
identity.AddClaim(new Claim(
ClaimTypes.NameIdentifier,
userId,
ClaimValueTypes.String,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
if (identity.HasClaim(x => x.Type == ClaimTypes.Name) == false)
{
identity.AddClaim(new Claim(
ClaimTypes.Name,
username,
ClaimValueTypes.String,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
if (identity.HasClaim(x => x.Type == ClaimTypes.GivenName) == false)
{
identity.AddClaim(new Claim(
ClaimTypes.GivenName,
realName,
ClaimValueTypes.String,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
if (identity.HasClaim(x => x.Type == Constants.Security.StartContentNodeIdClaimType) == false &&
startContentNodes != null)
{
foreach (var startContentNode in startContentNodes)
{
identity.AddClaim(new Claim(
Constants.Security.StartContentNodeIdClaimType,
startContentNode.ToInvariantString(),
ClaimValueTypes.Integer32,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
}
if (identity.HasClaim(x => x.Type == Constants.Security.StartMediaNodeIdClaimType) == false &&
startMediaNodes != null)
{
foreach (var startMediaNode in startMediaNodes)
{
identity.AddClaim(new Claim(
Constants.Security.StartMediaNodeIdClaimType,
startMediaNode.ToInvariantString(),
ClaimValueTypes.Integer32,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
}
if (identity.HasClaim(x => x.Type == ClaimTypes.Locality) == false)
{
identity.AddClaim(new Claim(
ClaimTypes.Locality,
culture,
ClaimValueTypes.String,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
// The security stamp claim is also required
if (identity.HasClaim(x => x.Type == Constants.Security.SecurityStampClaimType) == false)
{
identity.AddClaim(new Claim(
Constants.Security.SecurityStampClaimType,
securityStamp,
ClaimValueTypes.String,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
// Add each app as a separate claim
if (identity.HasClaim(x => x.Type == Constants.Security.AllowedApplicationsClaimType) == false &&
allowedApps != null)
{
foreach (var application in allowedApps)
{
identity.AddClaim(new Claim(
Constants.Security.AllowedApplicationsClaimType,
application,
ClaimValueTypes.String,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
}
// Claims are added by the ClaimsIdentityFactory because our UserStore supports roles, however this identity might
// not be made with that factory if it was created with a different ticket so perform the check
if (identity.HasClaim(x => x.Type == ClaimsIdentity.DefaultRoleClaimType) == false && roles != null)
{
// Manually add them
foreach (var roleName in roles)
{
identity.AddClaim(new Claim(
identity.RoleClaimType,
roleName,
ClaimValueTypes.String,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
identity));
}
}
}
/// <summary>
/// Get the start content nodes from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>Array of start content nodes</returns>
public static int[] GetStartContentNodes(this ClaimsIdentity identity) =>
identity.FindAll(x => x.Type == Constants.Security.StartContentNodeIdClaimType)
.Select(node => int.TryParse(node.Value, out var i) ? i : default)
.Where(x => x != default).ToArray();
/// <summary>
/// Get the start media nodes from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>Array of start media nodes</returns>
public static int[] GetStartMediaNodes(this ClaimsIdentity identity) =>
identity.FindAll(x => x.Type == Constants.Security.StartMediaNodeIdClaimType)
.Select(node => int.TryParse(node.Value, out var i) ? i : default)
.Where(x => x != default).ToArray();
/// <summary>
/// Get the allowed applications from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns></returns>
public static string[] GetAllowedApplications(this ClaimsIdentity identity) => identity
.FindAll(x => x.Type == Constants.Security.AllowedApplicationsClaimType).Select(app => app.Value).ToArray();
/// <summary>
/// Get the user ID from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>User ID as integer</returns>
public static int GetId(this ClaimsIdentity identity) => int.Parse(identity.FindFirstValue(ClaimTypes.NameIdentifier));
/// <summary>
/// Get the real name belonging to the user from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>Real name of the user</returns>
public static string GetRealName(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.GivenName);
/// <summary>
/// Get the username of the user from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>Username of the user</returns>
public static string GetUsername(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.Name);
/// <summary>
/// Get the culture string from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>Culture string</returns>
public static string GetCultureString(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.Locality);
/// <summary>
/// Get the security stamp from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>Security stamp</returns>
public static string GetSecurityStamp(this ClaimsIdentity identity) => identity.FindFirstValue(Constants.Security.SecurityStampClaimType);
/// <summary>
/// Get the roles assigned to a user from a ClaimsIdentity
/// </summary>
/// <param name="identity"></param>
/// <returns>Array of roles</returns>
public static string[] GetRoles(this ClaimsIdentity identity) => identity
.FindAll(x => x.Type == ClaimsIdentity.DefaultRoleClaimType).Select(role => role.Value).ToArray();
/// <summary>
/// Adds or updates and existing claim.
/// </summary>
public static void AddOrUpdateClaim(this ClaimsIdentity identity, Claim claim)
{
if (identity == null)
{
throw new ArgumentNullException(nameof(identity));
}
Claim existingClaim = identity.Claims.FirstOrDefault(x => x.Type == claim.Type);
identity.TryRemoveClaim(existingClaim);
identity.AddClaim(claim);
}
}
}

View File

@@ -2,9 +2,9 @@
// See LICENSE for more details.
using System.Globalization;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading;
using Umbraco.Cms.Core.Security;
namespace Umbraco.Extensions
{
@@ -24,9 +24,9 @@ namespace Umbraco.Extensions
public static CultureInfo GetCulture(this IIdentity identity)
{
if (identity is UmbracoBackOfficeIdentity umbIdentity && umbIdentity.IsAuthenticated)
if (identity is ClaimsIdentity umbIdentity && umbIdentity.VerifyBackOfficeIdentity(out _) && umbIdentity.IsAuthenticated)
{
return CultureInfo.GetCultureInfo(umbIdentity.Culture);
return CultureInfo.GetCultureInfo(umbIdentity.GetCultureString());
}
return null;

View File

@@ -14,29 +14,21 @@ namespace Umbraco.Extensions
public static class ClaimsPrincipalExtensions
{
/// <summary>
/// This will return the current back office identity if the IPrincipal is the correct type
/// This will return the current back office identity if the IPrincipal is the correct type and authenticated.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public static UmbracoBackOfficeIdentity GetUmbracoIdentity(this IPrincipal user)
public static ClaimsIdentity GetUmbracoIdentity(this IPrincipal user)
{
// TODO: It would be nice to get rid of this and only rely on Claims, not a strongly typed identity instance
//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
// Check if the identity is a ClaimsIdentity, and that's it's authenticated and has all required claims.
if (user.Identity is ClaimsIdentity claimsIdentity
&& claimsIdentity.IsAuthenticated
&& UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out var umbracoIdentity))
&& claimsIdentity.VerifyBackOfficeIdentity(out ClaimsIdentity umbracoIdentity))
{
if (claimsIdentity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType)
{
return claimsIdentity;
}
return umbracoIdentity;
}

View File

@@ -1,232 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.Security
{
/// <summary>
/// A custom user identity for the Umbraco backoffice
/// </summary>
[Serializable]
public class UmbracoBackOfficeIdentity : ClaimsIdentity
{
// TODO: Ideally we remove this class and only deal with ClaimsIdentity as a best practice. All things relevant to our own
// identity are part of claims. This class would essentially become extension methods on a ClaimsIdentity for resolving
// values from it.
public static bool FromClaimsIdentity(ClaimsIdentity identity, out UmbracoBackOfficeIdentity backOfficeIdentity)
{
// validate that all claims exist
foreach (var t in RequiredBackOfficeIdentityClaimTypes)
{
// if the identity doesn't have the claim, or the claim value is null
if (identity.HasClaim(x => x.Type == t) == false || identity.HasClaim(x => x.Type == t && x.Value.IsNullOrWhiteSpace()))
{
backOfficeIdentity = null;
return false;
}
}
backOfficeIdentity = new UmbracoBackOfficeIdentity(identity);
return true;
}
/// <summary>
/// Create a back office identity based on an existing claims identity
/// </summary>
/// <param name="identity"></param>
private UmbracoBackOfficeIdentity(ClaimsIdentity identity)
: base(identity.Claims, Constants.Security.BackOfficeAuthenticationType)
{
}
/// <summary>
/// Creates a new UmbracoBackOfficeIdentity
/// </summary>
/// <param name="userId"></param>
/// <param name="username"></param>
/// <param name="realName"></param>
/// <param name="startContentNodes"></param>
/// <param name="startMediaNodes"></param>
/// <param name="culture"></param>
/// <param name="securityStamp"></param>
/// <param name="allowedApps"></param>
/// <param name="roles"></param>
public UmbracoBackOfficeIdentity(string userId, string username, string realName,
IEnumerable<int> startContentNodes, IEnumerable<int> startMediaNodes, string culture,
string securityStamp, IEnumerable<string> allowedApps, IEnumerable<string> roles)
: base(Enumerable.Empty<Claim>(), Constants.Security.BackOfficeAuthenticationType) //this ctor is used to ensure the IsAuthenticated property is true
{
if (allowedApps == null)
throw new ArgumentNullException(nameof(allowedApps));
if (string.IsNullOrWhiteSpace(username))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(username));
if (string.IsNullOrWhiteSpace(realName))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(realName));
if (string.IsNullOrWhiteSpace(culture))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture));
if (string.IsNullOrWhiteSpace(securityStamp))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(securityStamp));
AddRequiredClaims(userId, username, realName, startContentNodes, startMediaNodes, culture, securityStamp, allowedApps, roles);
}
/// <summary>
/// Creates a new UmbracoBackOfficeIdentity
/// </summary>
/// <param name="childIdentity">
/// The original identity created by the ClaimsIdentityFactory
/// </param>
/// <param name="userId"></param>
/// <param name="username"></param>
/// <param name="realName"></param>
/// <param name="startContentNodes"></param>
/// <param name="startMediaNodes"></param>
/// <param name="culture"></param>
/// <param name="securityStamp"></param>
/// <param name="allowedApps"></param>
/// <param name="roles"></param>
public UmbracoBackOfficeIdentity(ClaimsIdentity childIdentity,
string userId, string username, string realName,
IEnumerable<int> startContentNodes, IEnumerable<int> startMediaNodes, string culture,
string securityStamp, IEnumerable<string> allowedApps, IEnumerable<string> roles)
: base(childIdentity.Claims, Constants.Security.BackOfficeAuthenticationType)
{
if (string.IsNullOrWhiteSpace(username))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(username));
if (string.IsNullOrWhiteSpace(realName))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(realName));
if (string.IsNullOrWhiteSpace(culture))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture));
if (string.IsNullOrWhiteSpace(securityStamp))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(securityStamp));
AddRequiredClaims(userId, username, realName, startContentNodes, startMediaNodes, culture, securityStamp, allowedApps, roles);
}
public const string Issuer = Constants.Security.BackOfficeAuthenticationType;
/// <summary>
/// Returns the required claim types for a back office identity
/// </summary>
/// <remarks>
/// This does not include the role claim type or allowed apps type since that is a collection and in theory could be empty
/// </remarks>
public static IEnumerable<string> RequiredBackOfficeIdentityClaimTypes => new[]
{
ClaimTypes.NameIdentifier, //id
ClaimTypes.Name, //username
ClaimTypes.GivenName,
Constants.Security.StartContentNodeIdClaimType,
Constants.Security.StartMediaNodeIdClaimType,
ClaimTypes.Locality,
Constants.Security.SecurityStampClaimType
};
/// <summary>
/// Adds claims based on the ctor data
/// </summary>
private void AddRequiredClaims(string userId, string username, string realName,
IEnumerable<int> startContentNodes, IEnumerable<int> startMediaNodes, string culture,
string securityStamp, IEnumerable<string> allowedApps, IEnumerable<string> roles)
{
//This is the id that 'identity' uses to check for the user id
if (HasClaim(x => x.Type == ClaimTypes.NameIdentifier) == false)
AddClaim(new Claim(ClaimTypes.NameIdentifier, userId, ClaimValueTypes.String, Issuer, Issuer, this));
if (HasClaim(x => x.Type == ClaimTypes.Name) == false)
AddClaim(new Claim(ClaimTypes.Name, username, ClaimValueTypes.String, Issuer, Issuer, this));
if (HasClaim(x => x.Type == ClaimTypes.GivenName) == false)
AddClaim(new Claim(ClaimTypes.GivenName, realName, ClaimValueTypes.String, Issuer, Issuer, this));
if (HasClaim(x => x.Type == Constants.Security.StartContentNodeIdClaimType) == false && startContentNodes != null)
{
foreach (var startContentNode in startContentNodes)
{
AddClaim(new Claim(Constants.Security.StartContentNodeIdClaimType, startContentNode.ToInvariantString(), ClaimValueTypes.Integer32, Issuer, Issuer, this));
}
}
if (HasClaim(x => x.Type == Constants.Security.StartMediaNodeIdClaimType) == false && startMediaNodes != null)
{
foreach (var startMediaNode in startMediaNodes)
{
AddClaim(new Claim(Constants.Security.StartMediaNodeIdClaimType, startMediaNode.ToInvariantString(), ClaimValueTypes.Integer32, Issuer, Issuer, this));
}
}
if (HasClaim(x => x.Type == ClaimTypes.Locality) == false)
AddClaim(new Claim(ClaimTypes.Locality, culture, ClaimValueTypes.String, Issuer, Issuer, this));
//The security stamp claim is also required
if (HasClaim(x => x.Type == Constants.Security.SecurityStampClaimType) == false)
AddClaim(new Claim(Constants.Security.SecurityStampClaimType, securityStamp, ClaimValueTypes.String, Issuer, Issuer, this));
//Add each app as a separate claim
if (HasClaim(x => x.Type == Constants.Security.AllowedApplicationsClaimType) == false && allowedApps != null)
{
foreach (var application in allowedApps)
{
AddClaim(new Claim(Constants.Security.AllowedApplicationsClaimType, application, ClaimValueTypes.String, Issuer, Issuer, this));
}
}
//Claims are added by the ClaimsIdentityFactory because our UserStore supports roles, however this identity might
// not be made with that factory if it was created with a different ticket so perform the check
if (HasClaim(x => x.Type == DefaultRoleClaimType) == false && roles != null)
{
//manually add them
foreach (var roleName in roles)
{
AddClaim(new Claim(RoleClaimType, roleName, ClaimValueTypes.String, Issuer, Issuer, this));
}
}
}
/// <inheritdoc />
/// <summary>
/// Gets the type of authenticated identity.
/// </summary>
/// <returns>
/// The type of authenticated identity. This property always returns "UmbracoBackOffice".
/// </returns>
public override string AuthenticationType => Issuer;
private int[] _startContentNodes;
public int[] StartContentNodes => _startContentNodes ?? (_startContentNodes = FindAll(x => x.Type == Constants.Security.StartContentNodeIdClaimType).Select(app => int.TryParse(app.Value, out var i) ? i : default).Where(x => x != default).ToArray());
private int[] _startMediaNodes;
public int[] StartMediaNodes => _startMediaNodes ?? (_startMediaNodes = FindAll(x => x.Type == Constants.Security.StartMediaNodeIdClaimType).Select(app => int.TryParse(app.Value, out var i) ? i : default).Where(x => x != default).ToArray());
private string[] _allowedApplications;
public string[] AllowedApplications => _allowedApplications ?? (_allowedApplications = FindAll(x => x.Type == Constants.Security.AllowedApplicationsClaimType).Select(app => app.Value).ToArray());
public int Id => int.Parse(this.FindFirstValue(ClaimTypes.NameIdentifier));
public string RealName => this.FindFirstValue(ClaimTypes.GivenName);
public string Username => this.FindFirstValue(ClaimTypes.Name);
public string Culture => this.FindFirstValue(ClaimTypes.Locality);
public string SecurityStamp => this.FindFirstValue(Constants.Security.SecurityStampClaimType);
public string[] Roles => FindAll(x => x.Type == DefaultRoleClaimType).Select(role => role.Value).ToArray();
/// <summary>
/// Overridden to remove any temporary claims that shouldn't be copied
/// </summary>
/// <returns></returns>
public override ClaimsIdentity Clone()
{
var clone = base.Clone();
foreach (var claim in clone.FindAll(x => x.Type == Constants.Security.TicketExpiresClaimType).ToList())
clone.RemoveClaim(claim);
return clone;
}
}
}

View File

@@ -26,14 +26,22 @@ namespace Umbraco.Core.Compose
private readonly IUserService _userService;
private readonly IEntityService _entityService;
private readonly IIpResolver _ipResolver;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly GlobalSettings _globalSettings;
public AuditEventsComponent(IAuditService auditService, IUserService userService, IEntityService entityService, IIpResolver ipResolver, IOptions<GlobalSettings> globalSettings)
public AuditEventsComponent(
IAuditService auditService,
IUserService userService,
IEntityService entityService,
IIpResolver ipResolver,
IOptions<GlobalSettings> globalSettings,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
{
_auditService = auditService;
_userService = userService;
_entityService = entityService;
_ipResolver = ipResolver;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_globalSettings = globalSettings.Value;
}
@@ -73,7 +81,7 @@ namespace Umbraco.Core.Compose
{
get
{
var identity = Thread.CurrentPrincipal?.GetUmbracoIdentity();
var identity = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
var user = identity == null ? null : _userService.GetUserById(Convert.ToInt32(identity.Id));
return user ?? UnknownUser(_globalSettings);
}

View File

@@ -4,7 +4,7 @@ using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Security;
using Umbraco.Extensions;
namespace Umbraco.Core.Security
{
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Security
/// <inheritdoc />
/// <remarks>
/// Returns a custom <see cref="UmbracoBackOfficeIdentity"/> and allows flowing claims from the external identity
/// Returns a ClaimsIdentity that has the required claims, and allows flowing of claims from external identity
/// </remarks>
public override async Task<ClaimsPrincipal> CreateAsync(BackOfficeIdentityUser user)
{
@@ -43,10 +43,7 @@ namespace Umbraco.Core.Security
baseIdentity.AddClaim(new Claim(claim.ClaimType, claim.ClaimValue));
}
// TODO: We want to remove UmbracoBackOfficeIdentity and only rely on ClaimsIdentity, once
// that is done then we'll create a ClaimsIdentity with all of the requirements here instead
var umbracoIdentity = new UmbracoBackOfficeIdentity(
baseIdentity,
baseIdentity.AddRequiredClaims(
user.Id,
user.UserName,
user.Name,
@@ -57,7 +54,7 @@ namespace Umbraco.Core.Security
user.AllowedSections,
user.Roles.Select(x => x.RoleId).ToArray());
return new ClaimsPrincipal(umbracoIdentity);
return new ClaimsPrincipal(baseIdentity);
}
/// <inheritdoc />

View File

@@ -39,24 +39,24 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.BackOffice
new Claim(Constants.Security.SecurityStampClaimType, securityStamp, ClaimValueTypes.String, TestIssuer, TestIssuer),
});
if (!UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out UmbracoBackOfficeIdentity backofficeIdentity))
if (!claimsIdentity.VerifyBackOfficeIdentity(out ClaimsIdentity verifiedIdentity))
{
Assert.Fail();
}
Assert.IsNull(backofficeIdentity.Actor);
Assert.AreEqual(1234, backofficeIdentity.Id);
Assert.IsNull(verifiedIdentity.Actor);
Assert.AreEqual(1234, verifiedIdentity.GetId());
//// Assert.AreEqual(sessionId, backofficeIdentity.SessionId);
Assert.AreEqual(securityStamp, backofficeIdentity.SecurityStamp);
Assert.AreEqual("testing", backofficeIdentity.Username);
Assert.AreEqual("hello world", backofficeIdentity.RealName);
Assert.AreEqual(1, backofficeIdentity.StartContentNodes.Length);
Assert.IsTrue(backofficeIdentity.StartMediaNodes.UnsortedSequenceEqual(new[] { 5543, 5555 }));
Assert.IsTrue(new[] { "content", "media" }.SequenceEqual(backofficeIdentity.AllowedApplications));
Assert.AreEqual("en-us", backofficeIdentity.Culture);
Assert.IsTrue(new[] { "admin" }.SequenceEqual(backofficeIdentity.Roles));
Assert.AreEqual(securityStamp, verifiedIdentity.GetSecurityStamp());
Assert.AreEqual("testing", verifiedIdentity.GetUsername());
Assert.AreEqual("hello world", verifiedIdentity.GetRealName());
Assert.AreEqual(1, verifiedIdentity.GetStartContentNodes().Length);
Assert.IsTrue(verifiedIdentity.GetStartMediaNodes().UnsortedSequenceEqual(new[] { 5543, 5555 }));
Assert.IsTrue(new[] { "content", "media" }.SequenceEqual(verifiedIdentity.GetAllowedApplications()));
Assert.AreEqual("en-us", verifiedIdentity.GetCultureString());
Assert.IsTrue(new[] { "admin" }.SequenceEqual(verifiedIdentity.GetRoles()));
Assert.AreEqual(11, backofficeIdentity.Claims.Count());
Assert.AreEqual(11, verifiedIdentity.Claims.Count());
}
[Test]
@@ -68,7 +68,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.BackOffice
new Claim(ClaimTypes.Name, "testing", ClaimValueTypes.String, TestIssuer, TestIssuer),
});
if (UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out _))
if (claimsIdentity.VerifyBackOfficeIdentity(out _))
{
Assert.Fail();
}
@@ -93,7 +93,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.BackOffice
new Claim(ClaimsIdentity.DefaultRoleClaimType, "admin", ClaimValueTypes.String, TestIssuer, TestIssuer),
});
if (UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out _))
if (claimsIdentity.VerifyBackOfficeIdentity(out _))
{
Assert.Fail();
}
@@ -112,8 +112,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.BackOffice
new Claim("TestClaim1", "test", ClaimValueTypes.Integer32, TestIssuer, TestIssuer)
});
var identity = new UmbracoBackOfficeIdentity(
claimsIdentity,
claimsIdentity.AddRequiredClaims(
"1234",
"testing",
"hello world",
@@ -124,25 +123,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.BackOffice
new[] { "content", "media" },
new[] { "admin" });
Assert.AreEqual(12, identity.Claims.Count());
Assert.IsNull(identity.Actor);
}
[Test]
public void Clone()
{
var securityStamp = Guid.NewGuid().ToString();
var identity = new UmbracoBackOfficeIdentity(
"1234", "testing", "hello world", new[] { 654 }, new[] { 654 }, "en-us", securityStamp, new[] { "content", "media" }, new[] { "admin" });
// this will be filtered out during cloning
identity.AddClaim(new Claim(Constants.Security.TicketExpiresClaimType, "test"));
ClaimsIdentity cloned = identity.Clone();
Assert.IsNull(cloned.Actor);
Assert.AreEqual(10, cloned.Claims.Count());
Assert.AreEqual(12, claimsIdentity.Claims.Count());
Assert.IsNull(claimsIdentity.Actor);
}
}
}

View File

@@ -5,9 +5,8 @@ using System;
using System.Linq;
using System.Security.Claims;
using NUnit.Framework;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions
{
@@ -17,7 +16,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions
[Test]
public void Get_Remaining_Ticket_Seconds()
{
var backOfficeIdentity = new UmbracoBackOfficeIdentity(
var backOfficeIdentity = new ClaimsIdentity();
backOfficeIdentity.AddRequiredClaims(
Constants.Security.SuperUserIdAsString,
"test",
"test",
@@ -27,6 +27,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions
Guid.NewGuid().ToString(),
Enumerable.Empty<string>(),
Enumerable.Empty<string>());
var principal = new ClaimsPrincipal(backOfficeIdentity);
var expireSeconds = 99;
@@ -37,16 +38,52 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions
var expires = now.AddSeconds(expireSeconds).ToString("o");
backOfficeIdentity.AddClaim(new Claim(
Constants.Security.TicketExpiresClaimType,
expires,
ClaimValueTypes.DateTime,
UmbracoBackOfficeIdentity.Issuer,
UmbracoBackOfficeIdentity.Issuer,
backOfficeIdentity));
Constants.Security.TicketExpiresClaimType,
expires,
ClaimValueTypes.DateTime,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
backOfficeIdentity));
var ticketRemainingSeconds = principal.GetRemainingAuthSeconds(then);
Assert.AreEqual(remainingSeconds, ticketRemainingSeconds);
}
[Test]
public void AddOrUpdateClaim__Should_ensure_a_claim_is_not_added_twice()
{
var backOfficeIdentity = new ClaimsIdentity();
backOfficeIdentity.AddRequiredClaims(
Constants.Security.SuperUserIdAsString,
"test",
"test",
Enumerable.Empty<int>(),
Enumerable.Empty<int>(),
"en-US",
Guid.NewGuid().ToString(),
Enumerable.Empty<string>(),
Enumerable.Empty<string>());
var expireSeconds = 99;
DateTimeOffset now = DateTimeOffset.Now;
var expires = now.AddSeconds(expireSeconds).ToString("o");
var claim = new Claim(
Constants.Security.TicketExpiresClaimType,
expires,
ClaimValueTypes.DateTime,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
backOfficeIdentity);
backOfficeIdentity.AddOrUpdateClaim(claim);
backOfficeIdentity.AddOrUpdateClaim(claim);
Assert.AreEqual(1, backOfficeIdentity.Claims.Count(x=>x.Type == Constants.Security.TicketExpiresClaimType));
}
}
}

View File

@@ -57,13 +57,13 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.BackOffice
}
[Test]
public async Task CreateAsync_Should_Create_Principal_With_Umbraco_Identity()
public async Task CreateAsync_Should_Create_Principal_With_Claims_Identity()
{
BackOfficeClaimsPrincipalFactory sut = CreateSut();
ClaimsPrincipal claimsPrincipal = await sut.CreateAsync(_testUser);
var umbracoBackOfficeIdentity = claimsPrincipal.Identity as UmbracoBackOfficeIdentity;
var umbracoBackOfficeIdentity = claimsPrincipal.Identity as ClaimsIdentity;
Assert.IsNotNull(umbracoBackOfficeIdentity);
}

View File

@@ -12,10 +12,8 @@ using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Web.BackOffice.Security;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Security
{
@@ -24,18 +22,21 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Security
{
private HttpContext GetHttpContext()
{
var identity = new ClaimsIdentity();
identity.AddRequiredClaims(
Constants.Security.SuperUserIdAsString,
"test",
"test",
Enumerable.Empty<int>(),
Enumerable.Empty<int>(),
"en-US",
Guid.NewGuid().ToString(),
Enumerable.Empty<string>(),
Enumerable.Empty<string>());
var httpContext = new DefaultHttpContext()
{
User = new ClaimsPrincipal(new UmbracoBackOfficeIdentity(
Constants.Security.SuperUserIdAsString,
"test",
"test",
Enumerable.Empty<int>(),
Enumerable.Empty<int>(),
"en-US",
Guid.NewGuid().ToString(),
Enumerable.Empty<string>(),
Enumerable.Empty<string>()))
User = new ClaimsPrincipal(identity)
};
httpContext.Request.IsHttps = true;
return httpContext;

View File

@@ -584,7 +584,7 @@ namespace Umbraco.Tests.PublishedContent
Assert.IsNotNull(result);
Assert.AreEqual(3, result.Length);
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1173, 1046 }));
Assert.IsTrue(result.Select(x => ((dynamic)x).GetId()).ContainsAll(new dynamic[] { 1174, 1173, 1046 }));
}
[Test]
@@ -597,7 +597,7 @@ namespace Umbraco.Tests.PublishedContent
Assert.IsNotNull(result);
Assert.AreEqual(2, result.Length);
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1046 }));
Assert.IsTrue(result.Select(x => ((dynamic)x).GetId()).ContainsAll(new dynamic[] { 1173, 1046 }));
}
[Test]
@@ -710,7 +710,7 @@ namespace Umbraco.Tests.PublishedContent
Assert.IsNotNull(result);
Assert.AreEqual(10, result.Count());
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175 }));
Assert.IsTrue(result.Select(x => ((dynamic)x).GetId()).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175 }));
}
[Test]
@@ -723,7 +723,7 @@ namespace Umbraco.Tests.PublishedContent
Assert.IsNotNull(result);
Assert.AreEqual(9, result.Count());
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
Assert.IsTrue(result.Select(x => ((dynamic)x).GetId()).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
}
[Test]

View File

@@ -1,12 +1,11 @@
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Owin;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Security;
using Umbraco.Core.Security;
using Umbraco.Extensions;
namespace Umbraco.Tests.TestHelpers.ControllerTesting
{
@@ -30,8 +29,18 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
{
var securityStamp = Guid.NewGuid().ToString();
var identity = new UmbracoBackOfficeIdentity(
Constants.Security.SuperUserIdAsString, "admin", "Admin", new[] { -1 }, new[] { -1 }, "en-US", securityStamp, new[] { "content", "media", "members" }, new[] { "admin" });
var identity = new ClaimsIdentity();
identity.AddRequiredClaims(
Cms.Core.Constants.Security.SuperUserIdAsString,
"admin",
"Admin",
new[] { -1 },
new[] { -1 },
"en-US",
securityStamp,
new[] { "content", "media", "members" },
new[] { "admin" });
return Task.FromResult(new AuthenticationTicket(
identity,

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
@@ -22,6 +23,7 @@ using Umbraco.Web.Routing;
using Umbraco.Web.WebApi;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Core.Security;
using Umbraco.Extensions;
namespace Umbraco.Tests.TestHelpers.ControllerTesting
{
@@ -97,29 +99,29 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
//chuck it into the props since this is what MS does when hosted and it's needed there
request.Properties["MS_HttpContext"] = httpContext;
var backofficeIdentity = (UmbracoBackOfficeIdentity) owinContext.Authentication.User.Identity;
var backofficeIdentity = (ClaimsIdentity) owinContext.Authentication.User.Identity;
var backofficeSecurity = new Mock<IBackOfficeSecurity>();
//mock CurrentUser
var groups = new List<ReadOnlyUserGroup>();
for (var index = 0; index < backofficeIdentity.Roles.Length; index++)
for (var index = 0; index < backofficeIdentity.GetRoles().Length; index++)
{
var role = backofficeIdentity.Roles[index];
var role = backofficeIdentity.GetRoles()[index];
groups.Add(new ReadOnlyUserGroup(index + 1, role, "icon-user", null, null, role, new string[0], new string[0]));
}
var mockUser = MockedUser.GetUserMock();
mockUser.Setup(x => x.IsApproved).Returns(true);
mockUser.Setup(x => x.IsLockedOut).Returns(false);
mockUser.Setup(x => x.AllowedSections).Returns(backofficeIdentity.AllowedApplications);
mockUser.Setup(x => x.AllowedSections).Returns(backofficeIdentity.GetAllowedApplications());
mockUser.Setup(x => x.Groups).Returns(groups);
mockUser.Setup(x => x.Email).Returns("admin@admin.com");
mockUser.Setup(x => x.Id).Returns((int)backofficeIdentity.Id);
mockUser.Setup(x => x.Id).Returns((int)backofficeIdentity.GetId());
mockUser.Setup(x => x.Language).Returns("en");
mockUser.Setup(x => x.Name).Returns(backofficeIdentity.RealName);
mockUser.Setup(x => x.StartContentIds).Returns(backofficeIdentity.StartContentNodes);
mockUser.Setup(x => x.StartMediaIds).Returns(backofficeIdentity.StartMediaNodes);
mockUser.Setup(x => x.Username).Returns(backofficeIdentity.Username);
mockUser.Setup(x => x.Name).Returns(backofficeIdentity.GetRealName());
mockUser.Setup(x => x.StartContentIds).Returns(backofficeIdentity.GetStartContentNodes());
mockUser.Setup(x => x.StartMediaIds).Returns(backofficeIdentity.GetStartMediaNodes());
mockUser.Setup(x => x.Username).Returns(backofficeIdentity.GetUsername());
backofficeSecurity.Setup(x => x.CurrentUser)
.Returns(mockUser.Object);

View File

@@ -112,13 +112,13 @@ namespace Umbraco.Cms.Web.BackOffice.Filters
return;
}
var identity = actionContext.HttpContext.User.Identity as UmbracoBackOfficeIdentity;
var identity = actionContext.HttpContext.User.Identity as ClaimsIdentity;
if (identity == null)
{
return;
}
Attempt<int> userId = identity.Id.TryConvertTo<int>();
Attempt<int> userId = identity.GetId().TryConvertTo<int>();
if (userId == false)
{
return;
@@ -133,23 +133,23 @@ namespace Umbraco.Cms.Web.BackOffice.Filters
// a list of checks to execute, if any of them pass then we resync
var checks = new Func<bool>[]
{
() => user.Username != identity.Username,
() => user.Username != identity.GetUsername(),
() =>
{
CultureInfo culture = user.GetUserCulture(_localizedTextService, _globalSettings.Value);
return culture != null && culture.ToString() != identity.Culture;
return culture != null && culture.ToString() != identity.GetCultureString();
},
() => user.AllowedSections.UnsortedSequenceEqual(identity.AllowedApplications) == false,
() => user.Groups.Select(x => x.Alias).UnsortedSequenceEqual(identity.Roles) == false,
() => user.AllowedSections.UnsortedSequenceEqual(identity.GetAllowedApplications()) == false,
() => user.Groups.Select(x => x.Alias).UnsortedSequenceEqual(identity.GetRoles()) == false,
() =>
{
var startContentIds = user.CalculateContentStartNodeIds(_entityService);
return startContentIds.UnsortedSequenceEqual(identity.StartContentNodes) == false;
return startContentIds.UnsortedSequenceEqual(identity.GetStartContentNodes()) == false;
},
() =>
{
var startMediaIds = user.CalculateMediaStartNodeIds(_entityService);
return startMediaIds.UnsortedSequenceEqual(identity.StartMediaNodes) == false;
return startMediaIds.UnsortedSequenceEqual(identity.GetStartMediaNodes()) == false;
}
};

View File

@@ -1,13 +1,13 @@
using System;
using System.Security.Claims;
using Umbraco.Extensions;
using Microsoft.AspNetCore.Authentication;
using Umbraco.Cms.Core.Security;
namespace Umbraco.Cms.Web.BackOffice.Security
{
/// <summary>
/// Custom secure format that ensures the Identity in the ticket is <see cref="UmbracoBackOfficeIdentity"/> and not just a ClaimsIdentity
/// Custom secure format that ensures the Identity in the ticket is verified <see cref="ClaimsIdentity"/>
/// </summary>
internal class BackOfficeSecureDataFormat : ISecureDataFormat<AuthenticationTicket>
{
@@ -59,11 +59,14 @@ namespace Umbraco.Cms.Web.BackOffice.Security
return null;
}
if (!UmbracoBackOfficeIdentity.FromClaimsIdentity((ClaimsIdentity)decrypt.Principal.Identity, out var identity))
var identity = (ClaimsIdentity)decrypt.Principal.Identity;
if (!identity.VerifyBackOfficeIdentity(out ClaimsIdentity verifiedIdentity))
{
return null;
}
//return the ticket with a UmbracoBackOfficeIdentity
var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), decrypt.Properties, decrypt.AuthenticationScheme);
var ticket = new AuthenticationTicket(new ClaimsPrincipal(verifiedIdentity), decrypt.Properties, decrypt.AuthenticationScheme);
return ticket;
}

View File

@@ -12,11 +12,9 @@ using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Net;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.Cms.Web.BackOffice.Security
{
@@ -136,7 +134,7 @@ namespace Umbraco.Cms.Web.BackOffice.Security
// Same goes for the signinmanager
IBackOfficeSignInManager signInManager = ctx.HttpContext.RequestServices.GetRequiredService<IBackOfficeSignInManager>();
UmbracoBackOfficeIdentity backOfficeIdentity = ctx.Principal.GetUmbracoIdentity();
ClaimsIdentity backOfficeIdentity = ctx.Principal.GetUmbracoIdentity();
if (backOfficeIdentity == null)
{
ctx.RejectPrincipal();
@@ -150,33 +148,33 @@ namespace Umbraco.Cms.Web.BackOffice.Security
await securityStampValidator.ValidateAsync(ctx);
EnsureTicketRenewalIfKeepUserLoggedIn(ctx);
// add a claim to track when the cookie expires, we use this to track time remaining
backOfficeIdentity.AddClaim(new Claim(
// add or update a claim to track when the cookie expires, we use this to track time remaining
backOfficeIdentity.AddOrUpdateClaim(new Claim(
Constants.Security.TicketExpiresClaimType,
ctx.Properties.ExpiresUtc.Value.ToString("o"),
ClaimValueTypes.DateTime,
UmbracoBackOfficeIdentity.Issuer,
UmbracoBackOfficeIdentity.Issuer,
Constants.Security.BackOfficeAuthenticationType,
Constants.Security.BackOfficeAuthenticationType,
backOfficeIdentity));
},
OnSigningIn = ctx =>
{
// occurs when sign in is successful but before the ticket is written to the outbound cookie
UmbracoBackOfficeIdentity backOfficeIdentity = ctx.Principal.GetUmbracoIdentity();
ClaimsIdentity backOfficeIdentity = ctx.Principal.GetUmbracoIdentity();
if (backOfficeIdentity != null)
{
// generate a session id and assign it
// create a session token - if we are configured and not in an upgrade state then use the db, otherwise just generate one
Guid session = _runtimeState.Level == RuntimeLevel.Run
? _userService.CreateLoginSession(backOfficeIdentity.Id, _ipResolver.GetCurrentRequestIpAddress())
? _userService.CreateLoginSession(backOfficeIdentity.GetId(), _ipResolver.GetCurrentRequestIpAddress())
: Guid.NewGuid();
// add our session claim
backOfficeIdentity.AddClaim(new Claim(Constants.Security.SessionIdClaimType, session.ToString(), ClaimValueTypes.String, UmbracoBackOfficeIdentity.Issuer, UmbracoBackOfficeIdentity.Issuer, backOfficeIdentity));
backOfficeIdentity.AddClaim(new Claim(Constants.Security.SessionIdClaimType, session.ToString(), ClaimValueTypes.String, Constants.Security.BackOfficeAuthenticationType, Constants.Security.BackOfficeAuthenticationType, backOfficeIdentity));
// since it is a cookie-based authentication add that claim
backOfficeIdentity.AddClaim(new Claim(ClaimTypes.CookiePath, "/", ClaimValueTypes.String, UmbracoBackOfficeIdentity.Issuer, UmbracoBackOfficeIdentity.Issuer, backOfficeIdentity));
backOfficeIdentity.AddClaim(new Claim(ClaimTypes.CookiePath, "/", ClaimValueTypes.String, Constants.Security.BackOfficeAuthenticationType, Constants.Security.BackOfficeAuthenticationType, backOfficeIdentity));
}
return Task.CompletedTask;

View File

@@ -32,7 +32,7 @@ namespace Umbraco.Extensions
/// <returns>
/// Returns the current back office identity if an admin is authenticated otherwise null
/// </returns>
public static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContext http)
public static ClaimsIdentity GetCurrentIdentity(this HttpContext http)
{
if (http == null) throw new ArgumentNullException(nameof(http));
if (http.User == null) return null; //there's no user at all so no identity

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
@@ -176,8 +177,8 @@ namespace Umbraco.Cms.Web.Common.Security
private string GetCurrentUserId(IPrincipal currentUser)
{
UmbracoBackOfficeIdentity umbIdentity = currentUser?.GetUmbracoIdentity();
var currentUserId = umbIdentity?.GetUserId<string>() ?? Cms.Core.Constants.Security.SuperUserIdAsString;
ClaimsIdentity umbIdentity = currentUser?.GetUmbracoIdentity();
var currentUserId = umbIdentity?.GetUserId<string>() ?? Core.Constants.Security.SuperUserIdAsString;
return currentUserId;
}

View File

@@ -55,7 +55,7 @@ namespace Umbraco.Cms.Web.Common.Security
public Attempt<int> GetUserId()
{
var identity = _httpContextAccessor.HttpContext?.GetCurrentIdentity();
return identity == null ? Attempt.Fail<int>() : Attempt.Succeed(identity.Id);
return identity == null ? Attempt.Fail<int>() : Attempt.Succeed(identity.GetId());
}
/// <inheritdoc />

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Security.Principal;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
@@ -39,7 +40,7 @@ namespace Umbraco.Web.Common.Security
private string GetCurrentUserId(IPrincipal currentUser)
{
UmbracoBackOfficeIdentity umbIdentity = currentUser?.GetUmbracoIdentity();
ClaimsIdentity umbIdentity = currentUser?.GetUmbracoIdentity();
var currentUserId = umbIdentity?.GetUserId<string>() ?? Cms.Core.Constants.Security.SuperUserIdAsString;
return currentUserId;
}