using System.IO;
using System.Runtime.Serialization;
using System.Security.Principal;
+using System.Threading;
namespace System.Security.Claims
{
private static Func<IEnumerable<ClaimsIdentity>, ClaimsIdentity?> s_identitySelector = SelectPrimaryIdentity;
private static Func<ClaimsPrincipal> s_principalSelector = ClaimsPrincipalSelector;
+ private static ClaimsPrincipal SelectClaimsPrincipal()
+ {
+ return (Thread.CurrentPrincipal is ClaimsPrincipal claimsPrincipal) ? claimsPrincipal : new ClaimsPrincipal(Thread.CurrentPrincipal!);
+ }
+
protected ClaimsPrincipal(SerializationInfo info, StreamingContext context)
{
throw new PlatformNotSupportedException();
// just accesses the current selected principal selector, doesn't set
get
{
- if (s_principalSelector != null)
- {
- return s_principalSelector();
- }
-
- return null;
+ return s_principalSelector is not null ? s_principalSelector() : SelectClaimsPrincipal();
}
}
using System.IO;
using System.Linq;
using System.Security.Principal;
+using System.Threading;
+using Microsoft.DotNet.RemoteExecutor;
using Xunit;
namespace System.Security.Claims
AssertExtensions.Throws<ArgumentNullException>("reader", () => new ClaimsPrincipal((BinaryReader)null));
}
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void Current_FallsBackToThread()
+ {
+ RemoteExecutor.Invoke(() =>
+ {
+ ClaimsPrincipal principal1 = new ClaimsPrincipal();
+ ClaimsPrincipal principal2 = new ClaimsPrincipal();
+
+ Thread.CurrentPrincipal = principal1;
+ Assert.Same(principal1, ClaimsPrincipal.Current);
+
+ Thread.CurrentPrincipal = principal2;
+ Assert.Same(principal2, ClaimsPrincipal.Current);
+
+ NonClaimsIdentity id = new NonClaimsIdentity() { Name = "NonClaimsIdentity_Name" };
+ NonClaimsPrincipal nonClaimsPrincipal = new NonClaimsPrincipal() { Identity = id };
+
+ Thread.CurrentPrincipal = nonClaimsPrincipal;
+
+ ClaimsPrincipal current = ClaimsPrincipal.Current;
+ Assert.NotNull(current);
+ Assert.Equal("NonClaimsIdentity_Name", current.Identity.Name);
+
+ // match .NET Framework behavior by throwing ArgumentNullException when Thread.CurrentPrincipal is null
+ Thread.CurrentPrincipal = null;
+ Assert.Throws<ArgumentNullException>(() => ClaimsPrincipal.Current);
+ }).Dispose();
+ }
+
private class NonClaimsPrincipal : IPrincipal
{
public IIdentity Identity { get; set; }