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.
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.
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.
Fixed links. Add note about CDI.
I think you should consider:
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).
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).