I've attached patches for geronimo/openejb2 trunk to GERONIMO-2313 that fix this problem, but I'd prefer to get some review before I apply them.

thanks
david jencks

On Aug 10, 2006, at 2:47 PM, David Jencks wrote:

A user noticed that when their web app called an ejb, despite the authentication of the user in the web app, in the ejb isCallerinRole always returns false. I've been investigating this and think we have some problems in how we handle run-as identities and the ContextManager currentCaller and nextCaller values. I'm also not sure where our defaultSubject idea fits into this. I'll try to summarize my understanding of the specs and what we should be doing, and make a bit of a proposal.

I'd really appreciate some review of how I think its supposed to work and comments on my proposal. I'm working on a patch to implement the proposal, but I believe we have to do something since what we do now appears to be broken.

web apps (2.4 spec):
SRV.12.3 states that the getRemoteUser, isUserInRole, and getUserPrincipal methods should return null, false, and null if there is no authenticated user. Following the specs' usual policy of not discussing cross context dispatch, we are left to guess that even if a run-as role is specified somewhere the target of a cross- context dispatch should continue to return null, false, null with no actual authenticated user.

SRV.12.7 states that if a run-as element is specified, all calls from any servlet in the application to an ejb must be done under a subject associated with the run-as role.

The spec does not seem to account for the possiblity that calls to ejbs could be done either pre- or post- user authentication: if a run-as role is specified, all calls will be made using it whether or not the user is authenticated.

We've introduced the concept of a defaultSubject that is used if the user is not authenticated, but will not interfere with using the users actual identity when the user is authenticated. IIUC (I haven't tested) currently the default subject is used in a way that interferes with the "null, false, null" requirements for getRemoteUser, isUserInrole, and getUserPrincipal.


ejbs: (2.1 spec)
21.3.4.1 indicates that the run-as identity specified for an ejb does not affect any security decisions for the ejb itself, but only specifies the identity to be used when it is calling other ejbs ( I need to check which identity is used use with resource adapters using container managed security). Methods such as isCallerInRole use the caller's identity, not the run-as identity (21.2.5.1)

----------------

We're keeping track of these two identities in ContextManager currentCaller and nextCaller (threadLocals). All security decisions are based on the currentCaller value. When a run-as value is specified for an ejb, it's put into the nextCaller. When an ejb is called, the nextCaller value is shifted into the currentCaller: this is supposed to occur before the run-as is put into the nextCaller.

My understanding of the requirements is that we should be:
- when a web user is authenticated we should put the subject into currentCaller and nextCaller. The currentCaller value will be used for security decisions in the web app, and the nextCaller value for security decisions on any ejbs it calls.

- when a run-as role is specified for a web app we put the subject associated with the run-as role into nextCaller (whether or not the current user is authenticated)

- cross context dispatch may replace the nextCaller if run-as is specified for the target, and the previous nextCaller value needs to be restored on return. This can never affect currentCaller.

- defaultSubject (a non-spec concept) should be put into both currentCaller and nextCaller unless run-as is specifed in which case run-as goes in the nextCaller.

----------------

Currently the web security stuff is pretty much ignoring nextCaller which is causing the authenticated user to be lost in ejb calls: this causes the problem the user reported. I'm mystified as to how the tck passes.

----------------

I think that perhaps we should organize this information into one object with more explicit operations on the ContextManager:

class Callers {
Subject currentCaller;
Subject nextCaller;
}

in ContextManager:

void setCallers(Subject currentCaller, Subject nextCaller)

//called for servlet cross context dispatch to set the target app run-as identity
Callers setNextCaller(Subject nextCaller);

//called for ejb call to shift the next caller to current caller and set the next caller to the run-as subject. // We need either another method with no params for the "no run-as" case or if null is suppled the nextCaller is not changed
Callers pushNextCaller(Subject nextCaller);

//called on return from an ejb call or servlet-cross-context-dispatch.
void popCallers(Callers oldCallers);

This would reduce the number of thread locals in ContextManager by at least one.


Thanks
david jencks


Reply via email to