3

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.

aturch
  • 53
  • 3
  • 8

2 Answers2

4

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.

Community
  • 1
  • 1
Ventsyslav Raikov
  • 6,882
  • 1
  • 25
  • 28
  • As i understand, u are talking about client side, i mean the place where all threads are created and called wcf service asynchronously? If so, how that can impact behavior of Thread.CurrentPrincipal on the server side (wcf)? If not, then how ASP can manage different user credentials at the same time? Thanks. – aturch Nov 08 '13 at 12:00
  • @aturch - wait - your app is console right? I deduced that from your Main method. For ASP.NET/WCF the framework sets the identity of the thread that processes the current request based on the authentication you use(e.g. if you use cookies ASP.NET will read the auth cookie, determine the user name and set the identity on the thread which will then be running your code) – Ventsyslav Raikov Nov 08 '13 at 12:54
  • and then if the your thread creates/uses other threads the execution context will flow and there you will have the same identity – Ventsyslav Raikov Nov 08 '13 at 12:55
  • actually there two app - console as client(it imitates 20 users for server app) and wcf as server app. I got an issue with shared CurrentPrincipal on the server layer. I thought that there will unique CurrentPrincipal for each user. Especial after configuring wcf service InstanceContextMode to PerSession – aturch Nov 08 '13 at 13:10
  • InstanceContextMode has nothing to do with users/authentication - it "Specifies the number of service instances available for handling calls that are contained in incoming messages." - this is quote from MSDN and is about the number of objects of your service class created. – Ventsyslav Raikov Nov 08 '13 at 13:33
1

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

ken2k
  • 48,145
  • 10
  • 116
  • 176