In .NET, System.Threading.Thread.CurrentPrincipal is the same for different threads

5.1k views Asked by At

I'm looking for some general approach to store my JWT token on the server side for different users. I decided to store that data in Thread.CurrentPrincipal. But when i tested it i saw, that different clients have access to the same Thread.

Simulation of several clients, that access to my tested wcf service:

private static void Main(string[] args)
        {
            List<Thread> threads = new List<Thread>();
            for (int i = 0; i < 20; i++)
            {
                var program = new Program();
                threads.Add(new Thread(program.DoWork));
            }
            foreach (var thread in threads)
            {
                thread.Start();
            }
            Console.ReadLine();
        }

        public void DoWork()
        {
            var client = new AuthenticationClient();
                ClaimsPrincipal claimsPrincipal;
                var _jwtTokenProvider = new JwtTokenProvider();
                Console.WriteLine(client.Connect());
            for (int i = 0; i < 40; i++)
            {
               var result = client.SignIn();
               _jwtTokenProvider.ValidateToken(result, out claimsPrincipal);
               Console.WriteLine(result);
            }
       }

And tested service's method:

public string Connect()
        {
            Thread.Sleep(300);
            foreach (var identity in ((ClaimsPrincipal)Thread.CurrentPrincipal).Identities)
            {
                var token = identity.Claims.FirstOrDefault(t => t.Type == "token");
                if (token != null)
                {
                    throw new FaultException<STSFault>(new STSFault(ExceptionsMessages.Message, ErrorCodes.EmptyCredentials), new FaultReason(ExceptionsMessages.Message)); 
                }
            }

            var claimsPrincipal = new ClaimsPrincipal();
            List<Claim> claims = new List<Claim>();
            claims.Add(new Claim("token", "token"));
            var claimIdentity = new ClaimsIdentity(claims);
            claimsPrincipal.AddIdentity(claimIdentity);
            Thread.CurrentPrincipal = claimsPrincipal;
            foreach (var identity in ((ClaimsPrincipal)Thread.CurrentPrincipal).Identities)
            {
                var token = identity.Claims.FirstOrDefault(t => t.Type == "token");
            }
            return Assembly.GetExecutingAssembly().GetName().Version.ToString();
        }

I can't understand, why FaultException throws. Thanks.

2

There are 2 answers

5
Ventsyslav Raikov On

This is called execution context. When you create those threads they 'inherit' the Principal from your application's main thread.

The principal in your main thread represents the user who's credentials your app is running under.

Take a look at this question.

0
ken2k On

You can't assume each client user will execute its actions on the server always in the same thread. Threads on server side might be reused for different requests from different clients.

This strongly depends on how you configure your WCF service. See the ConcurrencyMode and the InstanceContextMode.

See also combinations of Instancing and Concurrency