In our production, we will configure the security domain use ClientLoginModule to do login/logout.
This issue happens in multithread environment and with following strict call sequence
1. Thread1 Login with user "user1" and password "123456" using ClientLoginModule. After login, the principal "user1" is stored in its thread local cache
2. Thread1 invoke EJB call, in this call, the SecurityInterceptor will check if the caller info with the EJB is valid, which will invoke JaasSecurityManager.isValid, suppose at this stage, there already exists one JaasSecurityManager.DomainInfo with principal "user1", but this domain info is timeout (The timeout value is 30min in our production), then thread1 will remove it from domainCache, and it internally trigger the logout (TimedCachePolicy will invoke logout when it remove one entry). At this stage, there is no principal in thread1's thread local cache now
3. After the timeout domain info is removed from domainCache, thread1 will internally login again. After login, the principal "user1" is stored in the local cache again.
4. At this timie, another thread thread2 also invoke EJB call, and its caller is also "user1", as step2, the SecurityInterceptor will check if the caller is valid by checking the domain cache. As you see, there is no such entry now, because step2 has removed it and not put the new one into cache yet. As a result, thread2 will do login with user/password, after login, thread2 will try to put this domain info into domain cache, and it succeed to put the domain info because there is no such domain info now.
5. At this time, thread1 will also try to put its domain info (created at step3) into the domain cache. But unfortunately, there already one domain info now, thus, current implementation will remove the old domain info from the cache, this step will invoke the logout internally (by TimedCachePolicy). As a result, the principal "user1" will be removed from thread local cache again.
6. After step5, our business component wants to find out the caller now, because we already logins at step1, thus, we could always get the caller "user1", but actually there is no caller now.
This is the issue we meet.