private static Func<IEnumerable<ClaimsIdentity>, ClaimsIdentity?> s_identitySelector = SelectPrimaryIdentity;
private static Func<ClaimsPrincipal> s_principalSelector = ClaimsPrincipalSelector;
- private static ClaimsPrincipal SelectClaimsPrincipal()
+ private static ClaimsPrincipal? SelectClaimsPrincipal()
{
- return (Thread.CurrentPrincipal is ClaimsPrincipal claimsPrincipal) ? claimsPrincipal : new ClaimsPrincipal(Thread.CurrentPrincipal!);
+ // Diverging behavior from .NET Framework: In Framework, the default PrincipalPolicy is
+ // UnauthenticatedPrincipal. In .NET Core, the default is NoPrincipal. .NET Framework
+ // would throw an ArgumentNullException when constructing the ClaimsPrincipal with a
+ // null principal from the thread if it were set to use NoPrincipal. In .NET Core, since
+ // NoPrincipal is the default, we return null instead of throw.
+
+ IPrincipal? threadPrincipal = Thread.CurrentPrincipal;
+
+ return threadPrincipal switch {
+ ClaimsPrincipal claimsPrincipal => claimsPrincipal,
+ not null => new ClaimsPrincipal(threadPrincipal),
+ null => null
+ };
}
protected ClaimsPrincipal(SerializationInfo info, StreamingContext context)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
}
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
- public void Current_FallsBackToThread()
+ public void Current_FallsBackToThread_NoPrincipalPolicy()
{
RemoteExecutor.Invoke(() =>
{
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);
+ Assert.Null(ClaimsPrincipal.Current);
+ }).Dispose();
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void Current_FallsBackToThread_UnauthenticatedPrincipalPolicy()
+ {
+ RemoteExecutor.Invoke(() =>
+ {
+ AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.UnauthenticatedPrincipal);
+ Thread.CurrentPrincipal = null;
+ Assert.IsType<GenericPrincipal>(ClaimsPrincipal.Current);
}).Dispose();
}