Jos Vinke
Jos Vinke

Reputation: 2714

Thread.CurrentPrincipal is authenticated but ClaimsPrincipal.Current is not

I'm using Claims based Authorization in my WebApi project and have a method where I check if the current Identity is authenticated. When I use ClaimsPrincipal.Current the current Identity is not authenticated but when I use Thread.CurrentPrincipal it is.

ClaimsPrincipal.Current.Identity.IsAuthenticated; //False
Thread.CurrentPrincipal.Identity.IsAuthenticated; //True

This seems strange especially since the MSDN says ClaimsPrincipal.Current just returns Thread.CurrentPrincipal:

Remarks

By default, Thread.CurrentPrincipal is returned. You can change this behavior by setting the ClaimsPrincipalSelector property to specify a delegate to be called to determine the current principal.

Can someone please explain me why ClaimsPrincipal is not authenticated, while both, in theory, contain the same Identity?

Upvotes: 7

Views: 15613

Answers (1)

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239714

In short, the documentation is incorrect to say that it returns Thread.CurrentPrincipal by default.

What it actually returns is a ClaimsPrincipal wrapping Thread.CurrentPrincipal (if it's not, actually, already a ClaimsPrincipal), using this constructor:

public ClaimsPrincipal(IPrincipal principal)
{
    this.m_version = "1.0";
    this.m_identities = new List<ClaimsIdentity>();
    if (principal == null)
    {
        throw new ArgumentNullException("principal");
    }
    ClaimsPrincipal principal2 = principal as ClaimsPrincipal;
    if (principal2 == null)
    {
        this.m_identities.Add(new ClaimsIdentity(principal.Identity));
    }
    else if (principal2.Identities != null)
    {
        this.m_identities.AddRange(principal2.Identities);
    }
}

This, in turn, as you can hopefully see, is returning a ClaimsIdentity that wraps the principal's identity (again, if it's not, actually, already a ClaimsIdentity).

In constructing the ClaimsIdentity, the only place I can see where it will end up not setting the authentication type (and thus creating an identity that's not authenticated) is here:

if(identity is WindowsIdentity)
{
   try
   {
      this.m_authenticationType = identity.AuthenticationType;
   }
   catch(UnauthorizedAccessException)
   {
      this.m_authenticationType = null;
   }
}

So, if the identity you access via Thread.CurrentPrincipal.Identity is actually a WindowsIdentity instance, and in the context in which you're running you've got restricted permissions, the constructed ClaimsIdentity instance will have IsAuthenticated as false.

Upvotes: 10

Related Questions