Adding custom context information to EJB method calls

bernie picture bernie · Nov 5, 2011 · Viewed 11.3k times · Source

I want to pass authentication information to EJB stateless session beans when calling their methods from a Java web application (Wicket). The information consists of a user id and an authentication type (remember cookie or user/password) and is stored in the http session. One obvious solution is to add this as a parameter to all EJB methods, but this is cumbersome and I hope another solution exists.

The JNDI lookup of EJB beans is done via javax.naming.InitialContext#lookup(String) in the web tier.

Is there a portable way to add the authentication information to a calling context so it becomes available to the beans? I need this process to be available for callers both in the EJB layer (for an eventual web service endpoint) and in the web tier.

Some more information

I am using Java EE 6. CDI is not used and I would rather avoid implementing it.

Authentication is handled by the web tier with stateless beans validating remember cookies and user/password combinations. When a visitor first accesses the site, authentication with the remember cookie is tried. When eventually required, the user is asked to login with a username and password. As mentioned above, the authentication status is stored in the http session. I don’t use the Java EE security model based on realms because I couldn’t figure out how this authentication flow could be properly integrated.

The authorization scheme is based on dynamic roles similar to how Facebook determines authorization based on the link between 2 users and some preferences. Some actions also take into account the authentication type. For instance, modifying account settings requires user/password and the cookie is not enough. From what I understood, the Java EE standard groups and roles are not a good fit for this requirement.

Other related questions I found

EJB3 & How JAAS subject/principal is propagated to EJB Tier from servlet container?

Controlling the security Principle passed on a EJB call

Binding a User entity and a GlassFish Principal

Accessing the clients principal inside an ejb method

dynamic roles on a Java EE server

I hope my question is clear enough. If more information is required, I will gladly provide it.

edit

Fixed links. Add note about CDI.

Answer

Piotr Nowicki picture Piotr Nowicki · Nov 5, 2011

I think you should consider:

  1. Creating an interceptor for the authorization process. It will give you a common place for authorization despite from which layer the call was made from. You might check if the caller is allowed to invoke the method or if his session is still active (i.e. check it in the DB).

  2. In the interceptor you could pass some user-related data using InvocationContext#getContextData().put("user-related-data-name", someObj). In the caller EJB you can get this data using SessionContext#getContextData().

An example of passing contextual data using SessionContext can be found here

The last (and most interesting part) would be how to get the user credentials on the EJB layer. If you're saying about WebServices endpoint than I guess you need to provide some kind of boundary class or specify a methods which will take some sessionId for each call.

If it's about propagating HttpSession data from the Servlet to the EJB... It might be a long shot but I would think of using the CDI. Your Servlet might use a @SessionScoped bean which holds the user credentials and you inject the same @SessionScoped bean inside the interceptor.

I'm not sure if it's possible at all (injecting CDI beans in the interceptors or sharing @SessionScoped between Servlets and EJB's layers).