Remove usage of FromClaimsIdentity

This commit is contained in:
Mole
2021-02-17 11:50:19 +01:00
parent 80716a18d2
commit 33a99df73f
9 changed files with 56 additions and 57 deletions

View File

@@ -1,4 +1,5 @@
using System.Globalization;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading;
using Umbraco.Extensions;
@@ -21,7 +22,7 @@ namespace Umbraco.Core.Security
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.GetCultureString());
}

View File

@@ -21,8 +21,8 @@ namespace Umbraco.Extensions
ClaimTypes.NameIdentifier, //id
ClaimTypes.Name, //username
ClaimTypes.GivenName,
Constants.Security.StartContentNodeIdClaimType,
Constants.Security.StartMediaNodeIdClaimType,
// Constants.Security.StartContentNodeIdClaimType, These seem to be able to be null...
// Constants.Security.StartMediaNodeIdClaimType,
ClaimTypes.Locality,
Constants.Security.SecurityStampClaimType
};

View File

@@ -11,29 +11,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

@@ -15,22 +15,22 @@ namespace Umbraco.Core.Security
// 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;
}
// 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

View File

@@ -39,24 +39,24 @@ namespace Umbraco.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.GetId());
Assert.IsNull(verifiedIdentity.Actor);
Assert.AreEqual(1234, verifiedIdentity.GetId());
//// Assert.AreEqual(sessionId, backofficeIdentity.SessionId);
Assert.AreEqual(securityStamp, backofficeIdentity.GetSecurityStamp());
Assert.AreEqual("testing", backofficeIdentity.GetUsername());
Assert.AreEqual("hello world", backofficeIdentity.GetRealName());
Assert.AreEqual(1, backofficeIdentity.GetStartContentNodes().Length);
Assert.IsTrue(backofficeIdentity.GetStartMediaNodes().UnsortedSequenceEqual(new[] { 5543, 5555 }));
Assert.IsTrue(new[] { "content", "media" }.SequenceEqual(backofficeIdentity.GetAllowedApplications()));
Assert.AreEqual("en-us", backofficeIdentity.GetCultureString());
Assert.IsTrue(new[] { "admin" }.SequenceEqual(backofficeIdentity.GetRoles()));
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.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.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();
}

View File

@@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Authentication;
using System;
using System.Security.Claims;
using MimeKit.Cryptography;
using Umbraco.Core.Security;
using Umbraco.Extensions;
namespace Umbraco.Web.BackOffice.Security
{
@@ -19,7 +21,7 @@ namespace Umbraco.Web.BackOffice.Security
_loginTimeoutMinutes = loginTimeoutMinutes;
_ticketDataFormat = ticketDataFormat ?? throw new ArgumentNullException(nameof(ticketDataFormat));
}
public string Protect(AuthenticationTicket data, string purpose)
{
// create a new ticket based on the passed in tickets details, however, we'll adjust the expires utc based on the specified timeout mins
@@ -38,7 +40,7 @@ namespace Umbraco.Web.BackOffice.Security
public string Protect(AuthenticationTicket data) => Protect(data, string.Empty);
public AuthenticationTicket Unprotect(string protectedText) => Unprotect(protectedText, string.Empty);
/// <summary>
@@ -59,11 +61,14 @@ namespace Umbraco.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

@@ -138,7 +138,7 @@ namespace Umbraco.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();
@@ -165,7 +165,7 @@ namespace Umbraco.Web.BackOffice.Security
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

View File

@@ -35,7 +35,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;
@@ -178,7 +179,7 @@ namespace Umbraco.Web.Common.Security
private string GetCurrentUserId(IPrincipal currentUser)
{
UmbracoBackOfficeIdentity umbIdentity = currentUser?.GetUmbracoIdentity();
ClaimsIdentity umbIdentity = currentUser?.GetUmbracoIdentity();
var currentUserId = umbIdentity?.GetUserId<string>() ?? Core.Constants.Security.SuperUserIdAsString;
return currentUserId;
}