Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 588
Jos Vinke Avatar asked Mar 11 '13 15:03

Jos Vinke


1 Answers

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.

like image 100
Damien_The_Unbeliever Avatar answered Sep 17 '22 23:09

Damien_The_Unbeliever