• Post Reply Bookmark Topic Watch Topic
  • New Topic

Keeping track of current user in Stateless EJBs and POJOs invoked by remote call  RSS feed

 
David Sharpe
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am working with a case where a remote client is invoking my Stateless EJB:



The remote client passes in the user ID of the user making the request so that my application can determine whether the user has permission to do the thing it is trying to do. My application is not responsible for authentication, just authorization, so we trust the remote client. To emphasize, this is not container-managed auth-auth. While the application technically has many users, as far as it's concerned there is only one user: the remote client.

The problem is that the permissions are extremely fine-grained. Permissions are checked multiple times in multiple ways by the services interested in different aspects: "myService.addThing" will call other EJBs and validations, which may in turn call still more, and all of these modules may be interested in the user making the request so that they can check specific, fine-grained permissions.

I need a way for these Stateless EJBs and POJOs to know who the current user is. The most straight-forward thing for me to do would be to just add a "user" parameter to many methods in the system so that it can be passed-in. I could also encapsulate "thing" and "user" in a single object to pass-around. But authorization is usually treated as a cross-cutting concern, so it feels wrong to add a "user" parameter to so many methods. Is there some conventional way I can inject the user into any EJB or POJO that needs it? I was thinking of something like a Producer, but as a Stateless EJB has no concept of session I don't see how that could work. I also don't think a Stateful EJB is suitable because I don't need to maintain conversational state with the remote client: it's mostly fire-and-forget.
 
Rob Spoor
Sheriff
Posts: 20895
81
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was going to suggest using EJBContext and its getCallerPrincipal() method, but you mentioned not you don't use container managed auth/auth.

You said you don't want to use Producer because a stateless bean has no notion of sessions. While that is true, you don't need to worry about it. You can inject an instance of a class annotated with @SessionScoped (use the version from javax.enterprise.context, not javax.faces.bean though) and the EJB container should take care of injecting the correct value.
 
David Sharpe
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was going to suggest using EJBContext and its getCallerPrincipal() method, but you mentioned not you don't use container managed auth/auth.


That's right. The remote client that is calling my EJB has performed authentication (it might even be container managed, I don't know), and my application trusts the remote client.

You said you don't want to use Producer because a stateless bean has no notion of sessions. While that is true, you don't need to worry about it. You can inject an instance of a class annotated with @SessionScoped (use the version from javax.enterprise.context, not javax.faces.bean though) and the EJB container should take care of injecting the correct value.


This surprises me. javax.enterprise.context.SessionScoped:

Specifies that a bean is session scoped.

The session scope is active:

  • during the service() method of any servlet in the web application, during the doFilter() method of any servlet filter and when the container calls any HttpSessionListener, AsyncListener or ServletRequestListener.


  • The session context is shared between all servlet requests that occur in the same HTTP session. The session context is destroyed when the HTTPSession times out, after all HttpSessionListeners have been called, and at the very end of any request in which invalidate() was called, after all filters and ServletRequestListeners have been called.


    The Javadoc seems to state that the session scope is active only during HTTP sessions. The remote client is using Java RMI, so there is no HTTP session.

    I see that isn't clear in my original post, which I cannot edit. I'll emphasize it here for other readers: the remote client is invoking my EJB using Java RMI, so there is no HTTP session.
     
    Rob Spoor
    Sheriff
    Posts: 20895
    81
    Chrome Eclipse IDE Java Windows
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sorry, I didn't get that the client was an RMI client. Then no, you don't have @SessionScoped or @RequestScoped.

    How does the remote client identify itself during all of the calls?
     
    David Sharpe
    Ranch Hand
    Posts: 36
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I'm not sure, unfortunately. I am not directly responsible for that. I asked the person who was, and he says he's not sure (yet) either. Our security requirements for the communication between the one remote client and my application are quite simple. There is only one remote client of my application, so the intention was for both of us to hold some kind of client certificate. I'm not sure communication will even happen over SSL, because it's all internal. I'm sorry I'm not more knowledgable.

    Maybe I'm overthinking this. My API should just be:



    Where Message encapsulates the "thing" and the "user".

    I still seems a bit wrong though; it seems that Stateless or not, HTTP or not, there is still an implicit "session" here. For example, the call to the EJB is transactional (container-managed): there is only one transaction for each call. It seems that the transaction has a sort of session or scope, so I thought I could devise something to emulate this for the "user" variable, maybe even attach a variable to the transaction if that's not a horrible idea.
     
    David Sharpe
    Ranch Hand
    Posts: 36
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    If anyone's interested, I majorly revised this question and posted it on StackOverflow here. It's might be too broad for SO, but I hope not!
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!