0

I am using httpinvoker in JBoss 4.0.4 (little old) for EJB invocations. Since there are so many clients that make calls to my server, I want to identify the clients for each call in server.

Is there a way to do this with JBoss httpinvoker?

I could imagine adding a header to identify my client in each HTTP request, but cannot find a way to add a header in httpinvoker.

Beryllium
  • 12,808
  • 10
  • 56
  • 86
Suraj Chandran
  • 24,433
  • 12
  • 63
  • 94

1 Answers1

1

Auditing builds on a name, and thus on an authentication scheme somehow.

Therefore I suggest using the standard client authentication infrastructure to solve your problem. This works for RMI as well (it's not bound to HTTP), and the user ID is even passed down into your EJBs.

Server

  • Put the EJB in a security-domain (ejb.jar: META-INF/jboss.xml)
  • You could use the application-policy other which just the UsersRolesLoginModule (conf/login-config.xml); this is the default policy, it's already configured.
  • Add users.properties and roles.properties to your ejb.jar file (top level package): These are used by the UsersRolesLoginModule
  • For each user, add his name and a (dummy) password to users.properties

Client

  • Create a callback class which implements a javax.security.auth.callback.CallbackHandler: This callback is used, when the authentication needs the user and the password.
  • Create a javax.security.auth.login.LoginContext; pass the callback handler as the 2nd argument; call login() on the instance of the LoginContext
  • Connect normally to the EJB server using an InitialContext
  • Add -Djava.security.auth.login.config=.../jboss-4/client/auth.conf when you start the client

This way a user ID is passed from the client to the EJB (as part of the standard authentication process). Now, in the EJB methods, you can get the user ID by calling getCallerPrincipal() on the SessionContext instance. I have tested this against JBoss 4.2.3

Additional information: JBoss client authentication


Addendum 1:

Using RMI or HTTP, the password is not transported in a secure way. In this case just use a dummy password, this is OK for auditing.

On the other hand, if you use RMI over SSL or HttpInvoker over HTTPS, you could change to a real and secure authentication quickly.


Addendum 2:

I am not sure, if it works without defining roles. Possibly you have to

  • Add a line in roles.properties for each user: Add a connect role, for example
  • Add role definitions in ejb-jar.xml as well: security-role-ref for each EJB, and security-role and method-permission in the assembly-descriptor

Update

As there is already a login module, there might be another possibility:

If you have the source code of the login module, you could possibly use another TextCallback to get additional information from the client (in your case a user ID). The information could be used to create a custom Principal. Within the EJB, the result of getCallerPrincipal() could be cast to the custom principal.

Beryllium
  • 12,808
  • 10
  • 56
  • 86
  • Thank you Beryllium. We kind of have this solution already. But we use the same (or atleast each group uses the same) userId. The problem is that there are multiple instances(mirror images) of same app running and we can't have a new user id for each. Its not scalable. We have a significant number of servers and growing at a fast speed. – Suraj Chandran Jul 24 '13 at 12:51
  • @Suraj Chandran In that case I suggest creating a dummy LoginModule which lets pass everything. This way the clients can generate an UUID or provide any user ID. As an alternative, if there is already data in a RDBMS/LDAP, consider using/implementing a LoginModule against these databases. – Beryllium Jul 24 '13 at 13:00
  • @Berryllium The current login module is based on Kerberos, which is required for security, ofcourse. But do you mean that I add an additional login module(along with the existing one) that can take dummy credentials, and from the server side I get the principal for both login modules? Is that even possible? – Suraj Chandran Jul 24 '13 at 15:55
  • @Suraj Chandran If you already have a login module, can you use the result of `getCallerPrincipal`? Login modules can be stacked ("password stacking"), but I cannot tell, if this solves your problem. There is the possibility to use a custom principal class (can be set for a login module), but again I'm not sure whether this helps: It could be used to carry around information. Last ideas: Weave in some code using aspectj. If nothing helps, you could dig into the source. – Beryllium Jul 24 '13 at 20:26
  • @Suraj Chandran If you have the source code of the login module, there might be another possibility (I have added an update to the question). This might even work, if login modules are stacked. – Beryllium Jul 24 '13 at 21:34