Search code examples
javashiro

Shiro Subject Authenticated but missing Principal


I've got a strange Shiro problem I'm trying to track down where sometimes (race condition, likely) a session ends up containing the Authentication setting as true, but doesn't have a principal.

Here is what seems to be happening:

  1. User accesses our system with a URL.
  2. The URL contains a magic path that authenticates them and logs them in. The Subject now is Authenticated and has a Principal.
  3. The requested web page is sent to them.
  4. The web page includes other pages (JavaScript, CSS, etc.). The second request sometimes fails (accessing JavaScript) because the Subject is now Authenticated, but doesn't have a Principal, so we can't Authorize them.

Here is the code that performs the login (step 2):

if(!subject.isAuthenticated()) {
    // Log the user in
    LegacyAuthenticationToken token = new LegacyAuthenticationToken(site, facility, authUrl);
    subject.login(token);
}

The LegacyJDBCRealm extends AuthenticatingRealm and overrides doGetAutheticationInfo to return a SimpleAuthenticationInfo object which has the principal in it:

return new SimpleAuthenticationInfo(userKey.toString(), authUrl, getName());

userKey.toString() is the principal. AuthUrl is the URL provide that authenticates the user and getName() is the name of the Realm. I do have two different Realms in play - legacy and non-legacy. Could that be causing a problem?

With various break points, I can tell that the first subject is generated correctly and seems to be saved to the session correctly. The second subject is generated incorrectly because the session (same session ID, I checked) does not have a Principal (even though it does have an Authenticated value of true).

I've not had any luck figuring out what code is removing the Principal from the session, so I'm hoping for some pointers or debugging ideas. Setting a break point SessionDAO.upgdate(Session) has not proven helpful.


Solution

  • Ultimately, we tracked down the problem to a race condition where our Web Applications that are broadcasting changes to each other. An application that broadcast a change would also end up reading its own change. This didn't always happen in the order expected, resulting in a race condition that sometimes got us into the strange state described in the question.

    The solution we implemented was to mark the source of each broadcast, so the source would ignore its own broadcasts.

    While this solution is probably not directly helpful to others, I'm posting it here for completeness sake and to show that it was not a problem with Shiro.